From: Robert Pengelly Date: Mon, 15 Jun 2026 08:46:16 +0000 (+0100) Subject: Added pe-amd64 in --oformat X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;p=slink.git Added pe-amd64 in --oformat --- diff --git a/coff.c b/coff.c index 5ce9ae3..e54e356 100644 --- a/coff.c +++ b/coff.c @@ -42,7 +42,7 @@ struct symbol_table_entry { }; -static void translate_relocation (struct reloc_entry *reloc, struct coff_relocation_entry *input, struct section_part *part) { +static void translate_relocation32 (struct reloc_entry *reloc, struct coff_relocation_entry *input, struct section_part *part) { uint16_t type; @@ -97,6 +97,78 @@ static void translate_relocation (struct reloc_entry *reloc, struct coff_relocat } +static void translate_relocation64 (struct reloc_entry *reloc, struct coff_relocation_entry *input, struct section_part *part) { + + uint16_t type; + + reloc->symbol = part->of->symbol_arr + array_to_integer (input->SymbolTableIndex, 4, 0); + reloc->offset = array_to_integer (input->VirtualAddress, 4, 0); + + type = array_to_integer (input->Type, 2, 0); + + switch (type) { + + case IMAGE_REL_AMD64_ABSOLUTE: + + reloc->howto = &reloc_howtos[RELOC_TYPE_IGNORED]; + break; + + case IMAGE_REL_AMD64_ADDR64: + + reloc->howto = &reloc_howtos[RELOC_TYPE_64]; + break; + + case IMAGE_REL_AMD64_ADDR32: + + reloc->howto = &reloc_howtos[RELOC_TYPE_32]; + break; + + case IMAGE_REL_AMD64_ADDR32NB: + + reloc->howto = &reloc_howtos[RELOC_TYPE_32_NO_BASE]; + break; + + case IMAGE_REL_AMD64_REL32: + + reloc->howto = &reloc_howtos[RELOC_TYPE_PC32]; + break; + + case IMAGE_REL_AMD64_REL32_1: case IMAGE_REL_AMD64_REL32_2: case IMAGE_REL_AMD64_REL32_3: + case IMAGE_REL_AMD64_REL32_4: case IMAGE_REL_AMD64_REL32_5: + + reloc->howto = &reloc_howtos[RELOC_TYPE_PC32]; + + { + + unsigned long field = array_to_integer (part->content + reloc->offset, 4, 0); + field -= array_to_integer (input->Type, 2, 0) - IMAGE_REL_AMD64_REL32; + + integer_to_array (field, part->content + reloc->offset, 4, 0); + + } + + break; + + case IMAGE_REL_AMD64_SECTION: case IMAGE_REL_AMD64_SECREL: case IMAGE_REL_AMD64_SECREL7: case IMAGE_REL_AMD64_TOKEN: + case IMAGE_REL_AMD64_SREL32: case IMAGE_REL_AMD64_PAIR: case IMAGE_REL_AMD64_SSPAN32: + + report_at (program_name, 0, REPORT_INTERNAL_ERROR, "+++relocation type 0x%04hx not supported yet", array_to_integer (input->Type, 2, 0)); + 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, 0), part->of->filename); + exit (EXIT_FAILURE); + + } + + if (reloc->symbol->section_number == IMAGE_SYM_CLASS_STATIC) { + reloc->n_type = reloc->symbol->section_number; + } + +} + static unsigned long translate_Characteristics_to_alignment (unsigned long Characteristics) { unsigned long alignment = 1; @@ -281,7 +353,7 @@ void read_coff_object (const char *filename, unsigned char *data, unsigned long *p++ = '\0'; } - if (state->format == LD_FORMAT_I386_PE && strcmp (section_name, ".drectve") == 0) { + if ((state->format == LD_FORMAT_I386_PE || state->format == LD_FORMAT_AMD64_PE) && strcmp (section_name, ".drectve") == 0) { pe_interpret_dot_drectve_section (/*filename, data, data_size, */data + array_to_integer (section_hdr->PointerToRawData, 4, 0), array_to_integer (section_hdr->SizeOfRawData, 4, 0)); @@ -357,7 +429,12 @@ void read_coff_object (const char *filename, unsigned char *data, unsigned long 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 (data[0] == 0x64 && data[1] == 0x86) { + translate_relocation64 (part->reloc_arr + j, reloc_info, part); + } else { + translate_relocation32 (part->reloc_arr + j, reloc_info, part); + } } diff --git a/coff.h b/coff.h index 8aa5fc0..bf71a23 100644 --- a/coff.h +++ b/coff.h @@ -99,6 +99,24 @@ struct coff_relocation_entry { }; +#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 +#define IMAGE_REL_AMD64_ADDR64 0x0001 +#define IMAGE_REL_AMD64_ADDR32 0x0002 +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define IMAGE_REL_AMD64_REL32 0x0004 +#define IMAGE_REL_AMD64_REL32_1 0x0005 +#define IMAGE_REL_AMD64_REL32_2 0x0006 +#define IMAGE_REL_AMD64_REL32_3 0x0007 +#define IMAGE_REL_AMD64_REL32_4 0x0008 +#define IMAGE_REL_AMD64_REL32_5 0x0009 +#define IMAGE_REL_AMD64_SECTION 0x000A +#define IMAGE_REL_AMD64_SECREL 0x000B +#define IMAGE_REL_AMD64_SECREL7 0x000C +#define IMAGE_REL_AMD64_TOKEN 0x000D +#define IMAGE_REL_AMD64_SREL32 0x000E +#define IMAGE_REL_AMD64_PAIR 0x000F +#define IMAGE_REL_AMD64_SSPAN32 0x0010 + #define IMAGE_REL_I386_ABSOLUTE 0x0000 #define IMAGE_REL_I386_DIR16 0x0001 #define IMAGE_REL_I386_REL16 0x0002 diff --git a/ld.c b/ld.c index 796e721..f5c8447 100644 --- a/ld.c +++ b/ld.c @@ -89,7 +89,7 @@ static int read_object_file (const char *filename, unsigned char *data, unsigned } - if (data[0] == 0x4C && data[1] == 0x01) { + if ((data[0] == 0x4C && data[1] == 0x01) || (data[0] == 0x64 && data[1] == 0x86)) { read_coff_object (filename, data, data_size); return 0; @@ -390,7 +390,7 @@ static void read_archive (const char *filename, unsigned char *data) { } - if (state->format == LD_FORMAT_I386_PE) { + if (state->format == LD_FORMAT_AMD64_PE || state->format == LD_FORMAT_I386_PE) { for (i = 0; i < num_symbols && (!start_header_object_offset || !end_header_object_offset); i++) { @@ -437,7 +437,7 @@ static void read_archive (const char *filename, unsigned char *data) { } - if (state->format == LD_FORMAT_I386_PE) { + if (state->format == LD_FORMAT_AMD64_PE || state->format == LD_FORMAT_I386_PE) { if (end_header_object_offset) { read_archive_memeber (data + end_header_object_offset, filename); @@ -529,7 +529,7 @@ int main (int argc, char **argv) { if (state->format == LD_FORMAT_COM) { state->base_address = 0x00000100; - } else if (state->format == LD_FORMAT_I386_PE) { + } else if (state->format == LD_FORMAT_AMD64_PE || state->format == LD_FORMAT_I386_PE) { if (state->create_shared_library) { state->base_address = 0x10000000; @@ -562,7 +562,7 @@ int main (int argc, char **argv) { dx_before_link (); } else if (state->format == LD_FORMAT_I386_ELKS) { elks_before_link (); - } else if (state->format == LD_FORMAT_I386_PE) { + } else if (state->format == LD_FORMAT_AMD64_PE || state->format == LD_FORMAT_I386_PE) { pe_before_link (); } else if (state->format == LD_FORMAT_AARCH64_MACHO || state->format == LD_FORMAT_AMD64_MACHO) { macho_before_link (); @@ -629,10 +629,15 @@ int main (int argc, char **argv) { elks_write (state->output_filename); } else if (state->format == LD_FORMAT_I386_ELF) { elf32_write (state->output_filename); - } else if (state->format == LD_FORMAT_I386_PE) { + } else if (state->format == LD_FORMAT_AMD64_PE || state->format == LD_FORMAT_I386_PE) { pe_after_link (); - pe_write (state->output_filename); + + if (state->format == LD_FORMAT_AMD64_PE) { + pe64_write (state->output_filename); + } else { + pe32_write (state->output_filename); + } } else if (state->format == LD_FORMAT_I386_COFF) { diff --git a/ld.h b/ld.h index 5cc67d1..14b5ad4 100644 --- a/ld.h +++ b/ld.h @@ -63,9 +63,10 @@ struct ld_state { #define LD_FORMAT_AMD64_MACHO (LD_TARGET_MACHINE_AMD64 | 0x11) #define LD_FORMAT_AMD64_ELF (LD_TARGET_MACHINE_AMD64 | 0x12) +#define LD_FORMAT_AMD64_PE (LD_TARGET_MACHINE_AMD64 | 0x13) -#define LD_FORMAT_AARCH64_MACHO (LD_TARGET_MACHINE_AARCH64 | 0x13) -#define LD_FORMAT_AARCH64_ELF (LD_TARGET_MACHINE_AARCH64 | 0x14) +#define LD_FORMAT_AARCH64_MACHO (LD_TARGET_MACHINE_AARCH64 | 0x14) +#define LD_FORMAT_AARCH64_ELF (LD_TARGET_MACHINE_AARCH64 | 0x15) extern struct ld_state *state; diff --git a/lib.c b/lib.c index aabed80..5a0f890 100644 --- a/lib.c +++ b/lib.c @@ -119,7 +119,8 @@ static void print_usage (void) { fprintf (stderr, " elf-amd64, elf-i386\n"); fprintf (stderr, " elks-ia16, elks-i386\n"); fprintf (stderr, " macho-aarch64, macho-amd64\n"); - fprintf (stderr, " pe-i386, binary, msdos\n"); + fprintf (stderr, " pe-i386, pe-amd64\n"); + fprintf (stderr, " binary, msdos\n"); fprintf (stderr, " --image-base
Set base address of the executable.\n"); fprintf (stderr, "\n"); @@ -330,6 +331,30 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) { } + if (xstrcasecmp (optarg, "pe-amd64") == 0) { + + state->format = LD_FORMAT_AMD64_PE; + + if (state->emulation == LD_EMULATION_NONE) { + state->emulation = LD_EMULATION_I386_PE; + } + + break; + + } + + if (xstrcasecmp (optarg, "elf-amd64") == 0) { + + state->format = LD_FORMAT_AMD64_PE; + + /*if (state->emulation == LD_EMULATION_NONE) { + state->emulation = LD_EMULATION_I386_COFF; + }*/ + + break; + + } + if (xstrcasecmp (optarg, "coff-i386") == 0) { state->format = LD_FORMAT_I386_COFF; diff --git a/link.c b/link.c index 4f76c11..31eab40 100644 --- a/link.c +++ b/link.c @@ -322,7 +322,7 @@ static int has_dgroup = 0; static unsigned long align_section_if_needed (unsigned long value) { - if (state->format == LD_FORMAT_I386_PE) { + if (state->format == LD_FORMAT_I386_PE || state->format == LD_FORMAT_AMD64_PE) { return pe_align_to_file_alignment (value); } @@ -539,7 +539,7 @@ static void calculate_section_sizes_and_rvas (void) { uint64_t rva = 0; - if (state->format == LD_FORMAT_I386_PE) { + if (state->format == LD_FORMAT_AMD64_PE || state->format == LD_FORMAT_I386_PE) { rva = pe_get_first_section_rva (); } else if (state->format == LD_FORMAT_AMD64_MACHO || state->format == LD_FORMAT_AARCH64_MACHO) { rva = macho_get_first_section_rva (); @@ -970,7 +970,7 @@ static void calculate_entry_point (void) { } - } else if (state->format == LD_FORMAT_I386_PE) { + } else if (state->format == LD_FORMAT_I386_PE || state->format == LD_FORMAT_AMD64_PE) { state->entry_symbol_name = xstrdup ("_mainCRTStartup"); diff --git a/pe.c b/pe.c index 7e2f0a4..4797117 100644 --- a/pe.c +++ b/pe.c @@ -24,8 +24,8 @@ static int kill_at = 0, leading_underscore = 1; static unsigned short subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; -static unsigned long section_alignment = DEFAULT_SECTION_ALIGNMENT; -static unsigned long file_alignment = DEFAULT_FILE_ALIGNMENT; +static uint64_t section_alignment = DEFAULT_SECTION_ALIGNMENT; +static uint64_t file_alignment = DEFAULT_FILE_ALIGNMENT; static const char **def_list = 0; long nb_def_list = 0; @@ -327,7 +327,7 @@ static void export_symbol_callback (struct symbol *symbol) { } name_list->info = (symbol->part->section->flags & SECTION_FLAG_CODE) ? 0 : 1; - name_list->next = NULL; + name_list->next = 0; *last_export_name_list_p = name_list; last_export_name_list_p = &name_list->next; @@ -684,7 +684,7 @@ _finish: static struct section *last_section = 0; -static unsigned long base_of_code = 0; +static uint64_t base_of_code = 0; static unsigned long base_of_data = 0; static unsigned long size_of_code = 0; @@ -948,10 +948,9 @@ struct symbol_info *create_symbol_list (struct export_name *export_name, unsigne free (name); - for (i = 0; i < num_names; i++, j++) { + for (i = 0, j = 0; i < num_names; i++, j++) { symbol_info = xmalloc (sizeof (*symbol_info)); - symbol_info->name = xmalloc (7 + strlen (export_name[i].name) + 1); if (leading_underscore) { @@ -1128,7 +1127,7 @@ static void write_implib (struct export_name *export_names, unsigned long num_na info_list = create_symbol_list (export_names, num_names); offset_count = 2 + 3 + num_names; - offsets = xmalloc (offset_count * 4); + offsets = xmalloc (offset_count * 8); module_name = xstrdup (state->output_filename); @@ -1557,8 +1556,14 @@ static void write_implib (struct export_name *export_names, unsigned long num_na memset (&import_hdr, 0, sizeof (import_hdr)); + integer_to_array (IMAGE_FILE_MACHINE_UNKNOWN, import_hdr.Magic1, 2, 0); integer_to_array (0xFFFF, import_hdr.Magic2, 2, 0); - integer_to_array (IMAGE_FILE_MACHINE_I386, import_hdr.Machine, 2, 0); + + if (state->format == LD_FORMAT_AMD64_PE) { + integer_to_array (IMAGE_FILE_MACHINE_AMD64, import_hdr.Machine, 2, 0); + } else { + integer_to_array (IMAGE_FILE_MACHINE_I386, import_hdr.Machine, 2, 0); + } if (leading_underscore) { integer_to_array (1 + strlen (export_names[i].name) + 1 + module_name_length + 1, import_hdr.SizeOfData, 4, 0); @@ -1930,7 +1935,13 @@ void pe_before_link (void) { } - state->size_of_headers = sizeof (struct msdos_header) + sizeof (dos_stub) + sizeof (struct pe_header) + sizeof (struct pe_optional_header); + state->size_of_headers = sizeof (struct msdos_header) + sizeof (dos_stub) + sizeof (struct pe_header); + + if (state->format == LD_FORMAT_AMD64_PE) { + state->size_of_headers += sizeof (struct pe_optional_header_plus); + } else { + state->size_of_headers += sizeof (struct pe_optional_header); + } state->size_of_headers += NUMBER_OF_DATA_DIRECTORIES * sizeof (struct pe_image_data_directory); state->size_of_headers += sizeof (struct pe_section_table_entry) * section_count (); @@ -1966,7 +1977,7 @@ void pe_before_link (void) { } -void pe_write (const char *filename) { +void pe32_write (const char *filename) { FILE *fp; @@ -2090,9 +2101,9 @@ void pe_write (const char *filename) { unsigned short characteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT; - if (can_be_relocated) { + /*if (can_be_relocated) { characteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; - } + }*/ write721_to_byte_array (opthdr->DllCharacteristics, characteristics); @@ -2221,6 +2232,263 @@ void pe_write (const char *filename) { } +void pe64_write (const char *filename) { + + FILE *fp; + + unsigned long data_size = 0, checksum_pos = 0; + unsigned char *data, *pos; + + struct msdos_header *doshdr; + struct pe_header *pehdr; + struct pe_optional_header_plus *opthdr; + + struct section *section; + unsigned long size_of_optional_header; + + if (!(fp = fopen (filename, "wb"))) { + + report_at (program_name, 0, REPORT_ERROR, "failed to open '%s' for writing", filename); + return; + + } + + for (section = all_sections; section; section = section->next) { + + if (!section->is_bss) { + data_size += ALIGN (section->total_size, file_alignment); + } + + } + + data_size += state->size_of_headers; + + data = xmalloc (data_size); + write_sections (data); + + doshdr = (struct msdos_header *) data; + + pehdr = (struct pe_header *) ((char *) doshdr + sizeof (*doshdr) + sizeof (dos_stub)); + opthdr = (struct pe_optional_header_plus *) ((char *) pehdr + sizeof (*pehdr)); + + pos = (unsigned char *) opthdr + sizeof (*opthdr); + + doshdr->e_magic[0] = 'M'; + doshdr->e_magic[1] = 'Z'; + + write721_to_byte_array (doshdr->e_cblp, 0x0090); + write721_to_byte_array (doshdr->e_cp, 0x0003); + + write721_to_byte_array (doshdr->e_cparhdr, ALIGN (sizeof (*doshdr), 16) / 16); + + write721_to_byte_array (doshdr->e_maxalloc, 0xFFFF); + write721_to_byte_array (doshdr->e_sp, 0x00B8); + + write721_to_byte_array (doshdr->e_lfarlc, sizeof (*doshdr)); + write741_to_byte_array (doshdr->e_lfanew, sizeof (*doshdr) + sizeof (dos_stub)); + + memcpy ((char *) data + array_to_integer (doshdr->e_lfarlc, 2, 0), dos_stub, sizeof (dos_stub)); + + + pehdr->Signature[0] = 'P'; + pehdr->Signature[1] = 'E'; + + write721_to_byte_array (pehdr->Machine, IMAGE_FILE_MACHINE_AMD64); + write721_to_byte_array (pehdr->NumberOfSections, section_count ()); + write741_to_byte_array (pehdr->TimeDateStamp, time (0)); + + 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); + + { + + unsigned short characteristics = 0; + + characteristics |= IMAGE_FILE_EXECUTABLE_IMAGE; + /*characteristics |= IMAGE_FILE_LINE_NUMS_STRIPPED;*/ + /*characteristics |= IMAGE_FILE_LOCAL_SYMS_STRIPPED;*/ + characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; + characteristics |= IMAGE_FILE_DEBUG_STRIPPED; + + if (state->create_shared_library) { + characteristics |= IMAGE_FILE_DLL; + } + + if (!can_be_relocated) { + characteristics |= IMAGE_FILE_RELOCS_STRIPPED; + } + + write721_to_byte_array (pehdr->Characteristics, characteristics); + + } + + + write721_to_byte_array (opthdr->Magic, IMAGE_FILE_MAGIC_AMD64); + + opthdr->MajorLinkerVersion = 0; + opthdr->MinorLinkerVersion = 10; + + write741_to_byte_array (opthdr->SizeOfCode, ALIGN (size_of_code, file_alignment)); + write741_to_byte_array (opthdr->SizeOfInitializedData, ALIGN (size_of_initialized_data, file_alignment)); + write741_to_byte_array (opthdr->SizeOfUninitializedData, ALIGN (size_of_uninitialized_data, file_alignment)); + + write741_to_byte_array (opthdr->AddressOfEntryPoint, state->entry_point); + + write741_to_byte_array (opthdr->BaseOfCode, base_of_code); + integer_to_array (state->base_address, opthdr->ImageBase, 8, 0); + + write741_to_byte_array (opthdr->SectionAlignment, section_alignment); + write741_to_byte_array (opthdr->FileAlignment, file_alignment); + + write721_to_byte_array (opthdr->MajorOperatingSystemVersion, 4); + write721_to_byte_array (opthdr->MajorImageVersion, 1); + write721_to_byte_array (opthdr->MajorSubsystemVersion, 4); + + 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, 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; + + if (!(bss_section = section_find (".bss"))) { + + integer_to_array (section_alignment << 9, opthdr->SizeOfStackReserved, 8, 0); + integer_to_array (0x1000, opthdr->SizeOfStackCommit, 8, 0); + integer_to_array (section_alignment << 8, opthdr->SizeOfHeapReserved, 8, 0); + integer_to_array (0x1000, opthdr->SizeOfHeapCommit, 8, 0); + + } else { + + uint64_t ibss_addr = bss_section->rva; + uint64_t ibss_size = bss_section->total_size; + + uint64_t stack_addr = ibss_addr + ibss_size; + uint64_t stack_size = ALIGN (stack_addr, section_alignment); + + integer_to_array (section_alignment << 9, opthdr->SizeOfStackReserved, 8, 0); + integer_to_array (ALIGN (stack_addr % 16 + stack_size, section_alignment), opthdr->SizeOfStackCommit, 8, 0); + integer_to_array (section_alignment << 8, opthdr->SizeOfHeapReserved, 8, 0); + integer_to_array (ALIGN (stack_addr % 16 + stack_size, section_alignment), opthdr->SizeOfHeapCommit, 8, 0); + + } + + } + + 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")) && iat_first_part) { + + write741_to_byte_array (idd->VirtualAddress, iat_first_part->rva); + write741_to_byte_array (idd->Size, iat_last_part->rva + iat_last_part->content_size - iat_first_part->rva); + + } + + break; + + } + + pos += sizeof (*idd); + + } + + } + + + for (section = all_sections; section; section = section->next) { + + struct pe_section_table_entry *hdr = section->object_dependent_data; + + memcpy (pos, hdr, sizeof (*hdr)); + pos += sizeof (*hdr); + + free (hdr); + + } + + + checksum_pos = sizeof (*doshdr) + sizeof (dos_stub) + sizeof (*pehdr) + offsetof (struct pe_optional_header, Checksum); + write741_to_byte_array (opthdr->Checksum, calculate_checksum (data, checksum_pos, data_size)); + + if (fwrite (data, data_size, 1, fp) != 1) { + report_at (program_name, 0, REPORT_ERROR, "failed to write data to '%s'", filename); + } + + free (data); + fclose (fp); + +} + void pe_print_help (void) { fprintf (stderr, "i386pe:\n\n"); @@ -2288,7 +2556,7 @@ static void import_generate_import (const char *import_name, short ordinal_hint, part = section_part_new (section, of); subsection_append_section_part (subsection, part); - part->content = xmalloc (part->content_size = 4); + part->content = xmalloc (part->content_size = (state->format == LD_FORMAT_AMD64_PE ? 8 : 4)); part->reloc_cnt = 1; part->reloc_arr = xmalloc (part->reloc_cnt * sizeof (*part->reloc_arr)); @@ -2303,7 +2571,7 @@ static void import_generate_import (const char *import_name, short ordinal_hint, part = section_part_new (section, of); subsection_append_section_part (subsection, part); - part->content = xmalloc (part->content_size = 4); + part->content = xmalloc (part->content_size = (state->format == LD_FORMAT_AMD64_PE ? 8 : 4)); symbol->name = xstrdup (".idata$5"); symbol->value = 0; @@ -2394,8 +2662,13 @@ static void import_generate_import (const char *import_name, short ordinal_hint, relocs = part->reloc_arr; relocs[0].symbol = &of->symbol_arr[0]; - relocs[0].howto = &reloc_howtos[RELOC_TYPE_32]; relocs[0].offset = 2; + + if (state->format == LD_FORMAT_AMD64_PE) { + relocs[0].howto = &reloc_howtos[RELOC_TYPE_PC32]; + } else { + relocs[0].howto = &reloc_howtos[RELOC_TYPE_32]; + } } @@ -2526,13 +2799,13 @@ static void import_generate_end (void) { part = section_part_new (section, of); subsection_append_section_part (subsection, part); - part->content = xmalloc (part->content_size = 4); + part->content = xmalloc (part->content_size = (state->format == LD_FORMAT_AMD64_PE ? 8 : 4)); subsection = subsection_find_or_make (section, "5"); part = section_part_new (section, of); subsection_append_section_part (subsection, part); - part->content = xmalloc (part->content_size = 4); + part->content = xmalloc (part->content_size = (state->format == LD_FORMAT_AMD64_PE ? 8 : 4)); } @@ -2556,7 +2829,7 @@ void read_pe_import_library (const char *filename, unsigned char *data) { const char *import_name; const char *dll_name; - if (state->format != LD_FORMAT_I386_PE) { + if (state->format != LD_FORMAT_I386_PE && state->format != LD_FORMAT_AMD64_PE) { return; } diff --git a/pe.h b/pe.h index e63d8fa..ad7dd1b 100644 --- a/pe.h +++ b/pe.h @@ -60,14 +60,18 @@ struct pe_header { }; +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 +#define IMAGE_FILE_MACHINE_AMD64 0x8664 #define IMAGE_FILE_MACHINE_I386 0x014C #define IMAGE_FILE_RELOCS_STRIPPED 0x0001 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 #define IMAGE_FILE_32BIT_MACHINE 0x0100 #define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_DLL 0x2000 struct pe_optional_header { @@ -115,7 +119,48 @@ struct pe_optional_header { }; +struct pe_optional_header_plus { + + unsigned char Magic[2]; + + unsigned char MajorLinkerVersion; + unsigned char MinorLinkerVersion; + + unsigned char SizeOfCode[4]; + unsigned char SizeOfInitializedData[4]; + unsigned char SizeOfUninitializedData[4]; + unsigned char AddressOfEntryPoint[4]; + + unsigned char BaseOfCode[4]; + unsigned char ImageBase[8]; + + unsigned char SectionAlignment[4]; + unsigned char FileAlignment[4]; + unsigned char MajorOperatingSystemVersion[2]; + unsigned char MinorOperatingSystemVersion[2]; + unsigned char MajorImageVersion[2]; + unsigned char MinorImageVersion[2]; + unsigned char MajorSubsystemVersion[2]; + unsigned char MinorSubsystemVersion[2]; + unsigned char Win32VersionValue[4]; + unsigned char SizeOfImage[4]; + unsigned char SizeOfHeaders[4]; + unsigned char Checksum[4]; + unsigned char Subsystem[2]; + unsigned char DllCharacteristics[2]; + + unsigned char SizeOfStackReserved[8]; + unsigned char SizeOfStackCommit[8]; + unsigned char SizeOfHeapReserved[8]; + unsigned char SizeOfHeapCommit[8]; + + unsigned char LoaderFlags[4]; + unsigned char NumberOfRvaAndSizes[4]; + +}; + #define IMAGE_FILE_MAGIC_I386 0x010B +#define IMAGE_FILE_MAGIC_AMD64 0x020B struct pe_section_table_entry { @@ -236,10 +281,12 @@ void pe_after_link (void); void pe_before_link (void); void pe_print_help (void); -void pe_write (const char *filename); -void pe_use_option (const char *cmd_arg, int idx, const char *optarg); +void pe32_write (const char *filename); +void pe64_write (const char *filename); +void pe_use_option (const char *cmd_arg, int idx, const char *optarg); void pe_archive_end (void); + void read_pe_import_library (const char *filename, unsigned char *data); #endif /* _PE_H */