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