tccpe.c 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994
  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. #include "tcc.h"
  21. #define PE_MERGE_DATA
  22. /* #define PE_PRINT_SECTIONS */
  23. #ifndef _WIN32
  24. #define stricmp strcasecmp
  25. #define strnicmp strncasecmp
  26. #include <sys/stat.h> /* chmod() */
  27. #endif
  28. #ifdef TCC_TARGET_X86_64
  29. # define ADDR3264 ULONGLONG
  30. # define PE_IMAGE_REL IMAGE_REL_BASED_DIR64
  31. # define REL_TYPE_DIRECT R_X86_64_64
  32. # define R_XXX_THUNKFIX R_X86_64_PC32
  33. # define R_XXX_RELATIVE R_X86_64_RELATIVE
  34. # define IMAGE_FILE_MACHINE 0x8664
  35. # define RSRC_RELTYPE 3
  36. #elif defined TCC_TARGET_ARM
  37. # define ADDR3264 DWORD
  38. # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
  39. # define REL_TYPE_DIRECT R_ARM_ABS32
  40. # define R_XXX_THUNKFIX R_ARM_ABS32
  41. # define R_XXX_RELATIVE R_ARM_RELATIVE
  42. # define IMAGE_FILE_MACHINE 0x01C0
  43. # define RSRC_RELTYPE 7 /* ??? (not tested) */
  44. #elif defined TCC_TARGET_I386
  45. # define ADDR3264 DWORD
  46. # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
  47. # define REL_TYPE_DIRECT R_386_32
  48. # define R_XXX_THUNKFIX R_386_32
  49. # define R_XXX_RELATIVE R_386_RELATIVE
  50. # define IMAGE_FILE_MACHINE 0x014C
  51. # define RSRC_RELTYPE 7 /* DIR32NB */
  52. #endif
  53. #ifndef IMAGE_NT_SIGNATURE
  54. /* ----------------------------------------------------------- */
  55. /* definitions below are from winnt.h */
  56. typedef unsigned char BYTE;
  57. typedef unsigned short WORD;
  58. typedef unsigned int DWORD;
  59. typedef unsigned long long ULONGLONG;
  60. #pragma pack(push, 1)
  61. typedef struct _IMAGE_DOS_HEADER { /* DOS .EXE header */
  62. WORD e_magic; /* Magic number */
  63. WORD e_cblp; /* Bytes on last page of file */
  64. WORD e_cp; /* Pages in file */
  65. WORD e_crlc; /* Relocations */
  66. WORD e_cparhdr; /* Size of header in paragraphs */
  67. WORD e_minalloc; /* Minimum extra paragraphs needed */
  68. WORD e_maxalloc; /* Maximum extra paragraphs needed */
  69. WORD e_ss; /* Initial (relative) SS value */
  70. WORD e_sp; /* Initial SP value */
  71. WORD e_csum; /* Checksum */
  72. WORD e_ip; /* Initial IP value */
  73. WORD e_cs; /* Initial (relative) CS value */
  74. WORD e_lfarlc; /* File address of relocation table */
  75. WORD e_ovno; /* Overlay number */
  76. WORD e_res[4]; /* Reserved words */
  77. WORD e_oemid; /* OEM identifier (for e_oeminfo) */
  78. WORD e_oeminfo; /* OEM information; e_oemid specific */
  79. WORD e_res2[10]; /* Reserved words */
  80. DWORD e_lfanew; /* File address of new exe header */
  81. } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
  82. #define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
  83. #define SIZE_OF_NT_SIGNATURE 4
  84. typedef struct _IMAGE_FILE_HEADER {
  85. WORD Machine;
  86. WORD NumberOfSections;
  87. DWORD TimeDateStamp;
  88. DWORD PointerToSymbolTable;
  89. DWORD NumberOfSymbols;
  90. WORD SizeOfOptionalHeader;
  91. WORD Characteristics;
  92. } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
  93. #define IMAGE_SIZEOF_FILE_HEADER 20
  94. typedef struct _IMAGE_DATA_DIRECTORY {
  95. DWORD VirtualAddress;
  96. DWORD Size;
  97. } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
  98. typedef struct _IMAGE_OPTIONAL_HEADER {
  99. /* Standard fields. */
  100. WORD Magic;
  101. BYTE MajorLinkerVersion;
  102. BYTE MinorLinkerVersion;
  103. DWORD SizeOfCode;
  104. DWORD SizeOfInitializedData;
  105. DWORD SizeOfUninitializedData;
  106. DWORD AddressOfEntryPoint;
  107. DWORD BaseOfCode;
  108. #ifndef TCC_TARGET_X86_64
  109. DWORD BaseOfData;
  110. #endif
  111. /* NT additional fields. */
  112. ADDR3264 ImageBase;
  113. DWORD SectionAlignment;
  114. DWORD FileAlignment;
  115. WORD MajorOperatingSystemVersion;
  116. WORD MinorOperatingSystemVersion;
  117. WORD MajorImageVersion;
  118. WORD MinorImageVersion;
  119. WORD MajorSubsystemVersion;
  120. WORD MinorSubsystemVersion;
  121. DWORD Win32VersionValue;
  122. DWORD SizeOfImage;
  123. DWORD SizeOfHeaders;
  124. DWORD CheckSum;
  125. WORD Subsystem;
  126. WORD DllCharacteristics;
  127. ADDR3264 SizeOfStackReserve;
  128. ADDR3264 SizeOfStackCommit;
  129. ADDR3264 SizeOfHeapReserve;
  130. ADDR3264 SizeOfHeapCommit;
  131. DWORD LoaderFlags;
  132. DWORD NumberOfRvaAndSizes;
  133. IMAGE_DATA_DIRECTORY DataDirectory[16];
  134. } IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, IMAGE_OPTIONAL_HEADER;
  135. #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */
  136. #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */
  137. #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */
  138. #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */
  139. #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */
  140. #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */
  141. #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory */
  142. /* IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 (X86 usage) */
  143. #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 /* Architecture Specific Data */
  144. #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* RVA of GP */
  145. #define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */
  146. #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */
  147. #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */
  148. #define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
  149. #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 /* Delay Load Import Descriptors */
  150. #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 /* COM Runtime descriptor */
  151. /* Section header format. */
  152. #define IMAGE_SIZEOF_SHORT_NAME 8
  153. typedef struct _IMAGE_SECTION_HEADER {
  154. BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
  155. union {
  156. DWORD PhysicalAddress;
  157. DWORD VirtualSize;
  158. } Misc;
  159. DWORD VirtualAddress;
  160. DWORD SizeOfRawData;
  161. DWORD PointerToRawData;
  162. DWORD PointerToRelocations;
  163. DWORD PointerToLinenumbers;
  164. WORD NumberOfRelocations;
  165. WORD NumberOfLinenumbers;
  166. DWORD Characteristics;
  167. } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  168. #define IMAGE_SIZEOF_SECTION_HEADER 40
  169. typedef struct _IMAGE_EXPORT_DIRECTORY {
  170. DWORD Characteristics;
  171. DWORD TimeDateStamp;
  172. WORD MajorVersion;
  173. WORD MinorVersion;
  174. DWORD Name;
  175. DWORD Base;
  176. DWORD NumberOfFunctions;
  177. DWORD NumberOfNames;
  178. DWORD AddressOfFunctions;
  179. DWORD AddressOfNames;
  180. DWORD AddressOfNameOrdinals;
  181. } IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
  182. typedef struct _IMAGE_IMPORT_DESCRIPTOR {
  183. union {
  184. DWORD Characteristics;
  185. DWORD OriginalFirstThunk;
  186. };
  187. DWORD TimeDateStamp;
  188. DWORD ForwarderChain;
  189. DWORD Name;
  190. DWORD FirstThunk;
  191. } IMAGE_IMPORT_DESCRIPTOR;
  192. typedef struct _IMAGE_BASE_RELOCATION {
  193. DWORD VirtualAddress;
  194. DWORD SizeOfBlock;
  195. // WORD TypeOffset[1];
  196. } IMAGE_BASE_RELOCATION;
  197. #define IMAGE_SIZEOF_BASE_RELOCATION 8
  198. #define IMAGE_REL_BASED_ABSOLUTE 0
  199. #define IMAGE_REL_BASED_HIGH 1
  200. #define IMAGE_REL_BASED_LOW 2
  201. #define IMAGE_REL_BASED_HIGHLOW 3
  202. #define IMAGE_REL_BASED_HIGHADJ 4
  203. #define IMAGE_REL_BASED_MIPS_JMPADDR 5
  204. #define IMAGE_REL_BASED_SECTION 6
  205. #define IMAGE_REL_BASED_REL32 7
  206. #define IMAGE_REL_BASED_DIR64 10
  207. #pragma pack(pop)
  208. /* ----------------------------------------------------------- */
  209. #endif /* ndef IMAGE_NT_SIGNATURE */
  210. /* ----------------------------------------------------------- */
  211. #ifndef IMAGE_REL_BASED_DIR64
  212. # define IMAGE_REL_BASED_DIR64 10
  213. #endif
  214. #pragma pack(push, 1)
  215. struct pe_header
  216. {
  217. IMAGE_DOS_HEADER doshdr;
  218. BYTE dosstub[0x40];
  219. DWORD nt_sig;
  220. IMAGE_FILE_HEADER filehdr;
  221. #ifdef TCC_TARGET_X86_64
  222. IMAGE_OPTIONAL_HEADER64 opthdr;
  223. #else
  224. #ifdef _WIN64
  225. IMAGE_OPTIONAL_HEADER32 opthdr;
  226. #else
  227. IMAGE_OPTIONAL_HEADER opthdr;
  228. #endif
  229. #endif
  230. };
  231. struct pe_reloc_header {
  232. DWORD offset;
  233. DWORD size;
  234. };
  235. struct pe_rsrc_header {
  236. struct _IMAGE_FILE_HEADER filehdr;
  237. struct _IMAGE_SECTION_HEADER sectionhdr;
  238. };
  239. struct pe_rsrc_reloc {
  240. DWORD offset;
  241. DWORD size;
  242. WORD type;
  243. };
  244. #pragma pack(pop)
  245. /* ------------------------------------------------------------- */
  246. /* internal temporary structures */
  247. /*
  248. #define IMAGE_SCN_CNT_CODE 0x00000020
  249. #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
  250. #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
  251. #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
  252. #define IMAGE_SCN_MEM_SHARED 0x10000000
  253. #define IMAGE_SCN_MEM_EXECUTE 0x20000000
  254. #define IMAGE_SCN_MEM_READ 0x40000000
  255. #define IMAGE_SCN_MEM_WRITE 0x80000000
  256. */
  257. enum {
  258. sec_text = 0,
  259. sec_data ,
  260. sec_bss ,
  261. sec_idata ,
  262. sec_pdata ,
  263. sec_other ,
  264. sec_rsrc ,
  265. sec_stab ,
  266. sec_reloc ,
  267. sec_last
  268. };
  269. static const DWORD pe_sec_flags[] = {
  270. 0x60000020, /* ".text" , */
  271. 0xC0000040, /* ".data" , */
  272. 0xC0000080, /* ".bss" , */
  273. 0x40000040, /* ".idata" , */
  274. 0x40000040, /* ".pdata" , */
  275. 0xE0000060, /* < other > , */
  276. 0x40000040, /* ".rsrc" , */
  277. 0x42000802, /* ".stab" , */
  278. 0x42000040, /* ".reloc" , */
  279. };
  280. struct section_info {
  281. int cls, ord;
  282. char name[32];
  283. DWORD sh_addr;
  284. DWORD sh_size;
  285. DWORD sh_flags;
  286. unsigned char *data;
  287. DWORD data_size;
  288. IMAGE_SECTION_HEADER ish;
  289. };
  290. struct import_symbol {
  291. int sym_index;
  292. int iat_index;
  293. int thk_offset;
  294. };
  295. struct pe_import_info {
  296. int dll_index;
  297. int sym_count;
  298. struct import_symbol **symbols;
  299. };
  300. struct pe_info {
  301. TCCState *s1;
  302. Section *reloc;
  303. Section *thunk;
  304. const char *filename;
  305. int type;
  306. DWORD sizeofheaders;
  307. ADDR3264 imagebase;
  308. const char *start_symbol;
  309. DWORD start_addr;
  310. DWORD imp_offs;
  311. DWORD imp_size;
  312. DWORD iat_offs;
  313. DWORD iat_size;
  314. DWORD exp_offs;
  315. DWORD exp_size;
  316. int subsystem;
  317. DWORD section_align;
  318. DWORD file_align;
  319. struct section_info *sec_info;
  320. int sec_count;
  321. struct pe_import_info **imp_info;
  322. int imp_count;
  323. };
  324. #define PE_NUL 0
  325. #define PE_DLL 1
  326. #define PE_GUI 2
  327. #define PE_EXE 3
  328. #define PE_RUN 4
  329. /* --------------------------------------------*/
  330. static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym)
  331. {
  332. const char *name = (char*)symtab_section->link->data + sym->st_name;
  333. if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
  334. return name + 1;
  335. return name;
  336. }
  337. static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
  338. {
  339. char buffer[200];
  340. const char *s, *p;
  341. int sym_index = 0, n = 0;
  342. int a, err = 0;
  343. do {
  344. s = pe_export_name(s1, sym);
  345. a = 0;
  346. if (n) {
  347. /* second try: */
  348. if (sym->st_other & ST_PE_STDCALL) {
  349. /* try w/0 stdcall deco (windows API convention) */
  350. p = strrchr(s, '@');
  351. if (!p || s[0] != '_')
  352. break;
  353. strcpy(buffer, s+1)[p-s-1] = 0;
  354. } else if (s[0] != '_') { /* try non-ansi function */
  355. buffer[0] = '_', strcpy(buffer + 1, s);
  356. } else if (0 == memcmp(s, "__imp_", 6)) { /* mingw 2.0 */
  357. strcpy(buffer, s + 6), a = 1;
  358. } else if (0 == memcmp(s, "_imp__", 6)) { /* mingw 3.7 */
  359. strcpy(buffer, s + 6), a = 1;
  360. } else {
  361. continue;
  362. }
  363. s = buffer;
  364. }
  365. sym_index = find_elf_sym(s1->dynsymtab_section, s);
  366. // printf("find (%d) %d %s\n", n, sym_index, s);
  367. if (sym_index
  368. && ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT
  369. && 0 == (sym->st_other & ST_PE_IMPORT)
  370. && 0 == a
  371. ) err = -1, sym_index = 0;
  372. } while (0 == sym_index && ++n < 2);
  373. return n == 2 ? err : sym_index;
  374. }
  375. /*----------------------------------------------------------------------------*/
  376. static int dynarray_assoc(void **pp, int n, int key)
  377. {
  378. int i;
  379. for (i = 0; i < n; ++i, ++pp)
  380. if (key == **(int **) pp)
  381. return i;
  382. return -1;
  383. }
  384. #if 0
  385. ST_FN DWORD umin(DWORD a, DWORD b)
  386. {
  387. return a < b ? a : b;
  388. }
  389. #endif
  390. static DWORD umax(DWORD a, DWORD b)
  391. {
  392. return a < b ? b : a;
  393. }
  394. static DWORD pe_file_align(struct pe_info *pe, DWORD n)
  395. {
  396. return (n + (pe->file_align - 1)) & ~(pe->file_align - 1);
  397. }
  398. static DWORD pe_virtual_align(struct pe_info *pe, DWORD n)
  399. {
  400. return (n + (pe->section_align - 1)) & ~(pe->section_align - 1);
  401. }
  402. static void pe_align_section(Section *s, int a)
  403. {
  404. int i = s->data_offset & (a-1);
  405. if (i)
  406. section_ptr_add(s, a - i);
  407. }
  408. static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size)
  409. {
  410. hdr->opthdr.DataDirectory[dir].VirtualAddress = addr;
  411. hdr->opthdr.DataDirectory[dir].Size = size;
  412. }
  413. static int pe_fwrite(void *data, unsigned len, FILE *fp, DWORD *psum)
  414. {
  415. if (psum) {
  416. DWORD sum = *psum;
  417. WORD *p = data;
  418. int i;
  419. for (i = len; i > 0; i -= 2) {
  420. sum += (i >= 2) ? *p++ : *(BYTE*)p;
  421. sum = (sum + (sum >> 16)) & 0xFFFF;
  422. }
  423. *psum = sum;
  424. }
  425. return len == fwrite(data, 1, len, fp) ? 0 : -1;
  426. }
  427. static void pe_fpad(FILE *fp, DWORD new_pos)
  428. {
  429. DWORD pos = ftell(fp);
  430. while (++pos <= new_pos)
  431. fputc(0, fp);
  432. }
  433. /*----------------------------------------------------------------------------*/
  434. static int pe_write(struct pe_info *pe)
  435. {
  436. static const struct pe_header pe_template = {
  437. {
  438. /* IMAGE_DOS_HEADER doshdr */
  439. 0x5A4D, /*WORD e_magic; Magic number */
  440. 0x0090, /*WORD e_cblp; Bytes on last page of file */
  441. 0x0003, /*WORD e_cp; Pages in file */
  442. 0x0000, /*WORD e_crlc; Relocations */
  443. 0x0004, /*WORD e_cparhdr; Size of header in paragraphs */
  444. 0x0000, /*WORD e_minalloc; Minimum extra paragraphs needed */
  445. 0xFFFF, /*WORD e_maxalloc; Maximum extra paragraphs needed */
  446. 0x0000, /*WORD e_ss; Initial (relative) SS value */
  447. 0x00B8, /*WORD e_sp; Initial SP value */
  448. 0x0000, /*WORD e_csum; Checksum */
  449. 0x0000, /*WORD e_ip; Initial IP value */
  450. 0x0000, /*WORD e_cs; Initial (relative) CS value */
  451. 0x0040, /*WORD e_lfarlc; File address of relocation table */
  452. 0x0000, /*WORD e_ovno; Overlay number */
  453. {0,0,0,0}, /*WORD e_res[4]; Reserved words */
  454. 0x0000, /*WORD e_oemid; OEM identifier (for e_oeminfo) */
  455. 0x0000, /*WORD e_oeminfo; OEM information; e_oemid specific */
  456. {0,0,0,0,0,0,0,0,0,0}, /*WORD e_res2[10]; Reserved words */
  457. 0x00000080 /*DWORD e_lfanew; File address of new exe header */
  458. },{
  459. /* BYTE dosstub[0x40] */
  460. /* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */
  461. 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
  462. 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
  463. 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
  464. 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  465. },
  466. 0x00004550, /* DWORD nt_sig = IMAGE_NT_SIGNATURE */
  467. {
  468. /* IMAGE_FILE_HEADER filehdr */
  469. IMAGE_FILE_MACHINE, /*WORD Machine; */
  470. 0x0003, /*WORD NumberOfSections; */
  471. 0x00000000, /*DWORD TimeDateStamp; */
  472. 0x00000000, /*DWORD PointerToSymbolTable; */
  473. 0x00000000, /*DWORD NumberOfSymbols; */
  474. #if defined(TCC_TARGET_X86_64)
  475. 0x00F0, /*WORD SizeOfOptionalHeader; */
  476. 0x022F /*WORD Characteristics; */
  477. #define CHARACTERISTICS_DLL 0x222E
  478. #elif defined(TCC_TARGET_I386)
  479. 0x00E0, /*WORD SizeOfOptionalHeader; */
  480. 0x030F /*WORD Characteristics; */
  481. #define CHARACTERISTICS_DLL 0x230E
  482. #elif defined(TCC_TARGET_ARM)
  483. 0x00E0, /*WORD SizeOfOptionalHeader; */
  484. 0x010F, /*WORD Characteristics; */
  485. #define CHARACTERISTICS_DLL 0x230F
  486. #endif
  487. },{
  488. /* IMAGE_OPTIONAL_HEADER opthdr */
  489. /* Standard fields. */
  490. #ifdef TCC_TARGET_X86_64
  491. 0x020B, /*WORD Magic; */
  492. #else
  493. 0x010B, /*WORD Magic; */
  494. #endif
  495. 0x06, /*BYTE MajorLinkerVersion; */
  496. 0x00, /*BYTE MinorLinkerVersion; */
  497. 0x00000000, /*DWORD SizeOfCode; */
  498. 0x00000000, /*DWORD SizeOfInitializedData; */
  499. 0x00000000, /*DWORD SizeOfUninitializedData; */
  500. 0x00000000, /*DWORD AddressOfEntryPoint; */
  501. 0x00000000, /*DWORD BaseOfCode; */
  502. #ifndef TCC_TARGET_X86_64
  503. 0x00000000, /*DWORD BaseOfData; */
  504. #endif
  505. /* NT additional fields. */
  506. #if defined(TCC_TARGET_ARM)
  507. 0x00100000, /*DWORD ImageBase; */
  508. #else
  509. 0x00400000, /*DWORD ImageBase; */
  510. #endif
  511. 0x00001000, /*DWORD SectionAlignment; */
  512. 0x00000200, /*DWORD FileAlignment; */
  513. 0x0004, /*WORD MajorOperatingSystemVersion; */
  514. 0x0000, /*WORD MinorOperatingSystemVersion; */
  515. 0x0000, /*WORD MajorImageVersion; */
  516. 0x0000, /*WORD MinorImageVersion; */
  517. 0x0004, /*WORD MajorSubsystemVersion; */
  518. 0x0000, /*WORD MinorSubsystemVersion; */
  519. 0x00000000, /*DWORD Win32VersionValue; */
  520. 0x00000000, /*DWORD SizeOfImage; */
  521. 0x00000200, /*DWORD SizeOfHeaders; */
  522. 0x00000000, /*DWORD CheckSum; */
  523. 0x0002, /*WORD Subsystem; */
  524. 0x0000, /*WORD DllCharacteristics; */
  525. 0x00100000, /*DWORD SizeOfStackReserve; */
  526. 0x00001000, /*DWORD SizeOfStackCommit; */
  527. 0x00100000, /*DWORD SizeOfHeapReserve; */
  528. 0x00001000, /*DWORD SizeOfHeapCommit; */
  529. 0x00000000, /*DWORD LoaderFlags; */
  530. 0x00000010, /*DWORD NumberOfRvaAndSizes; */
  531. /* IMAGE_DATA_DIRECTORY DataDirectory[16]; */
  532. {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
  533. {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}
  534. }};
  535. struct pe_header pe_header = pe_template;
  536. int i;
  537. FILE *op;
  538. DWORD file_offset, sum;
  539. struct section_info *si;
  540. IMAGE_SECTION_HEADER *psh;
  541. op = fopen(pe->filename, "wb");
  542. if (NULL == op) {
  543. tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
  544. return -1;
  545. }
  546. pe->sizeofheaders = pe_file_align(pe,
  547. sizeof (struct pe_header)
  548. + pe->sec_count * sizeof (IMAGE_SECTION_HEADER)
  549. );
  550. file_offset = pe->sizeofheaders;
  551. if (2 == pe->s1->verbose)
  552. printf("-------------------------------"
  553. "\n virt file size section" "\n");
  554. for (i = 0; i < pe->sec_count; ++i) {
  555. DWORD addr, size;
  556. const char *sh_name;
  557. si = pe->sec_info + i;
  558. sh_name = si->name;
  559. addr = si->sh_addr - pe->imagebase;
  560. size = si->sh_size;
  561. psh = &si->ish;
  562. if (2 == pe->s1->verbose)
  563. printf("%6x %6x %6x %s\n",
  564. (unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name);
  565. switch (si->cls) {
  566. case sec_text:
  567. pe_header.opthdr.BaseOfCode = addr;
  568. break;
  569. case sec_data:
  570. #ifndef TCC_TARGET_X86_64
  571. pe_header.opthdr.BaseOfData = addr;
  572. #endif
  573. break;
  574. case sec_bss:
  575. break;
  576. case sec_reloc:
  577. pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
  578. break;
  579. case sec_rsrc:
  580. pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
  581. break;
  582. case sec_pdata:
  583. pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXCEPTION, addr, size);
  584. break;
  585. case sec_stab:
  586. break;
  587. }
  588. if (pe->thunk == pe->s1->sections[si->ord]) {
  589. if (pe->imp_size) {
  590. pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IMPORT,
  591. pe->imp_offs + addr, pe->imp_size);
  592. pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IAT,
  593. pe->iat_offs + addr, pe->iat_size);
  594. }
  595. if (pe->exp_size) {
  596. pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXPORT,
  597. pe->exp_offs + addr, pe->exp_size);
  598. }
  599. }
  600. strncpy((char*)psh->Name, sh_name, sizeof psh->Name);
  601. psh->Characteristics = pe_sec_flags[si->cls];
  602. psh->VirtualAddress = addr;
  603. psh->Misc.VirtualSize = size;
  604. pe_header.opthdr.SizeOfImage =
  605. umax(pe_virtual_align(pe, size + addr), pe_header.opthdr.SizeOfImage);
  606. if (si->data_size) {
  607. psh->PointerToRawData = file_offset;
  608. file_offset = pe_file_align(pe, file_offset + si->data_size);
  609. psh->SizeOfRawData = file_offset - psh->PointerToRawData;
  610. if (si->cls == sec_text)
  611. pe_header.opthdr.SizeOfCode += psh->SizeOfRawData;
  612. else
  613. pe_header.opthdr.SizeOfInitializedData += psh->SizeOfRawData;
  614. }
  615. }
  616. //pe_header.filehdr.TimeDateStamp = time(NULL);
  617. pe_header.filehdr.NumberOfSections = pe->sec_count;
  618. pe_header.opthdr.AddressOfEntryPoint = pe->start_addr;
  619. pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
  620. pe_header.opthdr.ImageBase = pe->imagebase;
  621. pe_header.opthdr.Subsystem = pe->subsystem;
  622. if (pe->s1->pe_stack_size)
  623. pe_header.opthdr.SizeOfStackReserve = pe->s1->pe_stack_size;
  624. if (PE_DLL == pe->type)
  625. pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
  626. pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;
  627. sum = 0;
  628. pe_fwrite(&pe_header, sizeof pe_header, op, &sum);
  629. for (i = 0; i < pe->sec_count; ++i)
  630. pe_fwrite(&pe->sec_info[i].ish, sizeof(IMAGE_SECTION_HEADER), op, &sum);
  631. pe_fpad(op, pe->sizeofheaders);
  632. for (i = 0; i < pe->sec_count; ++i) {
  633. si = pe->sec_info + i;
  634. psh = &si->ish;
  635. if (si->data_size) {
  636. pe_fwrite(si->data, si->data_size, op, &sum);
  637. file_offset = psh->PointerToRawData + psh->SizeOfRawData;
  638. pe_fpad(op, file_offset);
  639. }
  640. }
  641. pe_header.opthdr.CheckSum = sum + file_offset;
  642. fseek(op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);
  643. pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL);
  644. fclose (op);
  645. #ifndef _WIN32
  646. chmod(pe->filename, 0777);
  647. #endif
  648. if (2 == pe->s1->verbose)
  649. printf("-------------------------------\n");
  650. if (pe->s1->verbose)
  651. printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
  652. return 0;
  653. }
  654. /*----------------------------------------------------------------------------*/
  655. static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
  656. {
  657. int i;
  658. int dll_index;
  659. struct pe_import_info *p;
  660. struct import_symbol *s;
  661. ElfW(Sym) *isym;
  662. isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
  663. dll_index = isym->st_size;
  664. i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
  665. if (-1 != i) {
  666. p = pe->imp_info[i];
  667. goto found_dll;
  668. }
  669. p = tcc_mallocz(sizeof *p);
  670. p->dll_index = dll_index;
  671. dynarray_add(&pe->imp_info, &pe->imp_count, p);
  672. found_dll:
  673. i = dynarray_assoc ((void**)p->symbols, p->sym_count, sym_index);
  674. if (-1 != i)
  675. return p->symbols[i];
  676. s = tcc_mallocz(sizeof *s);
  677. dynarray_add(&p->symbols, &p->sym_count, s);
  678. s->sym_index = sym_index;
  679. return s;
  680. }
  681. void pe_free_imports(struct pe_info *pe)
  682. {
  683. int i;
  684. for (i = 0; i < pe->imp_count; ++i) {
  685. struct pe_import_info *p = pe->imp_info[i];
  686. dynarray_reset(&p->symbols, &p->sym_count);
  687. }
  688. dynarray_reset(&pe->imp_info, &pe->imp_count);
  689. }
  690. /*----------------------------------------------------------------------------*/
  691. static void pe_build_imports(struct pe_info *pe)
  692. {
  693. int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
  694. DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
  695. int ndlls = pe->imp_count;
  696. for (sym_cnt = i = 0; i < ndlls; ++i)
  697. sym_cnt += pe->imp_info[i]->sym_count;
  698. if (0 == sym_cnt)
  699. return;
  700. pe_align_section(pe->thunk, 16);
  701. pe->imp_offs = dll_ptr = pe->thunk->data_offset;
  702. pe->imp_size = (ndlls + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
  703. pe->iat_offs = dll_ptr + pe->imp_size;
  704. pe->iat_size = (sym_cnt + ndlls) * sizeof(ADDR3264);
  705. section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size);
  706. thk_ptr = pe->iat_offs;
  707. ent_ptr = pe->iat_offs + pe->iat_size;
  708. for (i = 0; i < pe->imp_count; ++i) {
  709. IMAGE_IMPORT_DESCRIPTOR *hdr;
  710. int k, n, dllindex;
  711. ADDR3264 v;
  712. struct pe_import_info *p = pe->imp_info[i];
  713. const char *name;
  714. DLLReference *dllref;
  715. dllindex = p->dll_index;
  716. if (dllindex)
  717. name = (dllref = pe->s1->loaded_dlls[dllindex-1])->name;
  718. else
  719. name = "", dllref = NULL;
  720. /* put the dll name into the import header */
  721. v = put_elf_str(pe->thunk, name);
  722. hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
  723. hdr->FirstThunk = thk_ptr + rva_base;
  724. hdr->OriginalFirstThunk = ent_ptr + rva_base;
  725. hdr->Name = v + rva_base;
  726. for (k = 0, n = p->sym_count; k <= n; ++k) {
  727. if (k < n) {
  728. int iat_index = p->symbols[k]->iat_index;
  729. int sym_index = p->symbols[k]->sym_index;
  730. ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
  731. ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index;
  732. const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
  733. int ordinal;
  734. org_sym->st_value = thk_ptr;
  735. org_sym->st_shndx = pe->thunk->sh_num;
  736. if (dllref)
  737. v = 0, ordinal = imp_sym->st_value; /* ordinal from pe_load_def */
  738. else
  739. ordinal = 0, v = imp_sym->st_value; /* address from tcc_add_symbol() */
  740. #ifdef TCC_IS_NATIVE
  741. if (pe->type == PE_RUN) {
  742. if (dllref) {
  743. if ( !dllref->handle )
  744. dllref->handle = LoadLibrary(dllref->name);
  745. v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(char*)0+ordinal:name);
  746. }
  747. if (!v)
  748. tcc_error_noabort("can't build symbol '%s'", name);
  749. } else
  750. #endif
  751. if (ordinal) {
  752. v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1);
  753. } else {
  754. v = pe->thunk->data_offset + rva_base;
  755. section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
  756. put_elf_str(pe->thunk, name);
  757. }
  758. } else {
  759. v = 0; /* last entry is zero */
  760. }
  761. *(ADDR3264*)(pe->thunk->data+thk_ptr) =
  762. *(ADDR3264*)(pe->thunk->data+ent_ptr) = v;
  763. thk_ptr += sizeof (ADDR3264);
  764. ent_ptr += sizeof (ADDR3264);
  765. }
  766. dll_ptr += sizeof(IMAGE_IMPORT_DESCRIPTOR);
  767. }
  768. }
  769. /* ------------------------------------------------------------- */
  770. struct pe_sort_sym
  771. {
  772. int index;
  773. const char *name;
  774. };
  775. static int sym_cmp(const void *va, const void *vb)
  776. {
  777. const char *ca = (*(struct pe_sort_sym**)va)->name;
  778. const char *cb = (*(struct pe_sort_sym**)vb)->name;
  779. return strcmp(ca, cb);
  780. }
  781. static void pe_build_exports(struct pe_info *pe)
  782. {
  783. ElfW(Sym) *sym;
  784. int sym_index, sym_end;
  785. DWORD rva_base, func_o, name_o, ord_o, str_o;
  786. IMAGE_EXPORT_DIRECTORY *hdr;
  787. int sym_count, ord;
  788. struct pe_sort_sym **sorted, *p;
  789. FILE *op;
  790. char buf[260];
  791. const char *dllname;
  792. const char *name;
  793. rva_base = pe->thunk->sh_addr - pe->imagebase;
  794. sym_count = 0, sorted = NULL, op = NULL;
  795. sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
  796. for (sym_index = 1; sym_index < sym_end; ++sym_index) {
  797. sym = (ElfW(Sym)*)symtab_section->data + sym_index;
  798. name = pe_export_name(pe->s1, sym);
  799. if ((sym->st_other & ST_PE_EXPORT)
  800. /* export only symbols from actually written sections */
  801. && pe->s1->sections[sym->st_shndx]->sh_addr) {
  802. p = tcc_malloc(sizeof *p);
  803. p->index = sym_index;
  804. p->name = name;
  805. dynarray_add(&sorted, &sym_count, p);
  806. }
  807. #if 0
  808. if (sym->st_other & ST_PE_EXPORT)
  809. printf("export: %s\n", name);
  810. if (sym->st_other & ST_PE_STDCALL)
  811. printf("stdcall: %s\n", name);
  812. #endif
  813. }
  814. if (0 == sym_count)
  815. return;
  816. qsort (sorted, sym_count, sizeof *sorted, sym_cmp);
  817. pe_align_section(pe->thunk, 16);
  818. dllname = tcc_basename(pe->filename);
  819. pe->exp_offs = pe->thunk->data_offset;
  820. func_o = pe->exp_offs + sizeof(IMAGE_EXPORT_DIRECTORY);
  821. name_o = func_o + sym_count * sizeof (DWORD);
  822. ord_o = name_o + sym_count * sizeof (DWORD);
  823. str_o = ord_o + sym_count * sizeof(WORD);
  824. hdr = section_ptr_add(pe->thunk, str_o - pe->exp_offs);
  825. hdr->Characteristics = 0;
  826. hdr->Base = 1;
  827. hdr->NumberOfFunctions = sym_count;
  828. hdr->NumberOfNames = sym_count;
  829. hdr->AddressOfFunctions = func_o + rva_base;
  830. hdr->AddressOfNames = name_o + rva_base;
  831. hdr->AddressOfNameOrdinals = ord_o + rva_base;
  832. hdr->Name = str_o + rva_base;
  833. put_elf_str(pe->thunk, dllname);
  834. #if 1
  835. /* automatically write exports to <output-filename>.def */
  836. pstrcpy(buf, sizeof buf, pe->filename);
  837. strcpy(tcc_fileextension(buf), ".def");
  838. op = fopen(buf, "wb");
  839. if (NULL == op) {
  840. tcc_error_noabort("could not create '%s': %s", buf, strerror(errno));
  841. } else {
  842. fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
  843. if (pe->s1->verbose)
  844. printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]);
  845. }
  846. #endif
  847. for (ord = 0; ord < sym_count; ++ord)
  848. {
  849. p = sorted[ord], sym_index = p->index, name = p->name;
  850. /* insert actual address later in relocate_section() */
  851. put_elf_reloc(symtab_section, pe->thunk,
  852. func_o, R_XXX_RELATIVE, sym_index);
  853. *(DWORD*)(pe->thunk->data + name_o)
  854. = pe->thunk->data_offset + rva_base;
  855. *(WORD*)(pe->thunk->data + ord_o)
  856. = ord;
  857. put_elf_str(pe->thunk, name);
  858. func_o += sizeof (DWORD);
  859. name_o += sizeof (DWORD);
  860. ord_o += sizeof (WORD);
  861. if (op)
  862. fprintf(op, "%s\n", name);
  863. }
  864. pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
  865. dynarray_reset(&sorted, &sym_count);
  866. if (op)
  867. fclose(op);
  868. }
  869. /* ------------------------------------------------------------- */
  870. static void pe_build_reloc (struct pe_info *pe)
  871. {
  872. DWORD offset, block_ptr, addr;
  873. int count, i;
  874. ElfW_Rel *rel, *rel_end;
  875. Section *s = NULL, *sr;
  876. offset = addr = block_ptr = count = i = 0;
  877. rel = rel_end = NULL;
  878. for(;;) {
  879. if (rel < rel_end) {
  880. int type = ELFW(R_TYPE)(rel->r_info);
  881. addr = rel->r_offset + s->sh_addr;
  882. ++ rel;
  883. if (type != REL_TYPE_DIRECT)
  884. continue;
  885. if (count == 0) { /* new block */
  886. block_ptr = pe->reloc->data_offset;
  887. section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
  888. offset = addr & 0xFFFFFFFF<<12;
  889. }
  890. if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */
  891. WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD));
  892. *wp = addr | PE_IMAGE_REL<<12;
  893. ++count;
  894. continue;
  895. }
  896. -- rel;
  897. } else if (i < pe->sec_count) {
  898. sr = (s = pe->s1->sections[pe->sec_info[i++].ord])->reloc;
  899. if (sr) {
  900. rel = (ElfW_Rel *)sr->data;
  901. rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
  902. }
  903. continue;
  904. }
  905. if (count) {
  906. /* store the last block and ready for a new one */
  907. struct pe_reloc_header *hdr;
  908. if (count & 1) /* align for DWORDS */
  909. section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
  910. hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
  911. hdr -> offset = offset - pe->imagebase;
  912. hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
  913. count = 0;
  914. }
  915. if (rel >= rel_end)
  916. break;
  917. }
  918. }
  919. /* ------------------------------------------------------------- */
  920. static int pe_section_class(Section *s)
  921. {
  922. int type, flags;
  923. const char *name;
  924. type = s->sh_type;
  925. flags = s->sh_flags;
  926. name = s->name;
  927. if (flags & SHF_ALLOC) {
  928. if (type == SHT_PROGBITS) {
  929. if (flags & SHF_EXECINSTR)
  930. return sec_text;
  931. if (flags & SHF_WRITE)
  932. return sec_data;
  933. if (0 == strcmp(name, ".rsrc"))
  934. return sec_rsrc;
  935. if (0 == strcmp(name, ".iedat"))
  936. return sec_idata;
  937. if (0 == strcmp(name, ".pdata"))
  938. return sec_pdata;
  939. return sec_other;
  940. } else if (type == SHT_NOBITS) {
  941. if (flags & SHF_WRITE)
  942. return sec_bss;
  943. }
  944. } else {
  945. if (0 == strcmp(name, ".reloc"))
  946. return sec_reloc;
  947. if (0 == strncmp(name, ".stab", 5)) /* .stab and .stabstr */
  948. return sec_stab;
  949. }
  950. return -1;
  951. }
  952. static int pe_assign_addresses (struct pe_info *pe)
  953. {
  954. int i, k, o, c;
  955. DWORD addr;
  956. int *section_order;
  957. struct section_info *si;
  958. Section *s;
  959. if (PE_DLL == pe->type)
  960. pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
  961. // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
  962. section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
  963. for (o = k = 0 ; k < sec_last; ++k) {
  964. for (i = 1; i < pe->s1->nb_sections; ++i) {
  965. s = pe->s1->sections[i];
  966. if (k == pe_section_class(s)) {
  967. // printf("%s %d\n", s->name, k);
  968. s->sh_addr = pe->imagebase;
  969. section_order[o++] = i;
  970. }
  971. }
  972. }
  973. pe->sec_info = tcc_mallocz(o * sizeof (struct section_info));
  974. addr = pe->imagebase + 1;
  975. for (i = 0; i < o; ++i)
  976. {
  977. k = section_order[i];
  978. s = pe->s1->sections[k];
  979. c = pe_section_class(s);
  980. si = &pe->sec_info[pe->sec_count];
  981. #ifdef PE_MERGE_DATA
  982. if (c == sec_bss && pe->sec_count && si[-1].cls == sec_data) {
  983. /* append .bss to .data */
  984. s->sh_addr = addr = ((addr-1) | (s->sh_addralign-1)) + 1;
  985. addr += s->data_offset;
  986. si[-1].sh_size = addr - si[-1].sh_addr;
  987. continue;
  988. }
  989. #endif
  990. if (c == sec_stab && 0 == pe->s1->do_debug)
  991. continue;
  992. strcpy(si->name, s->name);
  993. si->cls = c;
  994. si->ord = k;
  995. si->sh_addr = s->sh_addr = addr = pe_virtual_align(pe, addr);
  996. si->sh_flags = s->sh_flags;
  997. if (c == sec_data && NULL == pe->thunk)
  998. pe->thunk = s;
  999. if (s == pe->thunk) {
  1000. pe_build_imports(pe);
  1001. pe_build_exports(pe);
  1002. }
  1003. if (c == sec_reloc)
  1004. pe_build_reloc (pe);
  1005. if (s->data_offset)
  1006. {
  1007. if (s->sh_type != SHT_NOBITS) {
  1008. si->data = s->data;
  1009. si->data_size = s->data_offset;
  1010. }
  1011. addr += s->data_offset;
  1012. si->sh_size = s->data_offset;
  1013. ++pe->sec_count;
  1014. }
  1015. // printf("%08x %05x %s\n", si->sh_addr, si->sh_size, si->name);
  1016. }
  1017. #if 0
  1018. for (i = 1; i < pe->s1->nb_sections; ++i) {
  1019. Section *s = pe->s1->sections[i];
  1020. int type = s->sh_type;
  1021. int flags = s->sh_flags;
  1022. printf("section %-16s %-10s %5x %s,%s,%s\n",
  1023. s->name,
  1024. type == SHT_PROGBITS ? "progbits" :
  1025. type == SHT_NOBITS ? "nobits" :
  1026. type == SHT_SYMTAB ? "symtab" :
  1027. type == SHT_STRTAB ? "strtab" :
  1028. type == SHT_RELX ? "rel" : "???",
  1029. s->data_offset,
  1030. flags & SHF_ALLOC ? "alloc" : "",
  1031. flags & SHF_WRITE ? "write" : "",
  1032. flags & SHF_EXECINSTR ? "exec" : ""
  1033. );
  1034. }
  1035. pe->s1->verbose = 2;
  1036. #endif
  1037. tcc_free(section_order);
  1038. return 0;
  1039. }
  1040. /*----------------------------------------------------------------------------*/
  1041. static int pe_isafunc(int sym_index)
  1042. {
  1043. Section *sr = text_section->reloc;
  1044. ElfW_Rel *rel, *rel_end;
  1045. Elf32_Word info = ELF32_R_INFO(sym_index, R_386_PC32);
  1046. if (!sr)
  1047. return 0;
  1048. rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
  1049. for (rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++)
  1050. if (rel->r_info == info)
  1051. return 1;
  1052. return 0;
  1053. }
  1054. /*----------------------------------------------------------------------------*/
  1055. static int pe_check_symbols(struct pe_info *pe)
  1056. {
  1057. ElfW(Sym) *sym;
  1058. int sym_index, sym_end;
  1059. int ret = 0;
  1060. pe_align_section(text_section, 8);
  1061. sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
  1062. for (sym_index = 1; sym_index < sym_end; ++sym_index) {
  1063. sym = (ElfW(Sym) *)symtab_section->data + sym_index;
  1064. if (sym->st_shndx == SHN_UNDEF) {
  1065. const char *name = (char*)symtab_section->link->data + sym->st_name;
  1066. unsigned type = ELFW(ST_TYPE)(sym->st_info);
  1067. int imp_sym = pe_find_import(pe->s1, sym);
  1068. struct import_symbol *is;
  1069. if (imp_sym <= 0)
  1070. goto not_found;
  1071. if (type == STT_NOTYPE) {
  1072. /* symbols from assembler have no type, find out which */
  1073. if (pe_isafunc(sym_index))
  1074. type = STT_FUNC;
  1075. else
  1076. type = STT_OBJECT;
  1077. }
  1078. is = pe_add_import(pe, imp_sym);
  1079. if (type == STT_FUNC) {
  1080. unsigned long offset = is->thk_offset;
  1081. if (offset) {
  1082. /* got aliased symbol, like stricmp and _stricmp */
  1083. } else {
  1084. char buffer[100];
  1085. WORD *p;
  1086. offset = text_section->data_offset;
  1087. /* add the 'jmp IAT[x]' instruction */
  1088. #ifdef TCC_TARGET_ARM
  1089. p = section_ptr_add(text_section, 8+4); // room for code and address
  1090. (*(DWORD*)(p)) = 0xE59FC000; // arm code ldr ip, [pc] ; PC+8+0 = 0001xxxx
  1091. (*(DWORD*)(p+2)) = 0xE59CF000; // arm code ldr pc, [ip]
  1092. #else
  1093. p = section_ptr_add(text_section, 8);
  1094. *p = 0x25FF;
  1095. #ifdef TCC_TARGET_X86_64
  1096. *(DWORD*)(p+1) = (DWORD)-4;
  1097. #endif
  1098. #endif
  1099. /* add a helper symbol, will be patched later in
  1100. pe_build_imports */
  1101. sprintf(buffer, "IAT.%s", name);
  1102. is->iat_index = put_elf_sym(
  1103. symtab_section, 0, sizeof(DWORD),
  1104. ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
  1105. 0, SHN_UNDEF, buffer);
  1106. #ifdef TCC_TARGET_ARM
  1107. put_elf_reloc(symtab_section, text_section,
  1108. offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position
  1109. #else
  1110. put_elf_reloc(symtab_section, text_section,
  1111. offset + 2, R_XXX_THUNKFIX, is->iat_index);
  1112. #endif
  1113. is->thk_offset = offset;
  1114. }
  1115. /* tcc_realloc might have altered sym's address */
  1116. sym = (ElfW(Sym) *)symtab_section->data + sym_index;
  1117. /* patch the original symbol */
  1118. sym->st_value = offset;
  1119. sym->st_shndx = text_section->sh_num;
  1120. sym->st_other &= ~ST_PE_EXPORT; /* do not export */
  1121. continue;
  1122. }
  1123. if (type == STT_OBJECT) { /* data, ptr to that should be */
  1124. if (0 == is->iat_index) {
  1125. /* original symbol will be patched later in pe_build_imports */
  1126. is->iat_index = sym_index;
  1127. continue;
  1128. }
  1129. }
  1130. not_found:
  1131. if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
  1132. /* STB_WEAK undefined symbols are accepted */
  1133. continue;
  1134. tcc_error_noabort("undefined symbol '%s'%s", name,
  1135. imp_sym < 0 ? ", missing __declspec(dllimport)?":"");
  1136. ret = -1;
  1137. } else if (pe->s1->rdynamic
  1138. && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
  1139. /* if -rdynamic option, then export all non local symbols */
  1140. sym->st_other |= ST_PE_EXPORT;
  1141. }
  1142. }
  1143. return ret;
  1144. }
  1145. /*----------------------------------------------------------------------------*/
  1146. #ifdef PE_PRINT_SECTIONS
  1147. static void pe_print_section(FILE * f, Section * s)
  1148. {
  1149. /* just if you're curious */
  1150. BYTE *p, *e, b;
  1151. int i, n, l, m;
  1152. p = s->data;
  1153. e = s->data + s->data_offset;
  1154. l = e - p;
  1155. fprintf(f, "section \"%s\"", s->name);
  1156. if (s->link)
  1157. fprintf(f, "\nlink \"%s\"", s->link->name);
  1158. if (s->reloc)
  1159. fprintf(f, "\nreloc \"%s\"", s->reloc->name);
  1160. fprintf(f, "\nv_addr %08X", (unsigned)s->sh_addr);
  1161. fprintf(f, "\ncontents %08X", (unsigned)l);
  1162. fprintf(f, "\n\n");
  1163. if (s->sh_type == SHT_NOBITS)
  1164. return;
  1165. if (0 == l)
  1166. return;
  1167. if (s->sh_type == SHT_SYMTAB)
  1168. m = sizeof(ElfW(Sym));
  1169. else if (s->sh_type == SHT_RELX)
  1170. m = sizeof(ElfW_Rel);
  1171. else
  1172. m = 16;
  1173. fprintf(f, "%-8s", "offset");
  1174. for (i = 0; i < m; ++i)
  1175. fprintf(f, " %02x", i);
  1176. n = 56;
  1177. if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_RELX) {
  1178. const char *fields1[] = {
  1179. "name",
  1180. "value",
  1181. "size",
  1182. "bind",
  1183. "type",
  1184. "other",
  1185. "shndx",
  1186. NULL
  1187. };
  1188. const char *fields2[] = {
  1189. "offs",
  1190. "type",
  1191. "symb",
  1192. NULL
  1193. };
  1194. const char **p;
  1195. if (s->sh_type == SHT_SYMTAB)
  1196. p = fields1, n = 106;
  1197. else
  1198. p = fields2, n = 58;
  1199. for (i = 0; p[i]; ++i)
  1200. fprintf(f, "%6s", p[i]);
  1201. fprintf(f, " symbol");
  1202. }
  1203. fprintf(f, "\n");
  1204. for (i = 0; i < n; ++i)
  1205. fprintf(f, "-");
  1206. fprintf(f, "\n");
  1207. for (i = 0; i < l;)
  1208. {
  1209. fprintf(f, "%08X", i);
  1210. for (n = 0; n < m; ++n) {
  1211. if (n + i < l)
  1212. fprintf(f, " %02X", p[i + n]);
  1213. else
  1214. fprintf(f, " ");
  1215. }
  1216. if (s->sh_type == SHT_SYMTAB) {
  1217. ElfW(Sym) *sym = (ElfW(Sym) *) (p + i);
  1218. const char *name = s->link->data + sym->st_name;
  1219. fprintf(f, " %04X %04X %04X %02X %02X %02X %04X \"%s\"",
  1220. (unsigned)sym->st_name,
  1221. (unsigned)sym->st_value,
  1222. (unsigned)sym->st_size,
  1223. (unsigned)ELFW(ST_BIND)(sym->st_info),
  1224. (unsigned)ELFW(ST_TYPE)(sym->st_info),
  1225. (unsigned)sym->st_other,
  1226. (unsigned)sym->st_shndx,
  1227. name);
  1228. } else if (s->sh_type == SHT_RELX) {
  1229. ElfW_Rel *rel = (ElfW_Rel *) (p + i);
  1230. ElfW(Sym) *sym =
  1231. (ElfW(Sym) *) s->link->data + ELFW(R_SYM)(rel->r_info);
  1232. const char *name = s->link->link->data + sym->st_name;
  1233. fprintf(f, " %04X %02X %04X \"%s\"",
  1234. (unsigned)rel->r_offset,
  1235. (unsigned)ELFW(R_TYPE)(rel->r_info),
  1236. (unsigned)ELFW(R_SYM)(rel->r_info),
  1237. name);
  1238. } else {
  1239. fprintf(f, " ");
  1240. for (n = 0; n < m; ++n) {
  1241. if (n + i < l) {
  1242. b = p[i + n];
  1243. if (b < 32 || b >= 127)
  1244. b = '.';
  1245. fprintf(f, "%c", b);
  1246. }
  1247. }
  1248. }
  1249. i += m;
  1250. fprintf(f, "\n");
  1251. }
  1252. fprintf(f, "\n\n");
  1253. }
  1254. static void pe_print_sections(TCCState *s1, const char *fname)
  1255. {
  1256. Section *s;
  1257. FILE *f;
  1258. int i;
  1259. f = fopen(fname, "w");
  1260. for (i = 1; i < s1->nb_sections; ++i) {
  1261. s = s1->sections[i];
  1262. pe_print_section(f, s);
  1263. }
  1264. pe_print_section(f, s1->dynsymtab_section);
  1265. fclose(f);
  1266. }
  1267. #endif
  1268. /* ------------------------------------------------------------- */
  1269. /* helper function for load/store to insert one more indirection */
  1270. #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
  1271. ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
  1272. {
  1273. int r2;
  1274. if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
  1275. return sv;
  1276. if (!sv->sym->a.dllimport)
  1277. return sv;
  1278. // printf("import %04x %04x %04x %s\n", sv->type.t, sv->sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL));
  1279. memset(v2, 0, sizeof *v2);
  1280. v2->type.t = VT_PTR;
  1281. v2->r = VT_CONST | VT_SYM | VT_LVAL;
  1282. v2->sym = sv->sym;
  1283. r2 = get_reg(RC_INT);
  1284. load(r2, v2);
  1285. v2->r = r2;
  1286. if ((uint32_t)sv->c.i) {
  1287. vpushv(v2);
  1288. vpushi(sv->c.i);
  1289. gen_opi('+');
  1290. *v2 = *vtop--;
  1291. }
  1292. v2->type.t = sv->type.t;
  1293. v2->r |= sv->r & VT_LVAL;
  1294. return v2;
  1295. }
  1296. #endif
  1297. ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value)
  1298. {
  1299. return set_elf_sym(
  1300. s1->dynsymtab_section,
  1301. value,
  1302. dllindex, /* st_size */
  1303. ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
  1304. 0,
  1305. value ? SHN_ABS : SHN_UNDEF,
  1306. name
  1307. );
  1308. }
  1309. static int add_dllref(TCCState *s1, const char *dllname)
  1310. {
  1311. DLLReference *dllref;
  1312. int i;
  1313. for (i = 0; i < s1->nb_loaded_dlls; ++i)
  1314. if (0 == strcmp(s1->loaded_dlls[i]->name, dllname))
  1315. return i + 1;
  1316. dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
  1317. strcpy(dllref->name, dllname);
  1318. dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
  1319. return s1->nb_loaded_dlls;
  1320. }
  1321. /* ------------------------------------------------------------- */
  1322. static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
  1323. {
  1324. lseek(fd, offset, SEEK_SET);
  1325. return len == read(fd, buffer, len);
  1326. }
  1327. /* ------------------------------------------------------------- */
  1328. PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
  1329. {
  1330. int l, i, n, n0, ret;
  1331. char *p;
  1332. int fd;
  1333. IMAGE_SECTION_HEADER ish;
  1334. IMAGE_EXPORT_DIRECTORY ied;
  1335. IMAGE_DOS_HEADER dh;
  1336. IMAGE_FILE_HEADER ih;
  1337. DWORD sig, ref, addr, ptr, namep;
  1338. int pef_hdroffset, opt_hdroffset, sec_hdroffset;
  1339. n = n0 = 0;
  1340. p = NULL;
  1341. ret = -1;
  1342. fd = open(filename, O_RDONLY | O_BINARY);
  1343. if (fd < 0)
  1344. goto the_end_1;
  1345. ret = 1;
  1346. if (!read_mem(fd, 0, &dh, sizeof dh))
  1347. goto the_end;
  1348. if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
  1349. goto the_end;
  1350. if (sig != 0x00004550)
  1351. goto the_end;
  1352. pef_hdroffset = dh.e_lfanew + sizeof sig;
  1353. if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
  1354. goto the_end;
  1355. opt_hdroffset = pef_hdroffset + sizeof ih;
  1356. if (ih.Machine == 0x014C) {
  1357. IMAGE_OPTIONAL_HEADER32 oh;
  1358. sec_hdroffset = opt_hdroffset + sizeof oh;
  1359. if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
  1360. goto the_end;
  1361. if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
  1362. goto the_end_0;
  1363. addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  1364. } else if (ih.Machine == 0x8664) {
  1365. IMAGE_OPTIONAL_HEADER64 oh;
  1366. sec_hdroffset = opt_hdroffset + sizeof oh;
  1367. if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
  1368. goto the_end;
  1369. if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
  1370. goto the_end_0;
  1371. addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  1372. } else
  1373. goto the_end;
  1374. //printf("addr: %08x\n", addr);
  1375. for (i = 0; i < ih.NumberOfSections; ++i) {
  1376. if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
  1377. goto the_end;
  1378. //printf("vaddr: %08x\n", ish.VirtualAddress);
  1379. if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
  1380. goto found;
  1381. }
  1382. goto the_end_0;
  1383. found:
  1384. ref = ish.VirtualAddress - ish.PointerToRawData;
  1385. if (!read_mem(fd, addr - ref, &ied, sizeof ied))
  1386. goto the_end;
  1387. namep = ied.AddressOfNames - ref;
  1388. for (i = 0; i < ied.NumberOfNames; ++i) {
  1389. if (!read_mem(fd, namep, &ptr, sizeof ptr))
  1390. goto the_end;
  1391. namep += sizeof ptr;
  1392. for (l = 0;;) {
  1393. if (n+1 >= n0)
  1394. p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
  1395. if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
  1396. tcc_free(p), p = NULL;
  1397. goto the_end;
  1398. }
  1399. if (p[n++] == 0)
  1400. break;
  1401. }
  1402. }
  1403. if (p)
  1404. p[n] = 0;
  1405. the_end_0:
  1406. ret = 0;
  1407. the_end:
  1408. close(fd);
  1409. the_end_1:
  1410. *pp = p;
  1411. return ret;
  1412. }
  1413. /* -------------------------------------------------------------
  1414. * This is for compiled windows resources in 'coff' format
  1415. * as generated by 'windres.exe -O coff ...'.
  1416. */
  1417. static int pe_load_res(TCCState *s1, int fd)
  1418. {
  1419. struct pe_rsrc_header hdr;
  1420. Section *rsrc_section;
  1421. int i, ret = -1, sym_index;
  1422. BYTE *ptr;
  1423. unsigned offs;
  1424. if (!read_mem(fd, 0, &hdr, sizeof hdr))
  1425. goto quit;
  1426. if (hdr.filehdr.Machine != IMAGE_FILE_MACHINE
  1427. || hdr.filehdr.NumberOfSections != 1
  1428. || strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0)
  1429. goto quit;
  1430. rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
  1431. ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
  1432. offs = hdr.sectionhdr.PointerToRawData;
  1433. if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
  1434. goto quit;
  1435. offs = hdr.sectionhdr.PointerToRelocations;
  1436. sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc");
  1437. for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) {
  1438. struct pe_rsrc_reloc rel;
  1439. if (!read_mem(fd, offs, &rel, sizeof rel))
  1440. goto quit;
  1441. // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
  1442. if (rel.type != RSRC_RELTYPE)
  1443. goto quit;
  1444. put_elf_reloc(symtab_section, rsrc_section,
  1445. rel.offset, R_XXX_RELATIVE, sym_index);
  1446. offs += sizeof rel;
  1447. }
  1448. ret = 0;
  1449. quit:
  1450. return ret;
  1451. }
  1452. /* ------------------------------------------------------------- */
  1453. static char *trimfront(char *p)
  1454. {
  1455. while (*p && (unsigned char)*p <= ' ')
  1456. ++p;
  1457. return p;
  1458. }
  1459. static char *trimback(char *a, char *e)
  1460. {
  1461. while (e > a && (unsigned char)e[-1] <= ' ')
  1462. --e;
  1463. *e = 0;;
  1464. return a;
  1465. }
  1466. /* ------------------------------------------------------------- */
  1467. static int pe_load_def(TCCState *s1, int fd)
  1468. {
  1469. int state = 0, ret = -1, dllindex = 0, ord;
  1470. char line[400], dllname[80], *p, *x;
  1471. FILE *fp;
  1472. fp = fdopen(dup(fd), "rb");
  1473. while (fgets(line, sizeof line, fp))
  1474. {
  1475. p = trimfront(trimback(line, strchr(line, 0)));
  1476. if (0 == *p || ';' == *p)
  1477. continue;
  1478. switch (state) {
  1479. case 0:
  1480. if (0 != strnicmp(p, "LIBRARY", 7))
  1481. goto quit;
  1482. pstrcpy(dllname, sizeof dllname, trimfront(p+7));
  1483. ++state;
  1484. continue;
  1485. case 1:
  1486. if (0 != stricmp(p, "EXPORTS"))
  1487. goto quit;
  1488. ++state;
  1489. continue;
  1490. case 2:
  1491. dllindex = add_dllref(s1, dllname);
  1492. ++state;
  1493. /* fall through */
  1494. default:
  1495. /* get ordinal and will store in sym->st_value */
  1496. ord = 0;
  1497. x = strchr(p, ' ');
  1498. if (x) {
  1499. *x = 0, x = strrchr(x + 1, '@');
  1500. if (x) {
  1501. char *d;
  1502. ord = (int)strtol(x + 1, &d, 10);
  1503. if (*d)
  1504. ord = 0;
  1505. }
  1506. }
  1507. pe_putimport(s1, dllindex, p, ord);
  1508. continue;
  1509. }
  1510. }
  1511. ret = 0;
  1512. quit:
  1513. fclose(fp);
  1514. return ret;
  1515. }
  1516. /* ------------------------------------------------------------- */
  1517. static int pe_load_dll(TCCState *s1, const char *filename)
  1518. {
  1519. char *p, *q;
  1520. int index, ret;
  1521. ret = tcc_get_dllexports(filename, &p);
  1522. if (ret) {
  1523. return -1;
  1524. } else if (p) {
  1525. index = add_dllref(s1, tcc_basename(filename));
  1526. for (q = p; *q; q += 1 + strlen(q))
  1527. pe_putimport(s1, index, q, 0);
  1528. tcc_free(p);
  1529. }
  1530. return 0;
  1531. }
  1532. /* ------------------------------------------------------------- */
  1533. ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd)
  1534. {
  1535. int ret = -1;
  1536. char buf[10];
  1537. if (0 == strcmp(tcc_fileextension(filename), ".def"))
  1538. ret = pe_load_def(s1, fd);
  1539. else if (pe_load_res(s1, fd) == 0)
  1540. ret = 0;
  1541. else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4))
  1542. ret = pe_load_dll(s1, filename);
  1543. return ret;
  1544. }
  1545. /* ------------------------------------------------------------- */
  1546. #ifdef TCC_TARGET_X86_64
  1547. static unsigned pe_add_uwwind_info(TCCState *s1)
  1548. {
  1549. if (NULL == s1->uw_pdata) {
  1550. s1->uw_pdata = find_section(tcc_state, ".pdata");
  1551. s1->uw_pdata->sh_addralign = 4;
  1552. }
  1553. if (0 == s1->uw_sym)
  1554. s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
  1555. if (0 == s1->uw_offs) {
  1556. /* As our functions all have the same stackframe, we use one entry for all */
  1557. static const unsigned char uw_info[] = {
  1558. 0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
  1559. 0x04, // UBYTE Size of prolog
  1560. 0x02, // UBYTE Count of unwind codes
  1561. 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
  1562. // USHORT * n Unwind codes array
  1563. // 0x0b, 0x01, 0xff, 0xff, // stack size
  1564. 0x04, 0x03, // set frame ptr (mov rsp -> rbp)
  1565. 0x01, 0x50 // push reg (rbp)
  1566. };
  1567. Section *s = text_section;
  1568. unsigned char *p;
  1569. section_ptr_add(s, -s->data_offset & 3); /* align */
  1570. s1->uw_offs = s->data_offset;
  1571. p = section_ptr_add(s, sizeof uw_info);
  1572. memcpy(p, uw_info, sizeof uw_info);
  1573. }
  1574. return s1->uw_offs;
  1575. }
  1576. ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
  1577. {
  1578. TCCState *s1 = tcc_state;
  1579. Section *pd;
  1580. unsigned o, n, d;
  1581. struct /* _RUNTIME_FUNCTION */ {
  1582. DWORD BeginAddress;
  1583. DWORD EndAddress;
  1584. DWORD UnwindData;
  1585. } *p;
  1586. d = pe_add_uwwind_info(s1);
  1587. pd = s1->uw_pdata;
  1588. o = pd->data_offset;
  1589. p = section_ptr_add(pd, sizeof *p);
  1590. /* record this function */
  1591. p->BeginAddress = start;
  1592. p->EndAddress = end;
  1593. p->UnwindData = d;
  1594. /* put relocations on it */
  1595. for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
  1596. put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
  1597. }
  1598. #endif
  1599. /* ------------------------------------------------------------- */
  1600. #ifdef TCC_TARGET_X86_64
  1601. #define PE_STDSYM(n,s) n
  1602. #else
  1603. #define PE_STDSYM(n,s) "_" n s
  1604. #endif
  1605. static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
  1606. {
  1607. const char *start_symbol;
  1608. int pe_type = 0;
  1609. int unicode_entry = 0;
  1610. if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
  1611. pe_type = PE_GUI;
  1612. else
  1613. if (find_elf_sym(symtab_section, PE_STDSYM("wWinMain","@16"))) {
  1614. pe_type = PE_GUI;
  1615. unicode_entry = PE_GUI;
  1616. }
  1617. else
  1618. if (TCC_OUTPUT_DLL == s1->output_type) {
  1619. pe_type = PE_DLL;
  1620. /* need this for 'tccelf.c:relocate_section()' */
  1621. s1->output_type = TCC_OUTPUT_EXE;
  1622. }
  1623. else {
  1624. pe_type = PE_EXE;
  1625. if (find_elf_sym(symtab_section, "wmain"))
  1626. unicode_entry = PE_EXE;
  1627. }
  1628. start_symbol =
  1629. TCC_OUTPUT_MEMORY == s1->output_type
  1630. ? PE_GUI == pe_type ? (unicode_entry ? "__runwwinmain" : "__runwinmain")
  1631. : (unicode_entry ? "__runwmain" : "__runmain")
  1632. : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12")
  1633. : PE_GUI == pe_type ? (unicode_entry ? "__wwinstart": "__winstart")
  1634. : (unicode_entry ? "__wstart" : "__start")
  1635. ;
  1636. if (!s1->leading_underscore || strchr(start_symbol, '@'))
  1637. ++start_symbol;
  1638. /* grab the startup code from libtcc1 */
  1639. #ifdef TCC_IS_NATIVE
  1640. if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
  1641. #endif
  1642. set_elf_sym(symtab_section,
  1643. 0, 0,
  1644. ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
  1645. SHN_UNDEF, start_symbol);
  1646. if (0 == s1->nostdlib) {
  1647. static const char *libs[] = {
  1648. TCC_LIBTCC1, "msvcrt", "kernel32", "", "user32", "gdi32", NULL
  1649. };
  1650. const char **pp, *p;
  1651. for (pp = libs; 0 != (p = *pp); ++pp) {
  1652. if (0 == *p) {
  1653. if (PE_DLL != pe_type && PE_GUI != pe_type)
  1654. break;
  1655. } else if (pp == libs && tcc_add_dll(s1, p, 0) >= 0) {
  1656. continue;
  1657. } else {
  1658. tcc_add_library_err(s1, p);
  1659. }
  1660. }
  1661. }
  1662. if (TCC_OUTPUT_MEMORY == s1->output_type)
  1663. pe_type = PE_RUN;
  1664. pe->type = pe_type;
  1665. pe->start_symbol = start_symbol;
  1666. }
  1667. static void pe_set_options(TCCState * s1, struct pe_info *pe)
  1668. {
  1669. if (PE_DLL == pe->type) {
  1670. /* XXX: check if is correct for arm-pe target */
  1671. pe->imagebase = 0x10000000;
  1672. } else {
  1673. #if defined(TCC_TARGET_ARM)
  1674. pe->imagebase = 0x00010000;
  1675. #else
  1676. pe->imagebase = 0x00400000;
  1677. #endif
  1678. }
  1679. #if defined(TCC_TARGET_ARM)
  1680. /* we use "console" subsystem by default */
  1681. pe->subsystem = 9;
  1682. #else
  1683. if (PE_DLL == pe->type || PE_GUI == pe->type)
  1684. pe->subsystem = 2;
  1685. else
  1686. pe->subsystem = 3;
  1687. #endif
  1688. /* Allow override via -Wl,-subsystem=... option */
  1689. if (s1->pe_subsystem != 0)
  1690. pe->subsystem = s1->pe_subsystem;
  1691. /* set default file/section alignment */
  1692. if (pe->subsystem == 1) {
  1693. pe->section_align = 0x20;
  1694. pe->file_align = 0x20;
  1695. } else {
  1696. pe->section_align = 0x1000;
  1697. pe->file_align = 0x200;
  1698. }
  1699. if (s1->section_align != 0)
  1700. pe->section_align = s1->section_align;
  1701. if (s1->pe_file_align != 0)
  1702. pe->file_align = s1->pe_file_align;
  1703. if ((pe->subsystem >= 10) && (pe->subsystem <= 12))
  1704. pe->imagebase = 0;
  1705. if (s1->has_text_addr)
  1706. pe->imagebase = s1->text_addr;
  1707. }
  1708. ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
  1709. {
  1710. int ret;
  1711. struct pe_info pe;
  1712. int i;
  1713. memset(&pe, 0, sizeof pe);
  1714. pe.filename = filename;
  1715. pe.s1 = s1;
  1716. tcc_add_runtime(s1);
  1717. pe_add_runtime(s1, &pe);
  1718. resolve_common_syms(s1);
  1719. pe_set_options(s1, &pe);
  1720. ret = pe_check_symbols(&pe);
  1721. if (ret)
  1722. ;
  1723. else if (filename) {
  1724. pe_assign_addresses(&pe);
  1725. relocate_syms(s1, s1->symtab, 0);
  1726. s1->pe_imagebase = pe.imagebase;
  1727. for (i = 1; i < s1->nb_sections; ++i) {
  1728. Section *s = s1->sections[i];
  1729. if (s->reloc) {
  1730. relocate_section(s1, s);
  1731. }
  1732. }
  1733. pe.start_addr = (DWORD)
  1734. ((uintptr_t)tcc_get_symbol_err(s1, pe.start_symbol)
  1735. - pe.imagebase);
  1736. if (s1->nb_errors)
  1737. ret = -1;
  1738. else
  1739. ret = pe_write(&pe);
  1740. tcc_free(pe.sec_info);
  1741. } else {
  1742. #ifdef TCC_IS_NATIVE
  1743. pe.thunk = data_section;
  1744. pe_build_imports(&pe);
  1745. s1->runtime_main = pe.start_symbol;
  1746. #ifdef TCC_TARGET_X86_64
  1747. s1->uw_pdata = find_section(s1, ".pdata");
  1748. #endif
  1749. #endif
  1750. }
  1751. pe_free_imports(&pe);
  1752. #ifdef PE_PRINT_SECTIONS
  1753. pe_print_sections(s1, "tcc.log");
  1754. #endif
  1755. return ret;
  1756. }
  1757. /* ------------------------------------------------------------- */