/* * TCCPE.C - PE file output for the Tiny C Compiler * * Copyright (c) 2005-2007 grischka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "tcc.h" #define PE_MERGE_DATA/* #define PE_PRINT_SECTIONS */ #ifndef _WIN32#define stricmp strcasecmp#define strnicmp strncasecmp#include <sys/stat.h> /* chmod() */#endif #ifdef TCC_TARGET_X86_64# define ADDR3264 ULONGLONG# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64# define REL_TYPE_DIRECT R_X86_64_64# define R_XXX_THUNKFIX R_X86_64_PC32# define R_XXX_RELATIVE R_X86_64_RELATIVE# define IMAGE_FILE_MACHINE 0x8664# define RSRC_RELTYPE 3 #elif defined TCC_TARGET_ARM# define ADDR3264 DWORD# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW# define REL_TYPE_DIRECT R_ARM_ABS32# define R_XXX_THUNKFIX R_ARM_ABS32# define R_XXX_RELATIVE R_ARM_RELATIVE# define IMAGE_FILE_MACHINE 0x01C0# define RSRC_RELTYPE 7 /* ??? (not tested) */ #elif defined TCC_TARGET_I386# define ADDR3264 DWORD# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW# define REL_TYPE_DIRECT R_386_32# define R_XXX_THUNKFIX R_386_32# define R_XXX_RELATIVE R_386_RELATIVE# define IMAGE_FILE_MACHINE 0x014C# define RSRC_RELTYPE 7 /* DIR32NB */ #endif #ifndef IMAGE_NT_SIGNATURE/* ----------------------------------------------------------- *//* definitions below are from winnt.h */ typedef unsigned char BYTE;typedef unsigned short WORD;typedef unsigned int DWORD;typedef unsigned long long ULONGLONG;#pragma pack(push, 1) typedef struct _IMAGE_DOS_HEADER { /* DOS .EXE header */ WORD e_magic; /* Magic number */ WORD e_cblp; /* Bytes on last page of file */ WORD e_cp; /* Pages in file */ WORD e_crlc; /* Relocations */ WORD e_cparhdr; /* Size of header in paragraphs */ WORD e_minalloc; /* Minimum extra paragraphs needed */ WORD e_maxalloc; /* Maximum extra paragraphs needed */ WORD e_ss; /* Initial (relative) SS value */ WORD e_sp; /* Initial SP value */ WORD e_csum; /* Checksum */ WORD e_ip; /* Initial IP value */ WORD e_cs; /* Initial (relative) CS value */ WORD e_lfarlc; /* File address of relocation table */ WORD e_ovno; /* Overlay number */ WORD e_res[4]; /* Reserved words */ WORD e_oemid; /* OEM identifier (for e_oeminfo) */ WORD e_oeminfo; /* OEM information; e_oemid specific */ WORD e_res2[10]; /* Reserved words */ DWORD e_lfanew; /* File address of new exe header */} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; #define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */#define SIZE_OF_NT_SIGNATURE 4 typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics;} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; #define IMAGE_SIZEOF_FILE_HEADER 20 typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size;} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; typedef struct _IMAGE_OPTIONAL_HEADER { /* Standard fields. */ WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode;#ifndef TCC_TARGET_X86_64 DWORD BaseOfData;#endif /* NT additional fields. */ ADDR3264 ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; ADDR3264 SizeOfStackReserve; ADDR3264 SizeOfStackCommit; ADDR3264 SizeOfHeapReserve; ADDR3264 SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[16];} IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, IMAGE_OPTIONAL_HEADER; #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory *//* IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 (X86 usage) */#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 /* Architecture Specific Data */#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* RVA of GP */#define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 /* Delay Load Import Descriptors */#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 /* COM Runtime descriptor */ /* Section header format. */#define IMAGE_SIZEOF_SHORT_NAME 8 typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics;} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; #define IMAGE_SIZEOF_SECTION_HEADER 40 typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; DWORD AddressOfNames; DWORD AddressOfNameOrdinals;} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; DWORD OriginalFirstThunk; }; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; DWORD FirstThunk;} IMAGE_IMPORT_DESCRIPTOR; typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock;// WORD TypeOffset[1];} IMAGE_BASE_RELOCATION; #define IMAGE_SIZEOF_BASE_RELOCATION 8 #define IMAGE_REL_BASED_ABSOLUTE 0#define IMAGE_REL_BASED_HIGH 1#define IMAGE_REL_BASED_LOW 2#define IMAGE_REL_BASED_HIGHLOW 3#define IMAGE_REL_BASED_HIGHADJ 4#define IMAGE_REL_BASED_MIPS_JMPADDR 5#define IMAGE_REL_BASED_SECTION 6#define IMAGE_REL_BASED_REL32 7#define IMAGE_REL_BASED_DIR64 10 #define IMAGE_SCN_CNT_CODE 0x00000020#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000#define IMAGE_SCN_MEM_SHARED 0x10000000#define IMAGE_SCN_MEM_EXECUTE 0x20000000#define IMAGE_SCN_MEM_READ 0x40000000#define IMAGE_SCN_MEM_WRITE 0x80000000 #pragma pack(pop) /* ----------------------------------------------------------- */#endif /* ndef IMAGE_NT_SIGNATURE *//* ----------------------------------------------------------- */ #ifndef IMAGE_REL_BASED_DIR64# define IMAGE_REL_BASED_DIR64 10#endif #pragma pack(push, 1)struct pe_header{ IMAGE_DOS_HEADER doshdr; BYTE dosstub[0x40]; DWORD nt_sig; IMAGE_FILE_HEADER filehdr;#ifdef TCC_TARGET_X86_64 IMAGE_OPTIONAL_HEADER64 opthdr;#else#ifdef _WIN64 IMAGE_OPTIONAL_HEADER32 opthdr;#else IMAGE_OPTIONAL_HEADER opthdr;#endif#endif}; struct pe_reloc_header { DWORD offset; DWORD size;}; struct pe_rsrc_header { struct _IMAGE_FILE_HEADER filehdr; struct _IMAGE_SECTION_HEADER sectionhdr;}; struct pe_rsrc_reloc { DWORD offset; DWORD size; WORD type;};#pragma pack(pop) /* ------------------------------------------------------------- *//* internal temporary structures */ enum { sec_text = 0, sec_data , sec_bss , sec_idata , sec_pdata , sec_other , sec_rsrc , sec_stab , sec_stabstr , sec_reloc , sec_last}; #if 0static const DWORD pe_sec_flags[] = { 0x60000020, /* ".text" , */ 0xC0000040, /* ".data" , */ 0xC0000080, /* ".bss" , */ 0x40000040, /* ".idata" , */ 0x40000040, /* ".pdata" , */ 0xE0000060, /* < other > , */ 0x40000040, /* ".rsrc" , */ 0x42000802, /* ".stab" , */ 0x42000040, /* ".reloc" , */};#endif struct section_info { int cls; char name[32]; DWORD sh_addr; DWORD sh_size; DWORD pe_flags; Section *sec; DWORD data_size; IMAGE_SECTION_HEADER ish;}; struct import_symbol { int sym_index; int iat_index; int thk_offset;}; struct pe_import_info { int dll_index; int sym_count; struct import_symbol **symbols;}; struct pe_info { TCCState *s1; Section *reloc; Section *thunk; const char *filename; int type; DWORD sizeofheaders; ADDR3264 imagebase; const char *start_symbol; DWORD start_addr; DWORD imp_offs; DWORD imp_size; DWORD iat_offs; DWORD iat_size; DWORD exp_offs; DWORD exp_size; int subsystem; DWORD section_align; DWORD file_align; struct section_info **sec_info; int sec_count; struct pe_import_info **imp_info; int imp_count;}; #define PE_NUL 0#define PE_DLL 1#define PE_GUI 2#define PE_EXE 3#define PE_RUN 4 /* --------------------------------------------*/ static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym){ const char *name = (char*)symtab_section->link->data + sym->st_name; if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) return name + 1; return name;} static int pe_find_import(TCCState * s1, ElfW(Sym) *sym){ char buffer[200]; const char *s, *p; int sym_index = 0, n = 0; int a, err = 0; do { s = pe_export_name(s1, sym); a = 0; if (n) { /* second try: */ if (sym->st_other & ST_PE_STDCALL) { /* try w/0 stdcall deco (windows API convention) */ p = strrchr(s, '@'); if (!p || s[0] != '_') break; strcpy(buffer, s+1)[p-s-1] = 0; } else if (s[0] != '_') { /* try non-ansi function */ buffer[0] = '_', strcpy(buffer + 1, s); } else if (0 == memcmp(s, "__imp_", 6)) { /* mingw 2.0 */ strcpy(buffer, s + 6), a = 1; } else if (0 == memcmp(s, "_imp__", 6)) { /* mingw 3.7 */ strcpy(buffer, s + 6), a = 1; } else { continue; } s = buffer; } sym_index = find_elf_sym(s1->dynsymtab_section, s); // printf("find (%d) %d %s\n", n, sym_index, s); if (sym_index && ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT && 0 == (sym->st_other & ST_PE_IMPORT) && 0 == a ) err = -1, sym_index = 0; } while (0 == sym_index && ++n < 2); return n == 2 ? err : sym_index;} /*----------------------------------------------------------------------------*/ static int dynarray_assoc(void **pp, int n, int key){ int i; for (i = 0; i < n; ++i, ++pp) if (key == **(int **) pp) return i; return -1;} static DWORD umin(DWORD a, DWORD b){ return a < b ? a : b;} static DWORD umax(DWORD a, DWORD b){ return a < b ? b : a;} static DWORD pe_file_align(struct pe_info *pe, DWORD n){ return (n + (pe->file_align - 1)) & ~(pe->file_align - 1);} static DWORD pe_virtual_align(struct pe_info *pe, DWORD n){ return (n + (pe->section_align - 1)) & ~(pe->section_align - 1);} static void pe_align_section(Section *s, int a){ int i = s->data_offset & (a-1); if (i) section_ptr_add(s, a - i);} static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size){ hdr->opthdr.DataDirectory[dir].VirtualAddress = addr; hdr->opthdr.DataDirectory[dir].Size = size;} struct pe_file { FILE *op; DWORD sum; unsigned pos;}; static int pe_fwrite(void *data, int len, struct pe_file *pf){ WORD *p = data; DWORD sum; int ret, i; pf->pos += (ret = fwrite(data, 1, len, pf->op)); sum = pf->sum; for (i = len; i > 0; i -= 2) { sum += (i >= 2) ? *p++ : *(BYTE*)p; sum = (sum + (sum >> 16)) & 0xFFFF; } pf->sum = sum; return len == ret ? 0 : -1;} static void pe_fpad(struct pe_file *pf, DWORD new_pos){ char buf[256]; int n, diff = new_pos - pf->pos; memset(buf, 0, sizeof buf); while (diff > 0) { diff -= n = umin(diff, sizeof buf); fwrite(buf, n, 1, pf->op); } pf->pos = new_pos;} /*----------------------------------------------------------------------------*/Lines 1–500 of 2048. Load more
/* * TCCPE.C - PE file output for the Tiny C Compiler * * Copyright (c) 2005-2007 grischka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "tcc.h" #define PE_MERGE_DATA /* #define PE_PRINT_SECTIONS */ #ifndef _WIN32 #define stricmp strcasecmp #define strnicmp strncasecmp #include <sys/stat.h> /* chmod() */ #endif #ifdef TCC_TARGET_X86_64 # define ADDR3264 ULONGLONG # define PE_IMAGE_REL IMAGE_REL_BASED_DIR64 # define REL_TYPE_DIRECT R_X86_64_64 # define R_XXX_THUNKFIX R_X86_64_PC32 # define R_XXX_RELATIVE R_X86_64_RELATIVE # define IMAGE_FILE_MACHINE 0x8664 # define RSRC_RELTYPE 3 #elif defined TCC_TARGET_ARM # define ADDR3264 DWORD # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW # define REL_TYPE_DIRECT R_ARM_ABS32 # define R_XXX_THUNKFIX R_ARM_ABS32 # define R_XXX_RELATIVE R_ARM_RELATIVE # define IMAGE_FILE_MACHINE 0x01C0 # define RSRC_RELTYPE 7 /* ??? (not tested) */ #elif defined TCC_TARGET_I386 # define ADDR3264 DWORD # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW # define REL_TYPE_DIRECT R_386_32 # define R_XXX_THUNKFIX R_386_32 # define R_XXX_RELATIVE R_386_RELATIVE # define IMAGE_FILE_MACHINE 0x014C # define RSRC_RELTYPE 7 /* DIR32NB */ #endif #ifndef IMAGE_NT_SIGNATURE /* ----------------------------------------------------------- */ /* definitions below are from winnt.h */ typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned long long ULONGLONG; #pragma pack(push, 1) typedef struct _IMAGE_DOS_HEADER { /* DOS .EXE header */ WORD e_magic; /* Magic number */ WORD e_cblp; /* Bytes on last page of file */ WORD e_cp; /* Pages in file */ WORD e_crlc; /* Relocations */ WORD e_cparhdr; /* Size of header in paragraphs */ WORD e_minalloc; /* Minimum extra paragraphs needed */ WORD e_maxalloc; /* Maximum extra paragraphs needed */ WORD e_ss; /* Initial (relative) SS value */ WORD e_sp; /* Initial SP value */ WORD e_csum; /* Checksum */ WORD e_ip; /* Initial IP value */ WORD e_cs; /* Initial (relative) CS value */ WORD e_lfarlc; /* File address of relocation table */ WORD e_ovno; /* Overlay number */ WORD e_res[4]; /* Reserved words */ WORD e_oemid; /* OEM identifier (for e_oeminfo) */ WORD e_oeminfo; /* OEM information; e_oemid specific */ WORD e_res2[10]; /* Reserved words */ DWORD e_lfanew; /* File address of new exe header */ } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; #define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ #define SIZE_OF_NT_SIGNATURE 4 typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; #define IMAGE_SIZEOF_FILE_HEADER 20 typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; typedef struct _IMAGE_OPTIONAL_HEADER { /* Standard fields. */ WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; #ifndef TCC_TARGET_X86_64 DWORD BaseOfData; #endif /* NT additional fields. */ ADDR3264 ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; ADDR3264 SizeOfStackReserve; ADDR3264 SizeOfStackCommit; ADDR3264 SizeOfHeapReserve; ADDR3264 SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[16]; } IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, IMAGE_OPTIONAL_HEADER; #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */ #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */ #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */ #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */ #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */ #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */ #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory */ /* IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 (X86 usage) */ #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 /* Architecture Specific Data */ #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* RVA of GP */ #define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */ #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */ #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */ #define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */ #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 /* Delay Load Import Descriptors */ #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 /* COM Runtime descriptor */ /* Section header format. */ #define IMAGE_SIZEOF_SHORT_NAME 8 typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; #define IMAGE_SIZEOF_SECTION_HEADER 40 typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; DWORD AddressOfNames; DWORD AddressOfNameOrdinals; } IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; DWORD OriginalFirstThunk; }; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; DWORD FirstThunk; } IMAGE_IMPORT_DESCRIPTOR; typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock; // WORD TypeOffset[1]; } IMAGE_BASE_RELOCATION; #define IMAGE_SIZEOF_BASE_RELOCATION 8 #define IMAGE_REL_BASED_ABSOLUTE 0 #define IMAGE_REL_BASED_HIGH 1 #define IMAGE_REL_BASED_LOW 2 #define IMAGE_REL_BASED_HIGHLOW 3 #define IMAGE_REL_BASED_HIGHADJ 4 #define IMAGE_REL_BASED_MIPS_JMPADDR 5 #define IMAGE_REL_BASED_SECTION 6 #define IMAGE_REL_BASED_REL32 7 #define IMAGE_REL_BASED_DIR64 10 #define IMAGE_SCN_CNT_CODE 0x00000020 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 #define IMAGE_SCN_MEM_SHARED 0x10000000 #define IMAGE_SCN_MEM_EXECUTE 0x20000000 #define IMAGE_SCN_MEM_READ 0x40000000 #define IMAGE_SCN_MEM_WRITE 0x80000000 #pragma pack(pop) /* ----------------------------------------------------------- */ #endif /* ndef IMAGE_NT_SIGNATURE */ /* ----------------------------------------------------------- */ #ifndef IMAGE_REL_BASED_DIR64 # define IMAGE_REL_BASED_DIR64 10 #endif #pragma pack(push, 1) struct pe_header { IMAGE_DOS_HEADER doshdr; BYTE dosstub[0x40]; DWORD nt_sig; IMAGE_FILE_HEADER filehdr; #ifdef TCC_TARGET_X86_64 IMAGE_OPTIONAL_HEADER64 opthdr; #else #ifdef _WIN64 IMAGE_OPTIONAL_HEADER32 opthdr; #else IMAGE_OPTIONAL_HEADER opthdr; #endif #endif }; struct pe_reloc_header { DWORD offset; DWORD size; }; struct pe_rsrc_header { struct _IMAGE_FILE_HEADER filehdr; struct _IMAGE_SECTION_HEADER sectionhdr; }; struct pe_rsrc_reloc { DWORD offset; DWORD size; WORD type; }; #pragma pack(pop) /* ------------------------------------------------------------- */ /* internal temporary structures */ enum { sec_text = 0, sec_data , sec_bss , sec_idata , sec_pdata , sec_other , sec_rsrc , sec_stab , sec_stabstr , sec_reloc , sec_last }; #if 0 static const DWORD pe_sec_flags[] = { 0x60000020, /* ".text" , */ 0xC0000040, /* ".data" , */ 0xC0000080, /* ".bss" , */ 0x40000040, /* ".idata" , */ 0x40000040, /* ".pdata" , */ 0xE0000060, /* < other > , */ 0x40000040, /* ".rsrc" , */ 0x42000802, /* ".stab" , */ 0x42000040, /* ".reloc" , */ }; #endif struct section_info { int cls; char name[32]; DWORD sh_addr; DWORD sh_size; DWORD pe_flags; Section *sec; DWORD data_size; IMAGE_SECTION_HEADER ish; }; struct import_symbol { int sym_index; int iat_index; int thk_offset; }; struct pe_import_info { int dll_index; int sym_count; struct import_symbol **symbols; }; struct pe_info { TCCState *s1; Section *reloc; Section *thunk; const char *filename; int type; DWORD sizeofheaders; ADDR3264 imagebase; const char *start_symbol; DWORD start_addr; DWORD imp_offs; DWORD imp_size; DWORD iat_offs; DWORD iat_size; DWORD exp_offs; DWORD exp_size; int subsystem; DWORD section_align; DWORD file_align; struct section_info **sec_info; int sec_count; struct pe_import_info **imp_info; int imp_count; }; #define PE_NUL 0 #define PE_DLL 1 #define PE_GUI 2 #define PE_EXE 3 #define PE_RUN 4 /* --------------------------------------------*/ static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym) { const char *name = (char*)symtab_section->link->data + sym->st_name; if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) return name + 1; return name; } static int pe_find_import(TCCState * s1, ElfW(Sym) *sym) { char buffer[200]; const char *s, *p; int sym_index = 0, n = 0; int a, err = 0; do { s = pe_export_name(s1, sym); a = 0; if (n) { /* second try: */ if (sym->st_other & ST_PE_STDCALL) { /* try w/0 stdcall deco (windows API convention) */ p = strrchr(s, '@'); if (!p || s[0] != '_') break; strcpy(buffer, s+1)[p-s-1] = 0; } else if (s[0] != '_') { /* try non-ansi function */ buffer[0] = '_', strcpy(buffer + 1, s); } else if (0 == memcmp(s, "__imp_", 6)) { /* mingw 2.0 */ strcpy(buffer, s + 6), a = 1; } else if (0 == memcmp(s, "_imp__", 6)) { /* mingw 3.7 */ strcpy(buffer, s + 6), a = 1; } else { continue; } s = buffer; } sym_index = find_elf_sym(s1->dynsymtab_section, s); // printf("find (%d) %d %s\n", n, sym_index, s); if (sym_index && ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT && 0 == (sym->st_other & ST_PE_IMPORT) && 0 == a ) err = -1, sym_index = 0; } while (0 == sym_index && ++n < 2); return n == 2 ? err : sym_index; } /*----------------------------------------------------------------------------*/ static int dynarray_assoc(void **pp, int n, int key) { int i; for (i = 0; i < n; ++i, ++pp) if (key == **(int **) pp) return i; return -1; } static DWORD umin(DWORD a, DWORD b) { return a < b ? a : b; } static DWORD umax(DWORD a, DWORD b) { return a < b ? b : a; } static DWORD pe_file_align(struct pe_info *pe, DWORD n) { return (n + (pe->file_align - 1)) & ~(pe->file_align - 1); } static DWORD pe_virtual_align(struct pe_info *pe, DWORD n) { return (n + (pe->section_align - 1)) & ~(pe->section_align - 1); } static void pe_align_section(Section *s, int a) { int i = s->data_offset & (a-1); if (i) section_ptr_add(s, a - i); } static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size) { hdr->opthdr.DataDirectory[dir].VirtualAddress = addr; hdr->opthdr.DataDirectory[dir].Size = size; } struct pe_file { FILE *op; DWORD sum; unsigned pos; }; static int pe_fwrite(void *data, int len, struct pe_file *pf) { WORD *p = data; DWORD sum; int ret, i; pf->pos += (ret = fwrite(data, 1, len, pf->op)); sum = pf->sum; for (i = len; i > 0; i -= 2) { sum += (i >= 2) ? *p++ : *(BYTE*)p; sum = (sum + (sum >> 16)) & 0xFFFF; } pf->sum = sum; return len == ret ? 0 : -1; } static void pe_fpad(struct pe_file *pf, DWORD new_pos) { char buf[256]; int n, diff = new_pos - pf->pos; memset(buf, 0, sizeof buf); while (diff > 0) { diff -= n = umin(diff, sizeof buf); fwrite(buf, n, 1, pf->op); } pf->pos = new_pos; } /*----------------------------------------------------------------------------*/