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