tccpe.c 46 KB

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