reloc->howto = &reloc_howtos[RELOC_TYPE_PC32];
break;
+
+ default:
+
+ /* There is no point in continuing, the object is broken. */
+ report_at (program_name, 0, REPORT_FATAL_ERROR, "invalid relocation type 0x%04hx (origin object '%s')", array_to_integer (input->Type, 2), part->of->filename);
+ exit (EXIT_FAILURE);
}
#define IMAGE_SYM_DEBUG -2
#define IMAGE_SYM_UNDEFINED 0
+#define IMAGE_SYM_ABSOLUTE 1
#define IMAGE_SYM_CLASS_EXTERNAL 2
void read_coff_object (const char *filename, unsigned char *data, unsigned long data_size) {
unsigned long i;
struct section_part *bss_part = 0;
- long bss_section_number;
+ struct section *bss_section = 0;
+
+ long bss_section_number = 0;
if ((pos - data + sizeof (*coff_hdr) > data_size) || pos < data) {
for (i = 0; i < no_sections; i++) {
- section_hdr = (struct coff_section_table_entry *) ((unsigned char *) data + sizeof (struct coff_header) + sizeof (struct coff_section_table_entry) * i);
-
- if ((array_to_integer (section_hdr->Characteristics, 4) & IMAGE_SCN_LNK_REMOVE)) {
-
- part_p_array[i + 1] = 0;
- continue;
-
- }
-
+ section_hdr = (struct coff_section_table_entry *) (pos = (unsigned char *) data + sizeof (struct coff_header) + sizeof (struct coff_section_table_entry) * i);
section_name = xstrndup (section_hdr->Name, 8);
if (section_name[0] == '/') {
*p++ = '\0';
}
+ if (array_to_integer (section_hdr->Characteristics, 4) & IMAGE_SCN_LNK_REMOVE) {
+
+ part_p_array[i + 1] = 0;
+
+ free (section_name);
+ continue;
+
+ }
+
section = section_find_or_make (section_name);
section->flags = translate_Characteristics_to_section_flags (array_to_integer (section_hdr->Characteristics, 4));
section->is_bss = 1;
}
- subsection = (p ? subsection_find_or_make (section, p) : 0);
+ if (p) {
+ subsection = subsection_find_or_make (section, p);
+ } else {
+ subsection = 0;
+ }
+
free (section_name);
part = section_part_new (section, of);
}
+ if (section->is_bss) {
+
+ bss_section_number = i + 1;
+ bss_section = section;
+
+ }
+
if (array_to_integer (section_hdr->PointerToRelocations, 4) && array_to_integer (section_hdr->NumberOfRelocations, 2)) {
unsigned long j, no_relocs;
struct symbol_table_entry *coff_symbol;
struct symbol *symbol = of->symbol_arr + i;
- int section_no, no_sections;
+ short section_no, no_sections;
coff_symbol = (struct symbol_table_entry *) ((unsigned char *) data + array_to_integer (coff_hdr->PointerToSymbolTable, 4) + sizeof (struct symbol_table_entry) * i);
if (memcmp (coff_symbol->Name, "\0\0\0\0", 4) == 0) {
symbol->name = xstrndup ((char *) coff_symbol->Name, 8);
}
+ section_no = array_to_integer (coff_symbol->SectionNumber, 2);
+
symbol->value = array_to_integer (coff_symbol->value, 4);
- symbol->section_number = array_to_integer (coff_symbol->SectionNumber, 2);
+ symbol->size = 0;
+ symbol->section_number = section_no;
- section_no = array_to_integer (coff_symbol->SectionNumber, 2);
no_sections = array_to_integer (coff_hdr->NumberOfSections, 2);
- if (symbol->section_number == IMAGE_SYM_UNDEFINED) {
+ if (section_no == IMAGE_SYM_UNDEFINED) {
if (symbol->value) {
- if (!bss_part) {
+ struct symbol *old_symbol = symbol_find (symbol->name);
+
+ if (!old_symbol || symbol_is_undefined (old_symbol)) {
- struct section *section = section_find_or_make (".bss");
+ if (bss_section) {
- section->flags = translate_Characteristics_to_section_flags (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE);
- section->is_bss = 1;
+ bss_section = section_find_or_make (".bss");
+
+ bss_section->flags = translate_Characteristics_to_section_flags (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE);
+ bss_section->is_bss = 1;
+
+ bss_section_number = array_to_integer (coff_hdr->NumberOfSections, 2) ? array_to_integer (coff_hdr->NumberOfSections, 2) : 1;
- bss_section_number = array_to_integer (coff_hdr->NumberOfSections, 2) ? array_to_integer (coff_hdr->NumberOfSections, 2) : 1;
+ }
- bss_part = section_part_new (section, of);
- bss_part->content_size = 0;
+ bss_part = section_part_new (bss_section, of);
+ section_append_section_part (bss_section, bss_part);
- section_append_section_part (section, bss_part);
+ bss_part->content_size = symbol->size - symbol->value;
+
+ symbol->part = bss_part;
+ symbol->value = 0;
+ symbol->section_number = bss_section_number;
- }
+ } else {
- bss_part->content_size += symbol->value;
- symbol->part = bss_part;
+ if (symbol->value > old_symbol->size) {
+ old_symbol->part->content_size = old_symbol->size = symbol->value;
+ }
+
+ symbol->value = 0;
+ symbol->part = 0;
- symbol->value = bss_part->content_size - symbol->value;
- symbol->section_number = bss_section_number;
+ }
} else {
symbol->part = 0;
} else if (section_no > 0 && section_no <= no_sections) {
symbol->part = part_p_array[section_no];
- } else if (section_no == IMAGE_SYM_UNDEFINED || section_no == IMAGE_SYM_DEBUG) {
+ } else if (section_no == IMAGE_SYM_ABSOLUTE || section_no == IMAGE_SYM_DEBUG) {
+
+ symbol->section_number = section_no;
symbol->part = 0;
+
} else if (section_no > no_sections) {
report_at (program_name, 0, REPORT_ERROR, "%s: invalid symbol SectionNumber: %hi", filename, section_no);
}
- symbol->section_number = section_no;
-
- if (coff_symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
+ if (coff_symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL || section_no == IMAGE_SYM_UNDEFINED) {
symbol_record_external_symbol (symbol);
}
if (coff_symbol->NumberOfAuxSymbols) {
- for (i++; coff_symbol->NumberOfAuxSymbols; coff_symbol->NumberOfAuxSymbols--) {
+ unsigned long j;
- symbol = of->symbol_arr + i;
+ for (j = 0; j < coff_symbol->NumberOfAuxSymbols; j++) {
+
+ symbol = of->symbol_arr + i + 1 + j;
memset (symbol, 0, sizeof (*symbol));
symbol->auxiliary = 1;
}
+
+ i += coff_symbol->NumberOfAuxSymbols;
}
#define ALREADY_READ "Already read"
+static void read_archive_memeber (unsigned char *pos, const char *filename) {
+
+ struct ar_header *hdr = (struct ar_header *) pos;
+
+ char *temp, *name;
+ unsigned long data_size;
+
+ if (memcmp (pos, ALREADY_READ, sizeof (ALREADY_READ)) == 0) {
+ return;
+ }
+
+ hdr = (struct ar_header *) pos;
+
+ temp = xstrndup (hdr->name, sizeof (hdr->name));
+ strip_trailing_spaces (temp);
+
+ if (temp) {
+
+ unsigned long member_name_len = strlen (temp);
+
+ if (member_name_len && temp[member_name_len - 1] == '/' && temp[0] != '/') {
+ temp[member_name_len - 1] = '\0';
+ }
+
+ }
+
+ name = xmalloc (strlen (filename) + 1 + strlen (temp) + 1 + 1);
+ sprintf (name, "%s(%s)", filename, temp);
+
+ free (temp);
+
+ temp = xstrndup (hdr->size, sizeof (hdr->size));
+ strip_trailing_spaces (temp);
+
+ data_size = strtoul (temp, NULL, 10);
+ free (temp);
+
+ read_object_file (name, pos + sizeof (*hdr), data_size);
+ free (name);
+
+ memcpy (pos, ALREADY_READ, sizeof (ALREADY_READ));
+
+}
+
static void read_archive (const char *filename, unsigned char *data) {
unsigned char *pos = data + 8;
- struct ar_header *hdr = (struct ar_header *) pos;
+ struct ar_header *hdr = (struct ar_header *) pos;
struct offset_name_table *offset_name_table;
- char *name, *temp, *string_table_pos;
- unsigned long no_symbols, data_size, i;
+ char *string_table_pos, *name;
+ unsigned long no_symbols, i;
+
+ unsigned long start_header_object_offset = 0;
+ unsigned long end_header_object_offset = 0;
name = xstrndup (hdr->name, sizeof (hdr->name));
strip_trailing_spaces (name);
for (i = 0; i < no_symbols; i++) {
offset_name_table[i].offset = byte_array_to_integer (pos, 4, 1);
- pos += 4;
-
offset_name_table[i].name = (char *) string_table_pos;
+
string_table_pos += strlen (offset_name_table[i].name) + 1;
+ pos += 4;
+
+ }
+
+ for (i = 0; i < no_symbols && (!start_header_object_offset || !end_header_object_offset); i++) {
+ if (strncmp (offset_name_table[i].name, "__head_", 7) == 0) {
+ start_header_object_offset = offset_name_table[i].offset;
+ } else if (strlen (offset_name_table[i].name) > 6 && strcmp (offset_name_table[i].name + strlen (offset_name_table[i].name) - 6, "_iname") == 0) {
+ end_header_object_offset = offset_name_table[i].offset;
+ }
+
+ }
+
+ if (start_header_object_offset) {
+ read_archive_memeber (data + start_header_object_offset, filename);
}
while (1) {
continue;
}
- pos = data + offset_name_table[i].offset;
-
- if (memcmp (pos, ALREADY_READ, sizeof (ALREADY_READ)) == 0) {
+ if (offset_name_table[i].offset == start_header_object_offset || offset_name_table[i].offset == end_header_object_offset) {
continue;
}
- hdr = (struct ar_header *) pos;
-
- temp = xstrndup (hdr->name, sizeof (hdr->name));
- strip_trailing_spaces (temp);
-
- if (temp) {
-
- unsigned long member_name_len = strlen (temp);
-
- if (member_name_len && temp[member_name_len - 1] == '/' && temp[0] != '/') {
- temp[member_name_len - 1] = '\0';
- }
-
- }
-
- name = xmalloc (strlen (filename) + 1 + strlen (temp) + 1 + 1);
- sprintf (name, "%s(%s)", filename, temp);
-
- free (temp);
-
- temp = xstrndup (hdr->size, sizeof (hdr->size));
- strip_trailing_spaces (temp);
-
- data_size = strtoul (temp, NULL, 10);
- free (temp);
-
- read_object_file (name, pos + sizeof (*hdr), data_size);
- free (name);
-
- memcpy (pos, ALREADY_READ, sizeof (ALREADY_READ));
+ read_archive_memeber (data + offset_name_table[i].offset, filename);
change = 1;
}
}
+ if (end_header_object_offset) {
+ read_archive_memeber (data + end_header_object_offset, filename);
+ }
+
free (offset_name_table);
}
}
- sections_destroy_empty_before_collapse ();
-
if (state->format == LD_FORMAT_I386_COFF) {
coff_before_link ();
} else if (state->format == LD_FORMAT_I386_PE) {
struct reloc_howto reloc_howtos[RELOC_TYPE_END] = {
- { 0, 0, 0, 0, 0, "RELOC_TYPE_IGNORED", 0, 0 },
+ { 0, 0, 0, 0, 0, "RELOC_TYPE_IGNORED", 0, 0 },
- { 8, 0, 0, 0, 0, "RELOC_TYPE_64", 0, 0 },
- { 8, 1, 0, 0, 0, "RELOC_TYPE_PC64", 0, 0 },
+ { 8, 0, 0, 0, 0, "RELOC_TYPE_64", 0, 0 },
+ { 4, 0, 0, 0, 0, "RELOC_TYPE_32", 0, 0 },
+ { 2, 0, 0, 0, 0, "RELOC_TYPE_16", 0, 0 },
+ { 1, 0, 0, 0, 0, "RELOC_TYPE_8", 0, 0 },
- { 4, 0, 0, 0, 0, "RELOC_TYPE_32", 0, 0 },
- { 4, 1, 0, 0, 0, "RELOC_TYPE_PC32", 0, 0 },
+ { 8, 1, 0, 0, 0, "RELOC_TYPE_PC64", 0, 0 },
+ { 4, 1, 0, 0, 0, "RELOC_TYPE_PC32", 0, 0 },
+ { 2, 1, 0, 0, 0, "RELOC_TYPE_PC16", 0, 0 },
+ { 1, 1, 0, 0, 0, "RELOC_TYPE_PC8", 0, 0 },
- { 2, 0, 0, 0, 0, "RELOC_TYPE_16", 0, 0 },
- { 2, 1, 0, 0, 0, "RELOC_TYPE_PC16", 0, 0 },
-
- { 1, 0, 0, 0, 0, "RELOC_TYPE_8", 0, 0 },
- { 1, 1, 0, 0, 0, "RELOC_TYPE_PC8", 0, 0 }
+ { 4, 0, 1, 0, 0, "RELOC_TYPE_32_NO_BASE", 0, 0 }
};
part = section_part_new (section, object_file_make (FAKE_LD_FILENAME, 0));
- part->content_size = sizeof (struct pe_import_directory_table);
- part->content = xmalloc (part->content_size);
-
+ part->content = xmalloc (part->content_size = sizeof (struct pe_import_directory_table));
subsection_append_section_part (subsection, part);
if (!(subsection = subsection_find (section, "5"))) {
return;
}
- iat_first_part = subsection->first_part;
-
- if (!iat_first_part) {
+ if (!(iat_first_part = subsection->first_part)) {
return;
}
- for (part = iat_first_part; ; part = part->next) {
-
- if (!part->next) {
- break;
- }
-
+ for (part = iat_first_part; part->next; part = part->next) {
+ ;
}
iat_last_part = part;
case 12:
/* IMPORT Address Table. */
- if ((section = section_find (".idata"))) {
+ if ((section = section_find (".idata")) && iat_first_part) {
write741_to_byte_array (idd->VirtualAddress, iat_first_part->rva);
- write741_to_byte_array (idd->Size, iat_first_part->rva + iat_last_part->content_size);
+ write741_to_byte_array (idd->Size, iat_last_part->rva + iat_last_part->content_size - iat_first_part->rva);
}
RELOC_TYPE_IGNORED,
RELOC_TYPE_64,
- RELOC_TYPE_PC64,
-
RELOC_TYPE_32,
- RELOC_TYPE_PC32,
-
RELOC_TYPE_16,
- RELOC_TYPE_PC16,
-
RELOC_TYPE_8,
+
+ RELOC_TYPE_PC64,
+ RELOC_TYPE_PC32,
+ RELOC_TYPE_PC16,
RELOC_TYPE_PC8,
RELOC_TYPE_32_NO_BASE,
static struct section *discarded_sections = 0;
-struct object_file *object_file_make (const char *filename, unsigned long symbol_cnt) {
+struct object_file *object_file_make (const char *filename, unsigned long symbol_count) {
struct object_file *of = xmalloc (sizeof (*of));
-
of->filename = xstrdup (filename);
- of->symbol_arr = symbol_cnt ? xmalloc (sizeof (*of->symbol_arr) * symbol_cnt) : 0;
- of->symbol_cnt = symbol_cnt;
+ of->symbol_arr = symbol_count ? xmalloc (sizeof (*of->symbol_arr) * symbol_count) : 0;
+ of->symbol_cnt = symbol_count;
*last_object_file_p = of;
last_object_file_p = &of->next;
void sections_destroy_empty_before_collapse (void) {
struct section *section, **next_p;
-
struct section_part *part;
+
struct subsection *subsection;
for (next_p = &all_sections, section = *next_p; section; section = *next_p) {
for (part = section->first_part; part; part = part->next) {
- if (part->content_size > 0) {
-
- memcpy (memory, part->content, part->content_size);
- memory += part->content_size;
-
- }
+ memcpy (memory, part->content, part->content_size);
+ memory += part->content_size;
}
subsection = xmalloc (sizeof (*subsection));
subsection->name = xstrdup (name);
- subsection->next = *next_p;
subsection->last_part_p = &subsection->first_part;
+ subsection->next = *next_p;
*next_p = subsection;
}