Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  TCCPE.C - PE file output for the TinyC Compiler
  3.  *
  4.  *  Copyright (c) 2005 grischka
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. typedef unsigned char BYTE;
  22. typedef unsigned short WORD;
  23. typedef unsigned long DWORD;
  24. #define ST static
  25.  
  26. /* XXX: move that to TCC ? */
  27. int verbose = 0;
  28.  
  29. /* definitions below are from winnt.h */
  30.  
  31. typedef struct _IMAGE_DOS_HEADER {      /* DOS .EXE header */
  32.     WORD e_magic;               /* Magic number */
  33.     WORD e_cblp;                /* Bytes on last page of file */
  34.     WORD e_cp;                  /* Pages in file */
  35.     WORD e_crlc;                /* Relocations */
  36.     WORD e_cparhdr;             /* Size of header in paragraphs */
  37.     WORD e_minalloc;            /* Minimum extra paragraphs needed */
  38.     WORD e_maxalloc;            /* Maximum extra paragraphs needed */
  39.     WORD e_ss;                  /* Initial (relative) SS value */
  40.     WORD e_sp;                  /* Initial SP value */
  41.     WORD e_csum;                /* Checksum */
  42.     WORD e_ip;                  /* Initial IP value */
  43.     WORD e_cs;                  /* Initial (relative) CS value */
  44.     WORD e_lfarlc;              /* File address of relocation table */
  45.     WORD e_ovno;                /* Overlay number */
  46.     WORD e_res[4];              /* Reserved words */
  47.     WORD e_oemid;               /* OEM identifier (for e_oeminfo) */
  48.     WORD e_oeminfo;             /* OEM information; e_oemid specific */
  49.     WORD e_res2[10];            /* Reserved words */
  50.     DWORD e_lfanew;             /* File address of new exe header */
  51.     BYTE e_code[0x40];
  52.  
  53. } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
  54.  
  55. #define IMAGE_NT_SIGNATURE  0x00004550  /* PE00 */
  56. #define SIZE_OF_NT_SIGNATURE 4
  57.  
  58. typedef struct _IMAGE_FILE_HEADER {
  59.     WORD Machine;
  60.     WORD NumberOfSections;
  61.     DWORD TimeDateStamp;
  62.     DWORD PointerToSymbolTable;
  63.     DWORD NumberOfSymbols;
  64.     WORD SizeOfOptionalHeader;
  65.     WORD Characteristics;
  66. } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
  67.  
  68.  
  69. #define IMAGE_SIZEOF_FILE_HEADER 20
  70.  
  71. typedef struct _IMAGE_DATA_DIRECTORY {
  72.     DWORD VirtualAddress;
  73.     DWORD Size;
  74. } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
  75.  
  76.  
  77. typedef struct _IMAGE_OPTIONAL_HEADER {
  78.     /* Standard fields. */
  79.     WORD Magic;
  80.     BYTE MajorLinkerVersion;
  81.     BYTE MinorLinkerVersion;
  82.     DWORD SizeOfCode;
  83.     DWORD SizeOfInitializedData;
  84.     DWORD SizeOfUninitializedData;
  85.     DWORD AddressOfEntryPoint;
  86.     DWORD BaseOfCode;
  87.     DWORD BaseOfData;
  88.  
  89.     /* NT additional fields. */
  90.     DWORD ImageBase;
  91.     DWORD SectionAlignment;
  92.     DWORD FileAlignment;
  93.     WORD MajorOperatingSystemVersion;
  94.     WORD MinorOperatingSystemVersion;
  95.     WORD MajorImageVersion;
  96.     WORD MinorImageVersion;
  97.     WORD MajorSubsystemVersion;
  98.     WORD MinorSubsystemVersion;
  99.     DWORD Win32VersionValue;
  100.     DWORD SizeOfImage;
  101.     DWORD SizeOfHeaders;
  102.     DWORD CheckSum;
  103.     WORD Subsystem;
  104.     WORD DllCharacteristics;
  105.     DWORD SizeOfStackReserve;
  106.     DWORD SizeOfStackCommit;
  107.     DWORD SizeOfHeapReserve;
  108.     DWORD SizeOfHeapCommit;
  109.     DWORD LoaderFlags;
  110.     DWORD NumberOfRvaAndSizes;
  111.     IMAGE_DATA_DIRECTORY DataDirectory[16];
  112.  
  113. } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
  114.  
  115.  
  116. #define IMAGE_DIRECTORY_ENTRY_EXPORT          0 /* Export Directory */
  117. #define IMAGE_DIRECTORY_ENTRY_IMPORT          1 /* Import Directory */
  118. #define IMAGE_DIRECTORY_ENTRY_RESOURCE        2 /* Resource Directory */
  119. #define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3 /* Exception Directory */
  120. #define IMAGE_DIRECTORY_ENTRY_SECURITY        4 /* Security Directory */
  121. #define IMAGE_DIRECTORY_ENTRY_BASERELOC       5 /* Base Relocation Table */
  122. #define IMAGE_DIRECTORY_ENTRY_DEBUG           6 /* Debug Directory */
  123. /*      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7      (X86 usage) */
  124. #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7 /* Architecture Specific Data */
  125. #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8 /* RVA of GP */
  126. #define IMAGE_DIRECTORY_ENTRY_TLS             9 /* TLS Directory */
  127. #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10 /* Load Configuration Directory */
  128. #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11 /* Bound Import Directory in headers */
  129. #define IMAGE_DIRECTORY_ENTRY_IAT            12 /* Import Address Table */
  130. #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13 /* Delay Load Import Descriptors */
  131. #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 /* COM Runtime descriptor */
  132.  
  133. /* Section header format. */
  134. #define IMAGE_SIZEOF_SHORT_NAME              8
  135.  
  136. typedef struct _IMAGE_SECTION_HEADER {
  137.     BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
  138.     union {
  139.         DWORD PhysicalAddress;
  140.         DWORD VirtualSize;
  141.     } Misc;
  142.     DWORD VirtualAddress;
  143.     DWORD SizeOfRawData;
  144.     DWORD PointerToRawData;
  145.     DWORD PointerToRelocations;
  146.     DWORD PointerToLinenumbers;
  147.     WORD NumberOfRelocations;
  148.     WORD NumberOfLinenumbers;
  149.     DWORD Characteristics;
  150. } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  151.  
  152. #define IMAGE_SIZEOF_SECTION_HEADER          40
  153.  
  154. /* ----------------------------------------------------------- */
  155. typedef struct _IMAGE_BASE_RELOCATION {
  156.     DWORD VirtualAddress;
  157.     DWORD SizeOfBlock;
  158. //  WORD    TypeOffset[1];
  159. } IMAGE_BASE_RELOCATION;
  160.  
  161. #define IMAGE_SIZEOF_BASE_RELOCATION         8
  162.  
  163. #define IMAGE_REL_BASED_ABSOLUTE              0
  164. #define IMAGE_REL_BASED_HIGH                  1
  165. #define IMAGE_REL_BASED_LOW                   2
  166. #define IMAGE_REL_BASED_HIGHLOW               3
  167. #define IMAGE_REL_BASED_HIGHADJ               4
  168. #define IMAGE_REL_BASED_MIPS_JMPADDR          5
  169. #define IMAGE_REL_BASED_SECTION               6
  170. #define IMAGE_REL_BASED_REL32                 7
  171.  
  172. /* ----------------------------------------------------------- */
  173.  
  174. /* ----------------------------------------------------------- */
  175. IMAGE_DOS_HEADER pe_dos_hdr = {
  176.     0x5A4D,                     /*WORD e_magic;         Magic number */
  177.     0x0090,                     /*WORD e_cblp;          Bytes on last page of file */
  178.     0x0003,                     /*WORD e_cp;            Pages in file */
  179.     0x0000,                     /*WORD e_crlc;          Relocations */
  180.  
  181.     0x0004,                     /*WORD e_cparhdr;       Size of header in paragraphs */
  182.     0x0000,                     /*WORD e_minalloc;      Minimum extra paragraphs needed */
  183.     0xFFFF,                     /*WORD e_maxalloc;      Maximum extra paragraphs needed */
  184.     0x0000,                     /*WORD e_ss;            Initial (relative) SS value */
  185.  
  186.     0x00B8,                     /*WORD e_sp;            Initial SP value */
  187.     0x0000,                     /*WORD e_csum;          Checksum */
  188.     0x0000,                     /*WORD e_ip;            Initial IP value */
  189.     0x0000,                     /*WORD e_cs;            Initial (relative) CS value */
  190.     0x0040,                     /*WORD e_lfarlc;        File address of relocation table */
  191.     0x0000,                     /*WORD e_ovno;          Overlay number */
  192.     {0, 0, 0, 0},               /*WORD e_res[4];     Reserved words */
  193.     0x0000,                     /*WORD e_oemid;         OEM identifier (for e_oeminfo) */
  194.     0x0000,                     /*WORD e_oeminfo;       OEM information; e_oemid specific */
  195.     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},     /*WORD e_res2[10];      Reserved words */
  196.     0x00000080,                 /*DWORD   e_lfanew;        File address of new exe header */
  197.     {                           /* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */
  198.      /*0040 */ 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8,
  199.      0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
  200.      /*0050 */ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
  201.      0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
  202.      /*0060 */ 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69,
  203.      0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
  204.      /*0070 */ 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00,
  205.      0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  206.      /*0080 */
  207.      }
  208. };
  209.  
  210. DWORD pe_magic = IMAGE_NT_SIGNATURE;
  211.  
  212. IMAGE_FILE_HEADER pe_file_hdr = {
  213.     0x014C,                     /*WORD    Machine; */
  214.     0x0003,                     /*WORD    NumberOfSections; */
  215.     0x00000000,                 /*DWORD   TimeDateStamp; */
  216.     0x00000000,                 /*DWORD   PointerToSymbolTable; */
  217.     0x00000000,                 /*DWORD   NumberOfSymbols; */
  218.     0x00E0,                     /*WORD    SizeOfOptionalHeader; */
  219.     0x030F                      /*WORD    Characteristics; */
  220. };
  221.  
  222. IMAGE_OPTIONAL_HEADER32 pe_opt_hdr = {
  223.     /* Standard fields. */
  224.     0x010B,                     /*WORD    Magic; */
  225.     0x06,                       /*BYTE    MajorLinkerVersion; */
  226.     0x00,                       /*BYTE    MinorLinkerVersion; */
  227.     0x00000000,                 /*DWORD   SizeOfCode; */
  228.     0x00000000,                 /*DWORD   SizeOfInitializedData; */
  229.     0x00000000,                 /*DWORD   SizeOfUninitializedData; */
  230.     0x00000000,                 /*DWORD   AddressOfEntryPoint; */
  231.     0x00000000,                 /*DWORD   BaseOfCode; */
  232.     0x00000000,                 /*DWORD   BaseOfData; */
  233.  
  234.     /* NT additional fields. */
  235.     0x00400000,                 /*DWORD   ImageBase; */
  236.     0x00001000,                 /*DWORD   SectionAlignment; */
  237.     0x00000200,                 /*DWORD   FileAlignment; */
  238.     0x0004,                     /*WORD    MajorOperatingSystemVersion; */
  239.     0x0000,                     /*WORD    MinorOperatingSystemVersion; */
  240.     0x0000,                     /*WORD    MajorImageVersion; */
  241.     0x0000,                     /*WORD    MinorImageVersion; */
  242.     0x0004,                     /*WORD    MajorSubsystemVersion; */
  243.     0x0000,                     /*WORD    MinorSubsystemVersion; */
  244.     0x00000000,                 /*DWORD   Win32VersionValue; */
  245.     0x00000000,                 /*DWORD   SizeOfImage; */
  246.     0x00000200,                 /*DWORD   SizeOfHeaders; */
  247.     0x00000000,                 /*DWORD   CheckSum; */
  248.     0x0002,                     /*WORD    Subsystem; */
  249.     0x0000,                     /*WORD    DllCharacteristics; */
  250.     0x00100000,                 /*DWORD   SizeOfStackReserve; */
  251.     0x00001000,                 /*DWORD   SizeOfStackCommit; */
  252.     0x00100000,                 /*DWORD   SizeOfHeapReserve; */
  253.     0x00001000,                 /*DWORD   SizeOfHeapCommit; */
  254.     0x00000000,                 /*DWORD   LoaderFlags; */
  255.     0x00000010,                 /*DWORD   NumberOfRvaAndSizes; */
  256.  
  257.     /* IMAGE_DATA_DIRECTORY DataDirectory[16]; */
  258.     {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
  259.      {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}
  260. };
  261.  
  262. /*----------------------------------------------------------------------------*/
  263.  
  264. /*----------------------------------------------------------------------------*/
  265.  
  266. struct pe_import_header {
  267.     DWORD first_entry;
  268.     DWORD time_date;
  269.     DWORD forwarder;
  270.     DWORD lib_name_offset;
  271.     DWORD first_thunk;
  272. };
  273.  
  274. struct pe_export_header {
  275.     DWORD Characteristics;
  276.     DWORD TimeDateStamp;
  277.     DWORD Version;
  278.     DWORD Name;
  279.     DWORD Base;
  280.     DWORD NumberOfFunctions;
  281.     DWORD NumberOfNames;
  282.     DWORD AddressOfFunctions;
  283.     DWORD AddressOfNames;
  284.     DWORD AddressOfNameOrdinals;
  285. };
  286.  
  287. struct pe_reloc_header {
  288.     DWORD offset;
  289.     DWORD size;
  290. };
  291.  
  292. /* ------------------------------------------------------------- */
  293. /* internal temporary structures */
  294.  
  295. ST const char *pe_sec_names[] = {
  296.     ".text",
  297.     ".data",
  298.     ".bss",
  299.     ".rsrc",
  300.     ".reloc",
  301.     ".stab",
  302.     ".stabstr"
  303. };
  304.  
  305. enum {
  306.     sec_text = 0,
  307.     sec_data,
  308.     sec_bss,
  309.     sec_rsrc,
  310.     sec_reloc,
  311.     sec_stab,
  312.     sec_stabstr,
  313.     pe_sec_number
  314. };
  315.  
  316. ST DWORD pe_flags[] = {
  317.     0x60000020,                 /* ".text", */
  318.     0xC0000040,                 /* ".data", */
  319.     0xC0000080,                 /* ".bss", */
  320.     0x40000040,                 /* ".rsrc", */
  321.     0x42000040,                 /* ".reloc", */
  322.     0x42000802,                 /* ".stab", */
  323.     0x42000802                  /* ".stabstr", */
  324. };
  325.  
  326. struct section_info {
  327.     struct section_info *next;
  328.     int id;
  329.     DWORD sh_addr;
  330.     DWORD sh_size;
  331.     unsigned char *data;
  332.     DWORD data_size;
  333. };
  334.  
  335. struct import_symbol {
  336.     int sym_index;
  337.     int offset;
  338. };
  339.  
  340. struct pe_import_info {
  341.     int dll_index;
  342.     int sym_count;
  343.     struct import_symbol **symbols;
  344. };
  345.  
  346. struct pe_info {
  347.     const char *filename;
  348.     DWORD sizeofheaders;
  349.     DWORD imagebase;
  350.     DWORD start_addr;
  351.     DWORD imp_offs;
  352.     DWORD imp_size;
  353.     DWORD iat_offs;
  354.     DWORD iat_size;
  355.     DWORD exp_offs;
  356.     DWORD exp_size;
  357.     struct section_info sh_info[pe_sec_number];
  358.     int sec_count;
  359.     struct pe_import_info **imp_info;
  360.     int imp_count;
  361.     Section *reloc;
  362.     Section *thunk;
  363.     TCCState *s1;
  364. };
  365.  
  366. /* ------------------------------------------------------------- */
  367. #define PE_MERGE_DATA
  368. // #define PE_PRINT_SECTIONS
  369.  
  370. #ifndef MAX_PATH
  371. #define MAX_PATH 260
  372. #endif
  373.  
  374. void error_noabort(const char *, ...);
  375.  
  376. ST char pe_type;
  377.  
  378. #define PE_NUL 0
  379. #define PE_DLL 1
  380. #define PE_GUI 2
  381. #define PE_EXE 3
  382.  
  383. ST int pe_find_import(TCCState * s1, const char *symbol, char *ret)
  384. {
  385.     int sym_index = find_elf_sym(s1->dynsymtab_section, symbol);
  386.     if (0 == sym_index) {
  387.         /* Hm, maybe it's '_symbol' instead of 'symbol' or '__imp__symbol' */
  388.         char buffer[100];
  389.         if (0 == memcmp(symbol, "__imp__", 7))
  390.             symbol += 6;
  391.         else
  392.             buffer[0] = '_', strcpy(buffer + 1, symbol), symbol = buffer;
  393.         sym_index = find_elf_sym(s1->dynsymtab_section, symbol);
  394.     }
  395.     if (ret)
  396.         strcpy(ret, symbol);
  397.     return sym_index;
  398. }
  399.  
  400. #ifdef WIN32
  401. ST void **pe_imp;
  402. ST int nb_pe_imp;
  403.  
  404. void *resolve_sym(struct TCCState *s1, const char *symbol, int type)
  405. {
  406.     char buffer[100], *p = buffer;
  407.     void *a = NULL;
  408.     int sym_index = pe_find_import(s1, symbol, p);
  409.     int dll_index;
  410.     const char *dll_name;
  411.     void *hm;
  412.  
  413.     if (sym_index) {
  414.         dll_index = ((Elf32_Sym *) s1->dynsymtab_section->data)[sym_index].
  415.             st_other;
  416.         dll_name = s1->loaded_dlls[dll_index]->name;
  417.         hm = GetModuleHandleA(dll_name);
  418.         if (NULL == hm)
  419.             hm = LoadLibraryA(dll_name);
  420.         if (hm) {
  421.             a = GetProcAddress(hm, buffer);
  422.             if (a && STT_OBJECT == type) {
  423.                 // need to return a pointer to the address for data objects
  424.                 dynarray_add(&pe_imp, &nb_pe_imp, a);
  425.                 a = &pe_imp[nb_pe_imp - 1];
  426.             }
  427.         }
  428.     }
  429.     return a;
  430. }
  431. #endif
  432.  
  433. #define for_sym_in_symtab(sym) \
  434. for (sym = (Elf32_Sym *)symtab_section->data + 1; \
  435.          sym < (Elf32_Sym *)(symtab_section->data + \
  436.                 symtab_section->data_offset); \
  437.          ++sym)
  438.  
  439. #define pe_set_datadir(dir,addr,size) \
  440.         pe_opt_hdr.DataDirectory[dir].VirtualAddress = addr, \
  441.         pe_opt_hdr.DataDirectory[dir].Size = size
  442.  
  443. /*----------------------------------------------------------------------------*/
  444. ST void dynarray_reset(void ***pp, int *n)
  445. {
  446.     int i;
  447.     for (i = 0; i < *n; ++i)
  448.         tcc_free((*pp)[i]);
  449.     tcc_free(*pp);
  450.     *pp = NULL;
  451.     *n = 0;
  452. }
  453.  
  454. ST int dynarray_assoc(void **pp, int n, int key)
  455. {
  456.     int i;
  457.     for (i = 0; i < n; ++i, ++pp)
  458.         if (key == **(int **) pp)
  459.             return i;
  460.     return -1;
  461. }
  462.  
  463. #if 0
  464. ST DWORD umin(DWORD a, DWORD b)
  465. {
  466.     return a < b ? a : b;
  467. }
  468. #endif
  469.  
  470. ST DWORD umax(DWORD a, DWORD b)
  471. {
  472.     return a < b ? b : a;
  473. }
  474.  
  475. ST void pe_fpad(FILE * fp, DWORD new_pos)
  476. {
  477.     DWORD pos = ftell(fp);
  478.     while (++pos <= new_pos)
  479.         fputc(0, fp);
  480. }
  481.  
  482. ST DWORD pe_file_align(DWORD n)
  483. {
  484.     return (n + (0x200 - 1)) & ~(0x200 - 1);
  485. }
  486.  
  487. ST DWORD pe_virtual_align(DWORD n)
  488. {
  489.     return (n + (0x1000 - 1)) & ~(0x1000 - 1);
  490. }
  491.  
  492. ST void pe_align_section(Section * s, int a)
  493. {
  494.     int i = s->data_offset & (a - 1);
  495.     if (i)
  496.         section_ptr_add(s, a - i);
  497. }
  498.  
  499.  
  500. /*----------------------------------------------------------------------------*/
  501. ST int pe_write_pe(struct pe_info *pe)
  502. {
  503.     int i;
  504.     FILE *op;
  505.     DWORD file_offset;
  506.     IMAGE_SECTION_HEADER ish[pe_sec_number], *psh;
  507.     int sec_index = 0;
  508.  
  509.     op = fopen(pe->filename, "wb");
  510.     if (NULL == op) {
  511.         error_noabort("could not create file: %s", pe->filename);
  512.         return 1;
  513.     }
  514.  
  515.     memset(&ish, 0, sizeof ish);
  516.  
  517.     pe->sizeofheaders = pe_file_align(sizeof pe_dos_hdr
  518.                                       + sizeof pe_magic
  519.                                       + sizeof pe_file_hdr
  520.                                       + sizeof pe_opt_hdr
  521.                                       +
  522.                                       pe->sec_count *
  523.                                       sizeof(IMAGE_SECTION_HEADER)
  524.         );
  525.  
  526.     file_offset = pe->sizeofheaders;
  527.     pe_fpad(op, file_offset);
  528.  
  529.     if (2 == verbose)
  530.         printf("-------------------------------"
  531.                "\n  virt   file   size  section" "\n");
  532.  
  533.     for (i = 0; i < pe->sec_count; ++i) {
  534.         struct section_info *si = pe->sh_info + i;
  535.         const char *sh_name = pe_sec_names[si->id];
  536.         unsigned long addr = si->sh_addr - pe->imagebase;
  537.         unsigned long size = si->sh_size;
  538.  
  539.         if (2 == verbose)
  540.             printf("%6lx %6lx %6lx  %s\n",
  541.                    addr, file_offset, size, sh_name);
  542.  
  543.         switch (si->id) {
  544.         case sec_text:
  545.             pe_opt_hdr.BaseOfCode = addr;
  546.             pe_opt_hdr.AddressOfEntryPoint = addr + pe->start_addr;
  547.             break;
  548.  
  549.         case sec_data:
  550.             pe_opt_hdr.BaseOfData = addr;
  551.             if (pe->imp_size) {
  552.                 pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT,
  553.                                pe->imp_offs + addr, pe->imp_size);
  554.                 pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT,
  555.                                pe->iat_offs + addr, pe->iat_size);
  556.             }
  557.             if (pe->exp_size) {
  558.                 pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT,
  559.                                pe->exp_offs + addr, pe->exp_size);
  560.             }
  561.             break;
  562.  
  563.         case sec_bss:
  564.             break;
  565.  
  566.         case sec_reloc:
  567.             pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
  568.             break;
  569.  
  570.         case sec_rsrc:
  571.             pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
  572.             break;
  573.  
  574.         case sec_stab:
  575.             break;
  576.  
  577.         case sec_stabstr:
  578.             break;
  579.         }
  580.  
  581.         psh = &ish[sec_index++];
  582.         strcpy((char *) psh->Name, sh_name);
  583.  
  584.         psh->Characteristics = pe_flags[si->id];
  585.         psh->VirtualAddress = addr;
  586.         psh->Misc.VirtualSize = size;
  587.         pe_opt_hdr.SizeOfImage =
  588.             umax(psh->VirtualAddress + psh->Misc.VirtualSize,
  589.                  pe_opt_hdr.SizeOfImage);
  590.  
  591.         if (si->data_size) {
  592.             psh->PointerToRawData = file_offset;
  593.             fwrite(si->data, 1, si->data_size, op);
  594.             file_offset = pe_file_align(file_offset + si->data_size);
  595.             psh->SizeOfRawData = file_offset - psh->PointerToRawData;
  596.             pe_fpad(op, file_offset);
  597.         }
  598.     }
  599.  
  600.         /*----------------------------------------------------- */
  601.  
  602.     pe_file_hdr.NumberOfSections = sec_index;
  603.     pe_opt_hdr.SizeOfHeaders = pe->sizeofheaders;
  604.     pe_opt_hdr.ImageBase = pe->imagebase;
  605.     if (PE_DLL == pe_type)
  606.         pe_file_hdr.Characteristics = 0x230E;
  607.     else if (PE_GUI != pe_type)
  608.         pe_opt_hdr.Subsystem = 3;
  609.  
  610.     fseek(op, SEEK_SET, 0);
  611.     fwrite(&pe_dos_hdr, 1, sizeof pe_dos_hdr, op);
  612.     fwrite(&pe_magic, 1, sizeof pe_magic, op);
  613.     fwrite(&pe_file_hdr, 1, sizeof pe_file_hdr, op);
  614.     fwrite(&pe_opt_hdr, 1, sizeof pe_opt_hdr, op);
  615.     for (i = 0; i < sec_index; ++i)
  616.         fwrite(&ish[i], 1, sizeof(IMAGE_SECTION_HEADER), op);
  617.     fclose(op);
  618.  
  619.     if (2 == verbose)
  620.         printf("-------------------------------\n");
  621.     if (verbose)
  622.         printf("<-- %s (%lu bytes)\n", pe->filename, file_offset);
  623.  
  624.     return 0;
  625. }
  626.  
  627. /*----------------------------------------------------------------------------*/
  628. ST int pe_add_import(struct pe_info *pe, int sym_index, DWORD offset)
  629. {
  630.     int i;
  631.     int dll_index;
  632.     struct pe_import_info *p;
  633.     struct import_symbol *s;
  634.  
  635.     dll_index =
  636.         ((Elf32_Sym *) pe->s1->dynsymtab_section->data)[sym_index].
  637.         st_other;
  638.     i = dynarray_assoc((void **) pe->imp_info, pe->imp_count, dll_index);
  639.     if (-1 != i) {
  640.         p = pe->imp_info[i];
  641.         goto found_dll;
  642.     }
  643.     p = tcc_mallocz(sizeof *p);
  644.     p->dll_index = dll_index;
  645.     dynarray_add((void ***) &pe->imp_info, &pe->imp_count, p);
  646.  
  647.   found_dll:
  648.     i = dynarray_assoc((void **) p->symbols, p->sym_count, sym_index);
  649.     if (-1 != i)
  650.         goto found_sym;
  651.     s = tcc_mallocz(sizeof *s);
  652.     s->sym_index = sym_index;
  653.     s->offset = offset;
  654.     dynarray_add((void ***) &p->symbols, &p->sym_count, s);
  655.  
  656.   found_sym:
  657.     return 1;
  658. }
  659.  
  660. /*----------------------------------------------------------------------------*/
  661. ST void pe_build_imports(struct pe_info *pe)
  662. {
  663.     int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
  664.     DWORD voffset = pe->thunk->sh_addr - pe->imagebase;
  665.     int ndlls = pe->imp_count;
  666.  
  667.     for (sym_cnt = i = 0; i < ndlls; ++i)
  668.         sym_cnt += pe->imp_info[i]->sym_count;
  669.  
  670.     if (0 == sym_cnt)
  671.         return;
  672.  
  673.     pe_align_section(pe->thunk, 16);
  674.  
  675.     pe->imp_offs = dll_ptr = pe->thunk->data_offset;
  676.     pe->imp_size = (ndlls + 1) * sizeof(struct pe_import_header);
  677.     pe->iat_offs = dll_ptr + pe->imp_size;
  678.     pe->iat_size = (sym_cnt + ndlls) * sizeof(DWORD);
  679.     section_ptr_add(pe->thunk, pe->imp_size + 2 * pe->iat_size);
  680.  
  681.     thk_ptr = pe->iat_offs;
  682.     ent_ptr = pe->iat_offs + pe->iat_size;
  683.     for (i = 0; i < pe->imp_count; ++i) {
  684.         struct pe_import_header *hdr;
  685.         int k, n, v;
  686.         struct pe_import_info *p = pe->imp_info[i];
  687.         const char *name = pe->s1->loaded_dlls[p->dll_index]->name;
  688.  
  689.         /* put the dll name into the import header */
  690.         if (0 == strncmp(name, "lib", 3))
  691.             name += 3;
  692.         v = put_elf_str(pe->thunk, name);
  693.  
  694.         hdr = (struct pe_import_header *) (pe->thunk->data + dll_ptr);
  695.         hdr->first_thunk = thk_ptr + voffset;
  696.         hdr->first_entry = ent_ptr + voffset;
  697.         hdr->lib_name_offset = v + voffset;
  698.  
  699.         for (k = 0, n = p->sym_count; k <= n; ++k) {
  700.             if (k < n) {
  701.                 DWORD offset = p->symbols[k]->offset;
  702.                 int sym_index = p->symbols[k]->sym_index;
  703.                 Elf32_Sym *sym =
  704.                     (Elf32_Sym *) pe->s1->dynsymtab_section->data +
  705.                     sym_index;
  706.                 const char *name =
  707.                     pe->s1->dynsymtab_section->link->data + sym->st_name;
  708.  
  709.                 if (offset & 0x80000000) {      /* ref to data */
  710.                     Elf32_Sym *sym =
  711.                         &((Elf32_Sym *) symtab_section->
  712.                           data)[offset & 0x7FFFFFFF];
  713.                     sym->st_value = thk_ptr;
  714.                     sym->st_shndx = pe->thunk->sh_num;
  715.                 } else {        /* ref to function */
  716.  
  717.                     char buffer[100];
  718.                     sprintf(buffer, "IAT.%s", name);
  719.                     sym_index =
  720.                         put_elf_sym(symtab_section, thk_ptr, sizeof(DWORD),
  721.                                     ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
  722.                                     0, pe->thunk->sh_num, buffer);
  723.  
  724.                     put_elf_reloc(symtab_section, text_section, offset, R_386_32,       /*R_JMP_SLOT, */
  725.                                   sym_index);
  726.                 }
  727.                 v = pe->thunk->data_offset + voffset;
  728.                 section_ptr_add(pe->thunk, sizeof(WORD));       /* hint, not used */
  729.                 put_elf_str(pe->thunk, name);
  730.             } else {
  731.                 v = 0;          // last entry is zero
  732.             }
  733.             *(DWORD *) (pe->thunk->data + thk_ptr) =
  734.                 *(DWORD *) (pe->thunk->data + ent_ptr) = v;
  735.             thk_ptr += sizeof(DWORD);
  736.             ent_ptr += sizeof(DWORD);
  737.         }
  738.         dll_ptr += sizeof(struct pe_import_header);
  739.         dynarray_reset((void ***) &p->symbols, &p->sym_count);
  740.     }
  741.     dynarray_reset((void ***) &pe->imp_info, &pe->imp_count);
  742. }
  743.  
  744. /* ------------------------------------------------------------- */
  745. ST int sym_cmp(const void *va, const void *vb)
  746. {
  747.     Elf32_Sym *sa = (Elf32_Sym *)symtab_section->data + *(int*)va;
  748.     Elf32_Sym *sb = (Elf32_Sym *)symtab_section->data + *(int*)vb;
  749.     const char *ca = symtab_section->link->data + sa->st_name;
  750.     const char *cb = symtab_section->link->data + sb->st_name;
  751.     return strcmp(ca, cb);
  752. }
  753.  
  754. ST void pe_build_exports(struct pe_info *pe)
  755. {
  756.     Elf32_Sym *sym;
  757.     DWORD func_offset, voffset;
  758.     struct pe_export_header *hdr;
  759.     int sym_count, n, ord, *sorted;
  760.  
  761.     voffset = pe->thunk->sh_addr - pe->imagebase;
  762.     sym_count = 0, n = 1, sorted = NULL;
  763.  
  764.     // for simplicity only functions are exported
  765.     for_sym_in_symtab(sym)
  766.     {
  767.         if ((sym->st_other & 1)
  768.             && sym->st_shndx == text_section->sh_num)
  769.             dynarray_add((void***)&sorted, &sym_count, (void*)n);
  770.         ++n;
  771.     }
  772.  
  773.     if (0 == sym_count)
  774.         return;
  775.  
  776.     qsort (sorted, sym_count, sizeof sorted[0], sym_cmp);
  777.     pe_align_section(pe->thunk, 16);
  778.  
  779.     pe->exp_offs = pe->thunk->data_offset;
  780.     hdr = section_ptr_add(pe->thunk,
  781.                           sizeof(struct pe_export_header) +
  782.                           sym_count * (2 * sizeof(DWORD) + sizeof(WORD)));
  783.  
  784.     func_offset = pe->exp_offs + sizeof(struct pe_export_header);
  785.  
  786.     hdr->Characteristics = 0;
  787.     hdr->Base = 1;
  788.     hdr->NumberOfFunctions = sym_count;
  789.     hdr->NumberOfNames = sym_count;
  790.     hdr->AddressOfFunctions = func_offset + voffset;
  791.     hdr->AddressOfNames         = hdr->AddressOfFunctions + sym_count * sizeof(DWORD);
  792.     hdr->AddressOfNameOrdinals  = hdr->AddressOfNames + sym_count * sizeof(DWORD);
  793.     hdr->Name = pe->thunk->data_offset + voffset;
  794.     put_elf_str(pe->thunk, tcc_basename(pe->filename));
  795.  
  796.     for (ord = 0; ord < sym_count; ++ord)
  797.     {
  798.         char *name; DWORD *p, *pfunc, *pname; WORD *pord;
  799.         sym = (Elf32_Sym *)symtab_section->data + sorted[ord];
  800.         name = symtab_section->link->data + sym->st_name;
  801.         p = (DWORD*)(pe->thunk->data + func_offset);
  802.         pfunc = p + ord;
  803.         pname = p + sym_count + ord;
  804.         pord = (WORD *)(p + 2*sym_count) + ord;
  805.         *pfunc = sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - pe->imagebase;
  806.         *pname = pe->thunk->data_offset + voffset;
  807.         *pord  = ord;
  808.         put_elf_str(pe->thunk, name);
  809.         /* printf("export: %s\n", name); */
  810.     }
  811.     pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
  812.     tcc_free(sorted);
  813. }
  814.  
  815. /* ------------------------------------------------------------- */
  816. ST void pe_build_reloc(struct pe_info *pe, int *section_order,
  817.                        int section_count)
  818. {
  819.     DWORD offset, block_ptr, addr;
  820.     int count, i;
  821.     Elf32_Rel *rel, *rel_end;
  822.     Section *s = NULL, *sr;
  823.     offset = addr = block_ptr = count = i = 0;
  824.     rel = rel_end = NULL;
  825.     for (;;) {
  826.         if (rel < rel_end) {
  827.             int type = ELF32_R_TYPE(rel->r_info);
  828.             addr = rel->r_offset + s->sh_addr;
  829.             ++rel;
  830.             if (type != R_386_32)
  831.                 continue;
  832.             if (count == 0) {   /* new block */
  833.                 block_ptr = pe->reloc->data_offset;
  834.                 section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
  835.                 offset = addr & 0xFFFFFFFF << 12;
  836.             }
  837.             if ((addr -= offset) < (1 << 12)) { /* one block spans 4k addresses */
  838.                 WORD *wp = section_ptr_add(pe->reloc, sizeof(WORD));
  839.                 *wp = addr | IMAGE_REL_BASED_HIGHLOW << 12;
  840.                 ++count;
  841.                 continue;
  842.             }
  843.             --rel;
  844.         } else if (i < section_count) {
  845.             sr = (s = pe->s1->sections[section_order[i++]])->reloc;
  846.             if (sr) {
  847.                 rel = (Elf32_Rel *) sr->data;
  848.                 rel_end = (Elf32_Rel *) (sr->data + sr->data_offset);
  849.             }
  850.             continue;
  851.         }
  852.  
  853.         if (count) {            /* store the last block and ready for a new one */
  854.             struct pe_reloc_header *hdr;
  855.             if (count & 1)
  856.                 section_ptr_add(pe->reloc, 2), ++count;
  857.             hdr = (struct pe_reloc_header *) (pe->reloc->data + block_ptr);
  858.             hdr->offset = offset - pe->imagebase;
  859.             hdr->size =
  860.                 count * sizeof(WORD) + sizeof(struct pe_reloc_header);
  861.             count = 0;
  862.         }
  863.         if (rel >= rel_end)
  864.             break;
  865.     }
  866. }
  867.  
  868. /* ------------------------------------------------------------- */
  869. ST int pe_assign_addresses(struct pe_info *pe)
  870. {
  871.     int i, k, n;
  872.     DWORD addr;
  873.     int section_order[pe_sec_number];
  874.     struct section_info *si_data = NULL;
  875.  
  876.     pe->imagebase = PE_DLL == pe_type ? 0x10000000 : 0x00400000;
  877.     addr = pe->imagebase + 1;
  878.  
  879.     if (PE_DLL == pe_type)
  880.         pe->reloc = new_section(pe->s1, ".reloc", SHT_DYNAMIC, SHF_ALLOC);
  881.  
  882.     for (n = k = 0; n < pe_sec_number; ++n) {
  883.         for (i = 1; i < pe->s1->nb_sections; ++i) {
  884.             Section *s = pe->s1->sections[i];
  885.             if (0 == strcmp(s->name, pe_sec_names[n])) {
  886.                 struct section_info *si = &pe->sh_info[pe->sec_count];
  887. #ifdef PE_MERGE_DATA
  888.                 if (n == sec_bss && si_data) {
  889.                     /* append .bss to .data */
  890.                     s->sh_addr = addr = ((addr - 1) | 15) + 1;
  891.                     addr += s->data_offset;
  892.                     si_data->sh_size = addr - si_data->sh_addr;
  893.                 } else
  894. #endif
  895.                 {
  896.                     si->sh_addr = s->sh_addr = addr =
  897.                         pe_virtual_align(addr);
  898.                     si->id = n;
  899.  
  900.                     if (n == sec_data) {
  901.                         pe->thunk = s;
  902.                         si_data = si;
  903.                         pe_build_imports(pe);
  904.                         pe_build_exports(pe);
  905.                     } else if (n == sec_reloc) {
  906.                         pe_build_reloc(pe, section_order, k);
  907.                     }
  908.  
  909.                     if (s->data_offset) {
  910.                         if (n != sec_bss) {
  911.                             si->data = s->data;
  912.                             si->data_size = s->data_offset;
  913.                         }
  914.  
  915.                         addr += s->data_offset;
  916.                         si->sh_size = s->data_offset;
  917.                         ++pe->sec_count;
  918.                     }
  919.                     //printf("Section %08X %04X %s\n", si->sh_addr, si->data_size, s->name);
  920.                 }
  921.                 section_order[k] = i, ++k;
  922.             }
  923.         }
  924.     }
  925.     return 0;
  926. }
  927.  
  928. /*----------------------------------------------------------------------------*/
  929. ST int pe_check_symbols(struct pe_info *pe)
  930. {
  931.     Elf32_Sym *sym;
  932.     int ret = 0;
  933.  
  934.     pe_align_section(text_section, 8);
  935.  
  936.     for_sym_in_symtab(sym) {
  937.         if (sym->st_shndx == SHN_UNDEF) {
  938.             const char *symbol = symtab_section->link->data + sym->st_name;
  939.             unsigned type = ELF32_ST_TYPE(sym->st_info);
  940.             int sym_index = pe_find_import(pe->s1, symbol, NULL);
  941.             if (sym_index) {
  942.                 if (type == STT_FUNC) {
  943.                     unsigned long offset = text_section->data_offset;
  944.                     if (pe_add_import(pe, sym_index, offset + 2)) {
  945.                         /* add the 'jmp IAT[x]' instruction */
  946.                         *(WORD *) section_ptr_add(text_section, 8) =
  947.                             0x25FF;
  948.                         /* patch the symbol */
  949.                         sym->st_shndx = text_section->sh_num;
  950.                         sym->st_value = offset;
  951.                         continue;
  952.                     }
  953.                 } else if (type == STT_OBJECT) {        /* data, ptr to that should be */
  954.                     if (pe_add_import(pe, sym_index,
  955.                                       (sym -
  956.                                       (Elf32_Sym *) symtab_section->data) |
  957.                                       0x80000000))
  958.                         continue;
  959.                 }
  960.             }
  961.             error_noabort("undefined symbol '%s'", symbol);
  962.             ret = 1;
  963.         } else
  964.             if (pe->s1->rdynamic
  965.                 && ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
  966.             /* if -rdynamic option, then export all non local symbols */
  967.             sym->st_other |= 1;
  968.         }
  969.     }
  970.     return ret;
  971. }
  972.  
  973. /*----------------------------------------------------------------------------*/
  974. #ifdef PE_PRINT_SECTIONS
  975. ST void pe_print_section(FILE * f, Section * s)
  976. {                               /* just if you'r curious */
  977.     BYTE *p, *e, b;
  978.     int i, n, l, m;
  979.     p = s->data;
  980.     e = s->data + s->data_offset;
  981.     l = e - p;
  982.  
  983.     fprintf(f, "section  \"%s\"", s->name);
  984.     if (s->link)
  985.         fprintf(f, "\nlink     \"%s\"", s->link->name);
  986.     if (s->reloc)
  987.         fprintf(f, "\nreloc    \"%s\"", s->reloc->name);
  988.     fprintf(f, "\nv_addr   %08X", s->sh_addr);
  989.     fprintf(f, "\ncontents %08X", l);
  990.     fprintf(f, "\n\n");
  991.  
  992.     if (s->sh_type == SHT_NOBITS)
  993.         return;
  994.  
  995.     if (s->sh_type == SHT_SYMTAB)
  996.         m = sizeof(Elf32_Sym);
  997.     if (s->sh_type == SHT_REL)
  998.         m = sizeof(Elf32_Rel);
  999.     else
  1000.         m = 16;
  1001.  
  1002.     for (i = 0; i < l;) {
  1003.         fprintf(f, "%08X", i);
  1004.         for (n = 0; n < m; ++n) {
  1005.             if (n + i < l)
  1006.                 fprintf(f, " %02X", p[i + n]);
  1007.             else
  1008.                 fprintf(f, "   ");
  1009.         }
  1010.  
  1011.         if (s->sh_type == SHT_SYMTAB) {
  1012.             Elf32_Sym *sym = (Elf32_Sym *) (p + i);
  1013.             const char *name = s->link->data + sym->st_name;
  1014.             fprintf(f,
  1015.                     "  name:%04X"
  1016.                     "  value:%04X"
  1017.                     "  size:%04X"
  1018.                     "  bind:%02X"
  1019.                     "  type:%02X"
  1020.                     "  other:%02X"
  1021.                     "  shndx:%04X"
  1022.                     "  \"%s\"",
  1023.                     sym->st_name,
  1024.                     sym->st_value,
  1025.                     sym->st_size,
  1026.                     ELF32_ST_BIND(sym->st_info),
  1027.                     ELF32_ST_TYPE(sym->st_info),
  1028.                     sym->st_other, sym->st_shndx, name);
  1029.         } else if (s->sh_type == SHT_REL) {
  1030.             Elf32_Rel *rel = (Elf32_Rel *) (p + i);
  1031.             Elf32_Sym *sym =
  1032.                 (Elf32_Sym *) s->link->data + ELF32_R_SYM(rel->r_info);
  1033.             const char *name = s->link->link->data + sym->st_name;
  1034.             fprintf(f,
  1035.                     "  offset:%04X"
  1036.                     "  type:%02X"
  1037.                     "  symbol:%04X"
  1038.                     "  \"%s\"",
  1039.                     rel->r_offset,
  1040.                     ELF32_R_TYPE(rel->r_info),
  1041.                     ELF32_R_SYM(rel->r_info), name);
  1042.         } else {
  1043.             fprintf(f, "   ");
  1044.             for (n = 0; n < m; ++n) {
  1045.                 if (n + i < l) {
  1046.                     b = p[i + n];
  1047.                     if (b < 32 || b >= 127)
  1048.                         b = '.';
  1049.                     fprintf(f, "%c", b);
  1050.                 }
  1051.             }
  1052.         }
  1053.         i += m;
  1054.         fprintf(f, "\n");
  1055.     }
  1056.     fprintf(f, "\n\n");
  1057. }
  1058. #endif
  1059.  
  1060. static int pe_test_cmd(const char **pp, const char *cmd)
  1061. {
  1062.     const char *p;
  1063.     char *q, buf[16];
  1064.     int ret;
  1065.  
  1066.     p = *pp;
  1067.     q = buf;
  1068.     while (*p != '\0' && !is_space(*p)) {
  1069.         if ((q - buf) < sizeof(buf) - 1)
  1070.             *q++ = toup(*p);
  1071.         p++;
  1072.     }
  1073.     *q = '\0';
  1074.     ret = !strcmp(buf, cmd);
  1075.     *pp = p;
  1076.     return ret;
  1077. }
  1078.  
  1079. /* ------------------------------------------------------------- */
  1080. int pe_load_def_file(TCCState * s1, FILE * fp)
  1081. {
  1082.     DLLReference *dllref;
  1083.     int f = 0, sym_index;
  1084.     char *p, line[120], dllname[40];
  1085.     while (fgets(line, sizeof line, fp)) {
  1086.         p = strchr(line, 0);
  1087.         while (p > line && p[-1] <= ' ')
  1088.             --p;
  1089.         *p = 0;
  1090.         p = line;
  1091.         while (*p && *p <= ' ')
  1092.             ++p;
  1093.  
  1094.         if (*p && ';' != *p)
  1095.             switch (f) {
  1096.             case 0:
  1097.                 if (!pe_test_cmd((const char **)&p, "LIBRARY"))
  1098.                     return -1;
  1099.                 while (is_space(*p))
  1100.                     p++;
  1101.                 pstrcpy(dllname, sizeof(dllname), p);
  1102.                 ++f;
  1103.                 continue;
  1104.  
  1105.             case 1:
  1106.                 if (!pe_test_cmd((const char **)&p, "EXPORTS"))
  1107.                     return -1;
  1108.                 ++f;
  1109.                 continue;
  1110.  
  1111.             case 2:
  1112.                 dllref =
  1113.                     tcc_malloc(sizeof(DLLReference) + strlen(dllname));
  1114.                 strcpy(dllref->name, dllname);
  1115.                 dllref->level = 0;
  1116.                 dynarray_add((void ***) &s1->loaded_dlls,
  1117.                              &s1->nb_loaded_dlls, dllref);
  1118.                 ++f;
  1119.  
  1120.             default:
  1121.                 /* tccpe needs to know from what dll it should import
  1122.                    the sym */
  1123.                 sym_index = add_elf_sym(s1->dynsymtab_section,
  1124.                                         0, 0, ELF32_ST_INFO(STB_GLOBAL,
  1125.                                                             STT_FUNC),
  1126.                                         s1->nb_loaded_dlls - 1,
  1127.                                         text_section->sh_num, p);
  1128.                 continue;
  1129.             }
  1130.     }
  1131.     return 0;
  1132. }
  1133.  
  1134. /* ------------------------------------------------------------- */
  1135. void pe_guess_outfile(char *objfilename, int output_type)
  1136. {
  1137.     char *ext = strrchr(objfilename, '.');
  1138.     if (NULL == ext)
  1139.         ext = strchr(objfilename, 0);
  1140.     if (output_type == TCC_OUTPUT_DLL)
  1141.         strcpy(ext, ".dll");
  1142.     else
  1143.     if (output_type == TCC_OUTPUT_EXE)
  1144.         strcpy(ext, ".exe");
  1145.     else
  1146.     if (output_type == TCC_OUTPUT_OBJ && strcmp(ext, ".o"))
  1147.         strcpy(ext, ".o");
  1148.     else
  1149.         error("no outputfile given");
  1150. }
  1151.  
  1152. /* ------------------------------------------------------------- */
  1153. unsigned long pe_add_runtime(TCCState * s1)
  1154. {
  1155.     const char *start_symbol;
  1156.     unsigned long addr;
  1157.  
  1158.     if (find_elf_sym(symtab_section, "WinMain"))
  1159.         pe_type = PE_GUI;
  1160.     else
  1161.     if (TCC_OUTPUT_DLL == s1->output_type)
  1162.     {
  1163.         pe_type = PE_DLL;
  1164.         // need this for 'tccelf.c:relocate_section()'
  1165.         s1->output_type = TCC_OUTPUT_EXE;
  1166.     }
  1167.  
  1168.     start_symbol =
  1169.         TCC_OUTPUT_MEMORY == s1->output_type
  1170.         ? PE_GUI == pe_type ? "_runwinmain" : NULL
  1171.         : PE_DLL == pe_type ? "_dllstart"
  1172.         : PE_GUI == pe_type ? "_winstart" : "_start";
  1173.  
  1174.     /* grab the startup code from libtcc1 */
  1175.     if (start_symbol)
  1176.         add_elf_sym(symtab_section,
  1177.                     0, 0,
  1178.                     ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
  1179.                     SHN_UNDEF, start_symbol);
  1180.  
  1181.     if (0 == s1->nostdlib) {
  1182.         tcc_add_library(s1, "tcc1");
  1183.         tcc_add_library(s1, "msvcrt");
  1184.         if (PE_DLL == pe_type || PE_GUI == pe_type) {
  1185.             tcc_add_library(s1, "kernel32");
  1186.             tcc_add_library(s1, "user32");
  1187.             tcc_add_library(s1, "gdi32");
  1188.         }
  1189.     }
  1190.  
  1191.     addr = start_symbol ?
  1192.         (unsigned long) tcc_get_symbol_err(s1, start_symbol) : 0;
  1193.  
  1194.     if (s1->output_type == TCC_OUTPUT_MEMORY && addr) {
  1195.         /* for -run GUI's, put '_runwinmain' instead of 'main' */
  1196.         add_elf_sym(symtab_section,
  1197.                     addr, 0,
  1198.                     ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
  1199.                     text_section->sh_num, "main");
  1200.  
  1201.         /* FreeConsole(); */
  1202.     }
  1203.     return addr;
  1204. }
  1205.  
  1206. int tcc_output_pe(TCCState * s1, const char *filename)
  1207. {
  1208.     int ret;
  1209.     struct pe_info pe;
  1210.     int i;
  1211.     memset(&pe, 0, sizeof pe);
  1212.     pe.filename = filename;
  1213.     pe.s1 = s1;
  1214.     pe.start_addr = pe_add_runtime(s1);
  1215.  
  1216.     relocate_common_syms();     /* assign bss adresses */
  1217.     ret = pe_check_symbols(&pe);
  1218.     if (0 == ret) {
  1219.         pe_assign_addresses(&pe);
  1220.         relocate_syms(s1, 0);
  1221.         for (i = 1; i < s1->nb_sections; ++i) {
  1222.             Section *s = s1->sections[i];
  1223.             if (s->reloc)
  1224.                 relocate_section(s1, s);
  1225.         }
  1226.         ret = pe_write_pe(&pe);
  1227.     }
  1228. #ifdef PE_PRINT_SECTIONS
  1229.     {
  1230.         Section *s;
  1231.         FILE *f;
  1232.         f = fopen("tccpe.log", "wt");
  1233.         for (i = 1; i < s1->nb_sections; ++i) {
  1234.             s = s1->sections[i];
  1235.             pe_print_section(f, s);
  1236.         }
  1237.         pe_print_section(f, s1->dynsymtab_section);
  1238.         fclose(f);
  1239.     }
  1240. #endif
  1241.     return ret;
  1242. }
  1243.  
  1244. /*----------------------------------------------------------------------------*/
  1245.