#include "section.h"
#include "write7x.h"
+struct string_table_header {
+ unsigned char StringTableSize[4];
+};
+
+struct symbol_table_entry {
+
+ unsigned char Name[8];
+ unsigned char value[4];
+
+ unsigned char SectionNumber[2];
+ unsigned char Type[2];
+
+ unsigned char StorageClass;
+ unsigned char NumberOfAuxSymbols;
+
+};
+
+static void translate_relocation (struct reloc_entry *reloc, struct coff_relocation_entry *input, struct section_part *part) {
+
+ reloc->symbol = part->of->symbol_arr + array_to_integer (input->SymbolTableIndex, 4);
+ reloc->offset = array_to_integer (input->VirtualAddress, 4);
+
+ switch (array_to_integer (input->Type, 2)) {
+
+ case IMAGE_REL_I386_ABSOLUTE:
+
+ reloc->howto = &reloc_howtos[RELOC_TYPE_IGNORED];
+ break;
+
+ case IMAGE_REL_I386_DIR16:
+
+ reloc->howto = &reloc_howtos[RELOC_TYPE_16];
+ break;
+
+ case IMAGE_REL_I386_DIR32:
+
+ reloc->howto = &reloc_howtos[RELOC_TYPE_32];
+ break;
+
+ case IMAGE_REL_I386_DIR32NB:
+
+ reloc->howto = &reloc_howtos[RELOC_TYPE_32_NO_BASE];
+ break;
+
+ case IMAGE_REL_I386_REL16:
+
+ reloc->howto = &reloc_howtos[RELOC_TYPE_PC16];
+ break;
+
+ case IMAGE_REL_I386_REL32:
+
+ reloc->howto = &reloc_howtos[RELOC_TYPE_PC32];
+ break;
+
+ }
+
+}
+
+static unsigned long translate_Characteristics_to_alignment (unsigned long Characteristics) {
+
+ unsigned long alignment = 1;
+ Characteristics &= IMAGE_SCN_ALIGN_8192BYTES;
+
+ if (Characteristics == IMAGE_SCN_ALIGN_1BYTES) {
+ alignment = 1;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_2BYTES) {
+ alignment = 2;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_4BYTES) {
+ alignment = 4;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_8BYTES) {
+ alignment = 8;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_16BYTES) {
+ alignment = 16;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_32BYTES) {
+ alignment = 32;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_64BYTES) {
+ alignment = 64;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_128BYTES) {
+ alignment = 128;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_256BYTES) {
+ alignment = 256;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_512BYTES) {
+ alignment = 512;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_1024BYTES) {
+ alignment = 1024;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_2048BYTES) {
+ alignment = 2048;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_4096BYTES) {
+ alignment = 4096;
+ }
+
+ if (Characteristics == IMAGE_SCN_ALIGN_8192BYTES) {
+ alignment = 8192;
+ }
+
+ return alignment;
+
+}
+
+static unsigned long translate_Characteristics_to_section_flags (unsigned long Characteristics) {
+
+ unsigned long flags = 0;
+
+ if (!(Characteristics & IMAGE_SCN_MEM_WRITE)) {
+ flags |= SECTION_FLAG_READONLY;
+ }
+
+ if (Characteristics & (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE)) {
+ flags |= SECTION_FLAG_CODE;
+ }
+
+ if (Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
+ flags |= SECTION_FLAG_DATA;
+ }
+
+ if (Characteristics & IMAGE_SCN_TYPE_NOLOAD) {
+ flags |= SECTION_FLAG_NEVER_LOAD;
+ }
+
+ if (Characteristics & IMAGE_SCN_LNK_INFO) {
+ flags |= SECTION_FLAG_DEBUGGING;
+ }
+
+ if (Characteristics & IMAGE_SCN_LNK_REMOVE) {
+ flags |= SECTION_FLAG_EXCLUDE;
+ }
+
+ if (!(Characteristics & IMAGE_SCN_MEM_READ)) {
+ flags |= SECTION_FLAG_NOREAD;
+ }
+
+ if (Characteristics & IMAGE_SCN_MEM_SHARED) {
+ flags |= SECTION_FLAG_SHARED;
+ }
+
+ if (Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
+ flags |= SECTION_FLAG_ALLOC;
+ }
+
+ return flags;
+
+}
+
+#define IMAGE_SYM_DEBUG -2
+
+#define IMAGE_SYM_UNDEFINED 0
+#define IMAGE_SYM_CLASS_EXTERNAL 2
+
+void read_coff_object (const char *filename, unsigned char *data, unsigned long data_size) {
+
+ struct coff_header *coff_hdr;
+ struct coff_relocation_entry *reloc_info;
+
+ struct coff_section_table_entry *section_hdr;
+ struct string_table_header *string_table_hdr;
+
+ struct section_part **part_p_array, *part;
+ struct object_file *of;
+
+ struct section *section;
+ struct subsection *subsection;
+
+ char *string_table = 0, *section_name, *p;
+ unsigned long string_table_size, no_sections, no_syms;
+
+ unsigned char *pos = (unsigned char *) data;
+ unsigned long i;
+
+ struct section_part *bss_part = 0;
+ long bss_section_number;
+
+ if ((pos - data + sizeof (*coff_hdr) > data_size) || pos < data) {
+
+ report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: corrupted input file", filename);
+ return;
+
+ }
+
+ coff_hdr = (struct coff_header *) data;
+
+ pos = (unsigned char *) data + array_to_integer (coff_hdr->PointerToSymbolTable, 4) + sizeof (struct symbol_table_entry) * array_to_integer (coff_hdr->NumberOfSymbols, 4);
+ string_table_hdr = (struct string_table_header *) pos;
+
+ if ((string_table_size = array_to_integer (string_table_hdr->StringTableSize, 4)) < 4) {
+
+ report_at (program_name, 0, REPORT_ERROR, "%s: invalid string table size: %lu", filename, string_table_size);
+ return;
+
+ }
+
+ string_table = (char *) pos;
+
+ part_p_array = xmalloc (sizeof (*part_p_array) * (array_to_integer (coff_hdr->NumberOfSections, 2) + 1));
+ of = object_file_make (filename, array_to_integer (coff_hdr->NumberOfSymbols, 4));
+
+ no_sections = array_to_integer (coff_hdr->NumberOfSections, 2);
+
+ 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_name = xstrndup (section_hdr->Name, 8);
+
+ if (section_name[0] == '/') {
+
+ unsigned long offset = strtoul (section_name + 1, NULL, 10);
+
+ if (offset < array_to_integer (string_table_hdr->StringTableSize, 4)) {
+
+ free (section_name);
+ section_name = xstrdup (string_table + offset);
+
+ } else {
+ report_at (program_name, 0, REPORT_ERROR, "%s: invalid offset into string table", filename);
+ }
+
+ }
+
+ if ((p = strchr (section_name, '$'))) {
+ *p++ = '\0';
+ }
+
+ section = section_find_or_make (section_name);
+ section->flags = translate_Characteristics_to_section_flags (array_to_integer (section_hdr->Characteristics, 4));
+
+ if (array_to_integer (section_hdr->PointerToRawData, 4) == 0 && array_to_integer (section_hdr->SizeOfRawData, 4)) {
+ section->is_bss = 1;
+ }
+
+ subsection = (p ? subsection_find_or_make (section, p) : 0);
+ free (section_name);
+
+ part = section_part_new (section, of);
+ part->alignment = translate_Characteristics_to_alignment (array_to_integer (section_hdr->Characteristics, 4));
+ part->content_size = array_to_integer (section_hdr->SizeOfRawData, 4);
+
+ if (array_to_integer (section_hdr->PointerToRawData, 4)) {
+
+ pos = (unsigned char *) data + array_to_integer (section_hdr->PointerToRawData, 4);
+
+ part->content = xmalloc (part->content_size);
+ memcpy (part->content, pos, part->content_size);
+
+ }
+
+ if (array_to_integer (section_hdr->PointerToRelocations, 4) && array_to_integer (section_hdr->NumberOfRelocations, 2)) {
+
+ unsigned long j, no_relocs;
+
+ if (!array_to_integer (section_hdr->PointerToRawData, 4)) {
+
+ report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: section '%s' is BSS but has relocations", filename, section->name);
+ exit (EXIT_FAILURE);
+
+ }
+
+ pos = (unsigned char *) data + array_to_integer (section_hdr->PointerToRelocations, 4);
+
+ part->reloc_arr = xmalloc (sizeof (struct reloc_entry) * array_to_integer (section_hdr->NumberOfRelocations, 2));
+ part->reloc_cnt = array_to_integer (section_hdr->NumberOfRelocations, 2);
+
+ no_relocs = array_to_integer (section_hdr->NumberOfRelocations, 2);
+
+ for (j = 0; j < no_relocs; j++) {
+
+ reloc_info = (struct coff_relocation_entry *) (pos + (sizeof (*reloc_info) * j));
+ translate_relocation (part->reloc_arr + j, reloc_info, part);
+
+ }
+
+ }
+
+ if (subsection) {
+ subsection_append_section_part (subsection, part);
+ } else {
+ section_append_section_part (section, part);
+ }
+
+ part_p_array[i + 1] = part;
+
+ }
+
+ no_syms = array_to_integer (coff_hdr->NumberOfSymbols, 4);
+
+ for (i = 0; i < no_syms; i++) {
+
+ struct symbol_table_entry *coff_symbol;
+ struct symbol *symbol = of->symbol_arr + i;
+
+ int 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) {
+
+ unsigned long offset = array_to_integer (coff_symbol->Name + 4, 4);
+
+ if (offset < array_to_integer (string_table_hdr->StringTableSize, 4)) {
+ symbol->name = xstrdup (string_table + offset);
+ } else {
+
+ report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: invalid offset into string table", filename);
+ exit (EXIT_FAILURE);
+
+ }
+
+ } else {
+ symbol->name = xstrndup ((char *) coff_symbol->Name, 8);
+ }
+
+ symbol->value = array_to_integer (coff_symbol->value, 4);
+ symbol->section_number = array_to_integer (coff_symbol->SectionNumber, 2);
+
+ 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 (symbol->value) {
+
+ if (!bss_part) {
+
+ struct section *section = section_find_or_make (".bss");
+
+ 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_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;
+
+ section_append_section_part (section, bss_part);
+
+ }
+
+ bss_part->content_size += symbol->value;
+ symbol->part = bss_part;
+
+ 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) {
+ 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->part = 0;
+
+ } else {
+
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "+++not yet supported symbol SectionNumber: %hi", section_no);
+ exit (EXIT_FAILURE);
+
+ }
+
+ symbol->section_number = section_no;
+
+ if (coff_symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
+ symbol_record_external_symbol (symbol);
+ }
+
+ if (coff_symbol->NumberOfAuxSymbols) {
+
+ for (i++; coff_symbol->NumberOfAuxSymbols; coff_symbol->NumberOfAuxSymbols--) {
+
+ symbol = of->symbol_arr + i;
+
+ memset (symbol, 0, sizeof (*symbol));
+ symbol->auxiliary = 1;
+
+ }
+
+ }
+
+ }
+
+ free (part_p_array);
+
+}
+
+
struct exclude_symbol {
char *name;
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
#define IMAGE_SCN_LNK_INFO 0x00000200
#define IMAGE_SCN_LNK_REMOVE 0x00000800
+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
+#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
+#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
+#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
+#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
+#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
+#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
+#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
#define IMAGE_SCN_MEM_SHARED 0x10000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_REL_I386_DIR32NB 0x0007
#define IMAGE_REL_I386_REL32 0x0014
+void read_coff_object (const char *filename, unsigned char *data, unsigned long data_size);
+
void coff_after_link (void);
void coff_before_link (void);
static void read_object_file (const char *filename, unsigned char *data, unsigned long data_size) {
+ /*report_at (program_name, 0, REPORT_ERROR, "%s: signature: %#x:%#x", filename, data[0], data[1]);*/
/*printf ("reading: %s\n", filename);*/
if (data[0] == 0x01 && data[1] == 0x03) {
read_elks_object (filename, data, data_size);
} else if (data[0] == 0x07 && data[1] == 0x01) {
read_aout_object (filename, data, data_size);
+ } else if (data[0] == 0x4C && data[1] == 0x01) {
+ read_coff_object (filename, data, data_size);
} else if (data[0] == RECORD_TYPE_THEADR) {
read_omf_object (filename, data, data_size);
} else {
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);
}
+ sections_destroy_empty_before_collapse ();
+
if (state->format == LD_FORMAT_I386_COFF) {
coff_before_link ();
} else if (state->format == LD_FORMAT_I386_PE) {
static void estimate (void *data, unsigned long data_size, const char *filename, unsigned long *num_segments_p, unsigned long *num_extdefs_p, unsigned long *num_pubdefs_p, unsigned long *num_lnames_p) {
unsigned char *pos = (unsigned char *) data;
+ unsigned char base_segment_index;
unsigned char record_type;
unsigned short record_len;
} else if (record_type == RECORD_TYPE_PUBDEF) {
- pubdef_name_end = (pubdef_name = pos) + record_len - 3;
+ unsigned long prefix = 1;
+ unsigned long suffix = 2 + 1;
+
+ pubdef_name_end = pos + record_len - 1;
if (big_fields) {
+ suffix += 2;
+ }
- report_at (program_name, 0, REPORT_INTERNAL_ERROR, "%s: big fields not supported for record %#x", filename, record_type);
- exit (EXIT_FAILURE);
+ base_segment_index = pos[1];
+
+ if (!base_segment_index) {
+
+ report_at (program_name, 0, REPORT_WARNING, "%s: PUBDEF Base Frame is not supported", filename);
+ prefix += 2;
}
+ pubdef_name = pos + 2;
+
while (pubdef_name != pubdef_name_end) {
- pubdef_name_len = pubdef_name[2];
+ pubdef_name_len = pubdef_name[prefix - 1];
- if (pubdef_name + 2 + 1 + pubdef_name_len + 1 > pubdef_name_end) {
+ if (pubdef_name + prefix + pubdef_name_len + suffix > pubdef_name_end) {
report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: incorrect pubdef string length", filename);
exit (EXIT_FAILURE);
}
num_pubdefs++;
- pubdef_name = pubdef_name + 2 + 1 + pubdef_name_len + 1;
+ pubdef_name = pubdef_name + prefix + pubdef_name_len + suffix;
}
} else if (record_type == RECORD_TYPE_PUBDEF) {
- pubdef_name_end = (pubdef_name = pos) + record_len - 3;
- base_segment_index = pubdef_name[1];
+ unsigned long prefix = 1;
+ unsigned long suffix = 2 + 1;
- while (pubdef_name != pubdef_name_end) {
+ pubdef_name_end = pos + record_len - 1;
- pubdef_name_len = pubdef_name[2];
-
- public_offset = array_to_integer (pubdef_name + 3 + pubdef_name_len, 2);
- symbol = of->symbol_arr + i_extdefs++;
-
- if (base_segment_index >= i_segments || !base_segment_index) {
+ if (big_fields) {
+ suffix += 2;
+ }
- report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: invalid base segment index %d", filename, base_segment_index);
- exit (EXIT_FAILURE);
+ base_segment_index = pos[1];
+
+ if (!base_segment_index) {
+
+ report_at (program_name, 0, REPORT_WARNING, "%s: PUBDEF Base Frame is not supported", filename);
+ prefix += 2;
+
+ }
+
+ pubdef_name = pos + 2;
+
+ while (pubdef_name != pubdef_name_end) {
+
+ pubdef_name_len = pubdef_name[prefix - 1];
+ if (big_fields) {
+ public_offset = array_to_integer (pubdef_name + prefix + pubdef_name_len, 4);
+ } else {
+ public_offset = array_to_integer (pubdef_name + prefix + pubdef_name_len, 2);
}
- symbol->name = xstrndup ((char *) pubdef_name + 3, pubdef_name_len);
+ symbol = of->symbol_arr + i_pubdefs++;
+
+ symbol->name = xstrndup ((char *) pubdef_name + prefix, pubdef_name_len);
symbol->value = public_offset;
symbol->part = part_p_array[base_segment_index];
symbol->section_number = base_segment_index;
symbol_record_external_symbol (symbol);
- pubdef_name = pubdef_name + 2 + 1 + pubdef_name_len + 1;
+ pubdef_name = pubdef_name + prefix + pubdef_name_len + suffix;
}
unsigned long segment_len;
- if (!(attributes & SEGMENT_ATTR_P)) {
-
- report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: OMF USE16 segments are not supported", filename);
- exit (EXIT_FAILURE);
-
- }
-
if ((attributes >> 5) == 0) {
report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: OMF absolute segments are not supported", filename);
} else {
- report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "%s: non big fields not supported for record %#x", filename, record_type);
- exit (EXIT_FAILURE);
+ segment_len = array_to_integer (pos + 1, 2);
+
+ segment_name_index = pos[3];
+ class_name_index = pos[4];
}
- if (segment_name_index >= i_lnames || !segment_name_index) {
+ if (segment_name_index >= i_lnames || !segment_name_index) {
report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: invalid segment name index", filename);
exit (EXIT_FAILURE);
}
- if (class_name_index >= i_lnames || !class_name_index) {
+ if (class_name_index >= i_lnames || !class_name_index) {
report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: invalid class name index", filename);
exit (EXIT_FAILURE);
}
- if (!big_fields) {
-
- report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "%s: non big field not supported for record %#x", filename, record_type);
- exit (EXIT_FAILURE);
-
- }
-
while (subrec != end) {
if (subrec[0] & 0x80) {
unsigned char fixdat, frame_method, target_method;
unsigned short data_record_offset, target_datum;
- if (subrec[0] & 0x40) {
-
- report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "%s: only self-relative OMF fixups are supported", filename);
- exit (EXIT_FAILURE);
+ unsigned char loc;
+ int bits;
- }
+ /*seg_reloc = subrec[0] & 0x40;*/
+ loc = subrec[0] >> 2;
- if (((subrec[0] >> 2) & 0x0f) != 9) {
+ if ((loc & 0x0F) == 1) {
+ bits = 16;
+ } else if ((loc & 0x0F) == 9) {
+ bits = 32;
+ } else {
- report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "%s: only 32-bit offset OMF fixups are supported", filename);
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "%s: only 16-bit/32-bit offset OMF fixups are supported", filename);
exit (EXIT_FAILURE);
}
reloc->offset = data_record_offset;
reloc->addend = 0;
- reloc->howto = &reloc_howtos[RELOC_TYPE_PC32];
+
+ if (bits == 16) {
+ reloc->howto = &reloc_howtos[RELOC_TYPE_PC16];
+ } else {
+ reloc->howto = &reloc_howtos[RELOC_TYPE_PC32];
+ }
subrec += 4;
if (big_fields) {
offset = array_to_integer (pos + 1, 4);
+
size = record_len - 6;
data_bytes = pos + 5;
} else {
offset = array_to_integer (pos + 1, 2);
+
size = record_len - 4;
data_bytes = pos + 3;
#define RECORD_TYPE_FIXUPP 0x9C
#define RECORD_TYPE_LEDATA 0xA0
-#define SEGMENT_ATTR_P 0x1
+#define SEGMENT_ATTR_P 0x01
-#define METHOD_T2_EXTDEF 2
-#define METHOD_F5 5
+#define METHOD_T2_EXTDEF 0x02
+#define METHOD_F5 0x05
void read_omf_object (const char *filename, unsigned char *data, unsigned long data_size);
continue;
}
+ if (part->rva + relocs[i].offset < array_to_integer (ibr_hdr_p->RVAOfBlock, 4)) {
+ continue;
+ }
+
rel_word = (part->rva + relocs[i].offset - array_to_integer (ibr_hdr_p->RVAOfBlock, 4)) & 0xfff;
rel_word |= base_relocation_type << 12;
struct pe_optional_header *opthdr;
struct section *section;
+ unsigned long size_of_optional_header;
if (!(fp = fopen (filename, "wb"))) {
write_sections (data);
doshdr = (struct msdos_header *) data;
- pehdr = (struct pe_header *) ((char *) doshdr + sizeof (*doshdr) + sizeof (dos_stub));
+ pehdr = (struct pe_header *) ((char *) doshdr + sizeof (*doshdr) + sizeof (dos_stub));
opthdr = (struct pe_optional_header *) ((char *) pehdr + sizeof (*pehdr));
+
pos = (unsigned char *) opthdr + sizeof (*opthdr);
doshdr->e_magic[0] = 'M';
write721_to_byte_array (pehdr->Machine, IMAGE_FILE_MACHINE_I386);
write721_to_byte_array (pehdr->NumberOfSections, section_count ());
write741_to_byte_array (pehdr->TimeDateStamp, time (0));
- write721_to_byte_array (pehdr->SizeOfOptionalHeader, sizeof (*opthdr));
+
+ size_of_optional_header = sizeof (*opthdr);
+ size_of_optional_header += NUMBER_OF_DATA_DIRECTORIES * sizeof (struct pe_image_data_directory);
+ write721_to_byte_array (pehdr->SizeOfOptionalHeader, size_of_optional_header);
{
if (last_section) {
write741_to_byte_array (opthdr->SizeOfImage, ALIGN (last_section->rva + last_section->total_size, section_alignment));
} else {
- write741_to_byte_array (opthdr->SizeOfImage, state->size_of_headers);
+ write741_to_byte_array (opthdr->SizeOfImage, ALIGN (state->size_of_headers, section_alignment));
}
write741_to_byte_array (opthdr->SizeOfHeaders, state->size_of_headers);
write721_to_byte_array (opthdr->Subsystem, subsystem);
+ {
+
+ unsigned short characteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
+
+ if (can_be_relocated) {
+ characteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
+ }
+
+ write721_to_byte_array (opthdr->DllCharacteristics, characteristics);
+
+ }
+
{
struct section *bss_section;
write741_to_byte_array (opthdr->NumberOfRvaAndSizes, NUMBER_OF_DATA_DIRECTORIES);
+ {
+
+ struct pe_image_data_directory *idd;
+ int i;
+
+ for (i = 0; i < NUMBER_OF_DATA_DIRECTORIES; i++) {
+
+ idd = (struct pe_image_data_directory *) pos;
+
+ switch (i) {
+
+ case 0:
+
+ /* EXPORT Table. */
+ if ((section = section_find (".edata"))) {
+
+ write741_to_byte_array (idd->VirtualAddress, section->rva);
+ write741_to_byte_array (idd->Size, section->total_size);
+
+ }
+
+ break;
+
+ case 1:
+
+ /* IMPORT Table. */
+ if ((section = section_find (".idata"))) {
+
+ write741_to_byte_array (idd->VirtualAddress, section->rva);
+ write741_to_byte_array (idd->Size, section->total_size);
+
+ }
+
+ break;
+
+ case 5:
+
+ /* BASE RELOCATION Table. */
+ if ((section = section_find (".reloc"))) {
+
+ write741_to_byte_array (idd->VirtualAddress, section->rva);
+ write741_to_byte_array (idd->Size, section->total_size);
+
+ }
+
+ break;
+
+ case 12:
+
+ /* IMPORT Address Table. */
+ if ((section = section_find (".idata"))) {
+
+ 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);
+
+ }
+
+ break;
+
+ }
+
+ pos += sizeof (*idd);
+
+ }
+
+ }
+
+
for (section = all_sections; section; section = section->next) {
struct pe_section_table_entry *hdr = section->object_dependent_data;
#define IMAGE_SUBSYSTEM_XBOX 14
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPILCATION 16
+#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040
+#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
+
struct pe_header {
unsigned char Signature[4];
unsigned char LoaderFlags[4];
unsigned char NumberOfRvaAndSizes[4];
-
-
- /*unsigned char Reserved[128];*/
- unsigned char Reserved[32 * 4];
};
RELOC_TYPE_8,
RELOC_TYPE_PC8,
+ RELOC_TYPE_32_NO_BASE,
RELOC_TYPE_END
};
}
+struct subsection *subsection_find_or_make (struct section *section, const char *name) {
+
+ struct subsection *subsection, **next_p;
+
+ for (subsection = *(next_p = §ion->all_subsections); subsection; subsection = *(next_p = &subsection->next)) {
+
+ if (strcmp (name, subsection->name) <= 0) {
+ break;
+ }
+
+ }
+
+ if (!subsection || strcmp (name, subsection->name) != 0) {
+
+ subsection = xmalloc (sizeof (*subsection));
+
+ subsection->name = xstrdup (name);
+ subsection->next = *next_p;
+ subsection->last_part_p = &subsection->first_part;
+
+ *next_p = subsection;
+
+ }
+
+ return subsection;
+
+}
+
void subsection_append_section_part (struct subsection *subsection, struct section_part *part) {
*subsection->last_part_p = part;
int section_count (void);
struct subsection *subsection_find (struct section *section, const char *name);
+struct subsection *subsection_find_or_make (struct section *section, const char *name);
+
void subsection_append_section_part (struct subsection *subsection, struct section_part *part);
#endif /* _SECTION_H */