herman ten bruggeMake bound checking faster.0fb54302 months agoHistory
2304 lines · 71.5 KB · C
RawDownload
/* *  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 1#define PE_PRINT_SECTIONS 0 #ifndef _WIN32#define stricmp strcasecmp#define strnicmp strncasecmp#include <sys/stat.h> /* chmod() */#endif #if defined TCC_TARGET_X86_64# 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 R_XXX_FUNCCALL R_X86_64_PLT32# define RSRC_RELTYPE 3# define IMAGE_FILE_MACHINE 0x8664# define CHARACTERISTICS_EXE 0x022F# define CHARACTERISTICS_DLL 0x222E# define IMAGE_BASE_EXE 0x00400000# define IMAGE_BASE_DLL 0x10000000# define DLLCHARACTERISTICS 0# define OS_VER 0x0400 #elif defined TCC_TARGET_ARM# define REL_TYPE_DIRECT R_ARM_ABS32# define R_XXX_THUNKFIX R_ARM_ABS32# define R_XXX_RELATIVE R_ARM_RELATIVE# define R_XXX_FUNCCALL R_ARM_PC24# define R_XXX_FUNCCALL2 R_ARM_ABS32# define RSRC_RELTYPE 7 /* ??? (not tested) */# define IMAGE_FILE_MACHINE 0x01C0# define CHARACTERISTICS_EXE 0x010F# define CHARACTERISTICS_DLL 0x230F# define IMAGE_BASE_EXE 0x00100000# define IMAGE_BASE_DLL 0x10000000# define DLLCHARACTERISTICS 0# define OS_VER 0x0400 #elif defined TCC_TARGET_ARM64# define REL_TYPE_DIRECT R_AARCH64_ABS64# define R_XXX_THUNKFIX R_AARCH64_ABS64# define R_XXX_RELATIVE R_AARCH64_RELATIVE# define R_XXX_FUNCCALL R_AARCH64_CALL26# define RSRC_RELTYPE 3# define IMAGE_FILE_MACHINE 0xAA64# define CHARACTERISTICS_EXE 0x0022# define CHARACTERISTICS_DLL 0x2022# define IMAGE_BASE_EXE 0x140000000ULL# define IMAGE_BASE_DLL 0x180000000ULL# define OS_VER 0x0602# define DLLCHARACTERISTICS 0x8160 #elif defined TCC_TARGET_I386# define REL_TYPE_DIRECT R_386_32# define R_XXX_THUNKFIX R_386_32# define R_XXX_RELATIVE R_386_RELATIVE# define R_XXX_FUNCCALL R_386_PC32# define RSRC_RELTYPE 7 /* DIR32NB */# define IMAGE_FILE_MACHINE 0x014C# define CHARACTERISTICS_EXE 0x030F# define CHARACTERISTICS_DLL 0x230E# define IMAGE_BASE_EXE 0x00400000# define IMAGE_BASE_DLL 0x10000000# define OS_VER 0x0400# define DLLCHARACTERISTICS 0#endif #if PTR_SIZE == 8# define ADDR3264 ULONGLONG# define PE_MAGIC 0x020B# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64#else# define ADDR3264 DWORD# define PE_MAGIC 0x010B# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW#endif #ifndef IMAGE_NT_SIGNATURE/* cross compiler: windows.h was not included *//* ----------------------------------------------------------- *//* 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 */ 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;#if PTR_SIZE == 4    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_TLS_DIRECTORY {    ADDR3264 StartAddressOfRawData;    ADDR3264 EndAddressOfRawData;    ADDR3264 AddressOfIndex;    ADDR3264 AddressOfCallBacks;    DWORD SizeOfZeroFill;    DWORD Characteristics;} IMAGE_TLS_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 #define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001 #pragma pack(pop) /* ----------------------------------------------------------- */#endif /* ndef IMAGE_NT_SIGNATURE *//* ----------------------------------------------------------- */ #ifndef IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE  /* allow self-host build with tcc 0.9.27 - doesn't have this in winnt.h */  #define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040#endif #pragma pack(push, 1)struct pe_header{    IMAGE_DOS_HEADER doshdr;    BYTE dosstub[0x40];    DWORD nt_sig;    IMAGE_FILE_HEADER filehdr;#if PTR_SIZE == 8    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_rdata ,    sec_data ,    sec_bss ,    sec_idata ,    sec_pdata ,    sec_tdata ,    sec_tbss ,    sec_other ,    sec_rsrc ,    sec_debug ,    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];    ADDR3264 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;    Section *coffsym;    Section *coffstr;    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;    DWORD tls_dir;    DWORD tls_data;    DWORD tls_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;    /* output */    FILE *op;    DWORD sum;    unsigned pos;}; #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 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 ADDR3264 pe_virtual_align(struct pe_info *pe, ADDR3264 n){    return (n + (pe->section_align - 1)) & ~(ADDR3264)(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;} static int pe_fwrite(struct pe_info *pe, const void *data, int len){    const WORD *p = data;    DWORD sum;    int ret, i;    pe->pos += (ret = fwrite(data, 1, len, pe->op));    sum = pe->sum;    for (i = len; i > 0; i -= 2) {

Lines 1–500 of 2304.