Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5199 | serge | 1 | /* Routines to help build PEI-format DLLs (Win32 etc) |
2 | Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, |
||
3 | 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. |
||
4 | Written by DJ Delorie |
||
5 | |||
6 | This file is part of the GNU Binutils. |
||
7 | |||
8 | This program is free software; you can redistribute it and/or modify |
||
9 | it under the terms of the GNU General Public License as published by |
||
10 | the Free Software Foundation; either version 3 of the License, or |
||
11 | (at your option) any later version. |
||
12 | |||
13 | This program is distributed in the hope that it will be useful, |
||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | GNU General Public License for more details. |
||
17 | |||
18 | You should have received a copy of the GNU General Public License |
||
19 | along with this program; if not, write to the Free Software |
||
20 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
||
21 | MA 02110-1301, USA. */ |
||
22 | |||
23 | #include "sysdep.h" |
||
24 | #include "bfd.h" |
||
25 | #include "bfdlink.h" |
||
26 | #include "libiberty.h" |
||
27 | #include "filenames.h" |
||
28 | #include "safe-ctype.h" |
||
29 | |||
30 | #include |
||
31 | |||
32 | #include "ld.h" |
||
33 | #include "ldexp.h" |
||
34 | #include "ldlang.h" |
||
35 | #include "ldwrite.h" |
||
36 | #include "ldmisc.h" |
||
37 | #include |
||
38 | #include "ldmain.h" |
||
39 | #include "ldfile.h" |
||
40 | #include "ldemul.h" |
||
41 | #include "coff/internal.h" |
||
42 | #include "../bfd/libcoff.h" |
||
43 | #include "deffile.h" |
||
44 | |||
45 | #ifdef pe_use_x86_64 |
||
46 | |||
47 | #define PE_IDATA4_SIZE 8 |
||
48 | #define PE_IDATA5_SIZE 8 |
||
49 | #include "pep-dll.h" |
||
50 | #undef AOUTSZ |
||
51 | #define AOUTSZ PEPAOUTSZ |
||
52 | #define PEAOUTHDR PEPAOUTHDR |
||
53 | |||
54 | #else |
||
55 | |||
56 | #include "pe-dll.h" |
||
57 | |||
58 | #endif |
||
59 | |||
60 | #ifndef PE_IDATA4_SIZE |
||
61 | #define PE_IDATA4_SIZE 4 |
||
62 | #endif |
||
63 | |||
64 | #ifndef PE_IDATA5_SIZE |
||
65 | #define PE_IDATA5_SIZE 4 |
||
66 | #endif |
||
67 | |||
68 | /* This file turns a regular Windows PE image into a DLL. Because of |
||
69 | the complexity of this operation, it has been broken down into a |
||
70 | number of separate modules which are all called by the main function |
||
71 | at the end of this file. This function is not re-entrant and is |
||
72 | normally only called once, so static variables are used to reduce |
||
73 | the number of parameters and return values required. |
||
74 | |||
75 | See also: ld/emultempl/pe.em and ld/emultempl/pep.em. */ |
||
76 | |||
77 | /* Auto-import feature by Paul Sokolovsky |
||
78 | |||
79 | Quick facts: |
||
80 | |||
81 | 1. With this feature on, DLL clients can import variables from DLL |
||
82 | without any concern from their side (for example, without any source |
||
83 | code modifications). |
||
84 | |||
85 | 2. This is done completely in bounds of the PE specification (to be fair, |
||
86 | there's a place where it pokes nose out of, but in practice it works). |
||
87 | So, resulting module can be used with any other PE compiler/linker. |
||
88 | |||
89 | 3. Auto-import is fully compatible with standard import method and they |
||
90 | can be mixed together. |
||
91 | |||
92 | 4. Overheads: space: 8 bytes per imported symbol, plus 20 for each |
||
93 | reference to it; load time: negligible; virtual/physical memory: should be |
||
94 | less than effect of DLL relocation, and I sincerely hope it doesn't affect |
||
95 | DLL sharability (too much). |
||
96 | |||
97 | Idea |
||
98 | |||
99 | The obvious and only way to get rid of dllimport insanity is to make client |
||
100 | access variable directly in the DLL, bypassing extra dereference. I.e., |
||
101 | whenever client contains something like |
||
102 | |||
103 | mov dll_var,%eax, |
||
104 | |||
105 | address of dll_var in the command should be relocated to point into loaded |
||
106 | DLL. The aim is to make OS loader do so, and than make ld help with that. |
||
107 | Import section of PE made following way: there's a vector of structures |
||
108 | each describing imports from particular DLL. Each such structure points |
||
109 | to two other parallel vectors: one holding imported names, and one which |
||
110 | will hold address of corresponding imported name. So, the solution is |
||
111 | de-vectorize these structures, making import locations be sparse and |
||
112 | pointing directly into code. Before continuing, it is worth a note that, |
||
113 | while authors strives to make PE act ELF-like, there're some other people |
||
114 | make ELF act PE-like: elfvector, ;-) . |
||
115 | |||
116 | Implementation |
||
117 | |||
118 | For each reference of data symbol to be imported from DLL (to set of which |
||
119 | belong symbols with name |
||
120 | import fixup entry is generated. That entry is of type |
||
121 | IMAGE_IMPORT_DESCRIPTOR and stored in .idata$2 subsection. Each |
||
122 | fixup entry contains pointer to symbol's address within .text section |
||
123 | (marked with __fuN_ |
||
124 | (so, DLL name is referenced by multiple entries), and pointer to symbol |
||
125 | name thunk. Symbol name thunk is singleton vector (__nm_th_ |
||
126 | pointing to IMAGE_IMPORT_BY_NAME structure (__nm_ |
||
127 | containing imported name. Here comes that "on the edge" problem mentioned |
||
128 | above: PE specification rambles that name vector (OriginalFirstThunk) |
||
129 | should run in parallel with addresses vector (FirstThunk), i.e. that they |
||
130 | should have same number of elements and terminated with zero. We violate |
||
131 | this, since FirstThunk points directly into machine code. But in practice, |
||
132 | OS loader implemented the sane way: it goes thru OriginalFirstThunk and |
||
133 | puts addresses to FirstThunk, not something else. It once again should be |
||
134 | noted that dll and symbol name structures are reused across fixup entries |
||
135 | and should be there anyway to support standard import stuff, so sustained |
||
136 | overhead is 20 bytes per reference. Other question is whether having several |
||
137 | IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, it is |
||
138 | done even by native compiler/linker (libth32's functions are in fact reside |
||
139 | in windows9x kernel32.dll, so if you use it, you have two |
||
140 | IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is whether |
||
141 | referencing the same PE structures several times is valid. The answer is why |
||
142 | not, prohibiting that (detecting violation) would require more work on |
||
143 | behalf of loader than not doing it. |
||
144 | |||
145 | See also: ld/emultempl/pe.em and ld/emultempl/pep.em. */ |
||
146 | |||
147 | static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *); |
||
148 | |||
149 | /* For emultempl/pe.em. */ |
||
150 | |||
151 | def_file * pe_def_file = 0; |
||
152 | int pe_dll_export_everything = 0; |
||
153 | int pe_dll_exclude_all_symbols = 0; |
||
154 | int pe_dll_do_default_excludes = 1; |
||
155 | int pe_dll_kill_ats = 0; |
||
156 | int pe_dll_stdcall_aliases = 0; |
||
157 | int pe_dll_warn_dup_exports = 0; |
||
158 | int pe_dll_compat_implib = 0; |
||
159 | int pe_dll_extra_pe_debug = 0; |
||
160 | int pe_use_nul_prefixed_import_tables = 0; |
||
161 | int pe_use_coff_long_section_names = -1; |
||
162 | int pe_leading_underscore = -1; |
||
163 | |||
164 | /* Static variables and types. */ |
||
165 | |||
166 | static bfd_vma image_base; |
||
167 | static bfd *filler_bfd; |
||
168 | static struct bfd_section *edata_s, *reloc_s; |
||
169 | static unsigned char *edata_d, *reloc_d; |
||
170 | static size_t edata_sz, reloc_sz; |
||
171 | static int runtime_pseudo_relocs_created = 0; |
||
172 | static int runtime_pseudp_reloc_v2_init = 0; |
||
173 | |||
174 | typedef struct |
||
175 | { |
||
176 | const char *name; |
||
177 | int len; |
||
178 | } |
||
179 | autofilter_entry_type; |
||
180 | |||
181 | typedef struct |
||
182 | { |
||
183 | const char *target_name; |
||
184 | const char *object_target; |
||
185 | unsigned int imagebase_reloc; |
||
186 | int pe_arch; |
||
187 | int bfd_arch; |
||
188 | bfd_boolean underscored; |
||
189 | const autofilter_entry_type* autofilter_symbollist; |
||
190 | } |
||
191 | pe_details_type; |
||
192 | |||
193 | static const autofilter_entry_type autofilter_symbollist_generic[] = |
||
194 | { |
||
195 | { STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") }, |
||
196 | /* Entry point symbols. */ |
||
197 | { STRING_COMMA_LEN ("DllMain") }, |
||
198 | { STRING_COMMA_LEN ("DllMainCRTStartup") }, |
||
199 | { STRING_COMMA_LEN ("_DllMainCRTStartup") }, |
||
200 | /* Runtime pseudo-reloc. */ |
||
201 | { STRING_COMMA_LEN ("_pei386_runtime_relocator") }, |
||
202 | { STRING_COMMA_LEN ("do_pseudo_reloc") }, |
||
203 | { NULL, 0 } |
||
204 | }; |
||
205 | |||
206 | static const autofilter_entry_type autofilter_symbollist_i386[] = |
||
207 | { |
||
208 | { STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") }, |
||
209 | /* Entry point symbols, and entry hooks. */ |
||
210 | { STRING_COMMA_LEN ("cygwin_crt0") }, |
||
211 | #ifdef pe_use_x86_64 |
||
212 | { STRING_COMMA_LEN ("DllMain") }, |
||
213 | { STRING_COMMA_LEN ("DllEntryPoint") }, |
||
214 | { STRING_COMMA_LEN ("DllMainCRTStartup") }, |
||
215 | { STRING_COMMA_LEN ("_cygwin_dll_entry") }, |
||
216 | { STRING_COMMA_LEN ("_cygwin_crt0_common") }, |
||
217 | { STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry") }, |
||
218 | #else |
||
219 | { STRING_COMMA_LEN ("DllMain@12") }, |
||
220 | { STRING_COMMA_LEN ("DllEntryPoint@0") }, |
||
221 | { STRING_COMMA_LEN ("DllMainCRTStartup@12") }, |
||
222 | { STRING_COMMA_LEN ("_cygwin_dll_entry@12") }, |
||
223 | { STRING_COMMA_LEN ("_cygwin_crt0_common@8") }, |
||
224 | { STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry@12") }, |
||
225 | { STRING_COMMA_LEN ("cygwin_attach_dll") }, |
||
226 | #endif |
||
227 | { STRING_COMMA_LEN ("cygwin_premain0") }, |
||
228 | { STRING_COMMA_LEN ("cygwin_premain1") }, |
||
229 | { STRING_COMMA_LEN ("cygwin_premain2") }, |
||
230 | { STRING_COMMA_LEN ("cygwin_premain3") }, |
||
231 | /* Runtime pseudo-reloc. */ |
||
232 | { STRING_COMMA_LEN ("_pei386_runtime_relocator") }, |
||
233 | { STRING_COMMA_LEN ("do_pseudo_reloc") }, |
||
234 | /* Global vars that should not be exported. */ |
||
235 | { STRING_COMMA_LEN ("impure_ptr") }, |
||
236 | { STRING_COMMA_LEN ("_impure_ptr") }, |
||
237 | { STRING_COMMA_LEN ("_fmode") }, |
||
238 | { STRING_COMMA_LEN ("environ") }, |
||
239 | { NULL, 0 } |
||
240 | }; |
||
241 | |||
242 | #define PE_ARCH_i386 1 |
||
243 | #define PE_ARCH_sh 2 |
||
244 | #define PE_ARCH_mips 3 |
||
245 | #define PE_ARCH_arm 4 |
||
246 | #define PE_ARCH_arm_epoc 5 |
||
247 | #define PE_ARCH_arm_wince 6 |
||
248 | |||
249 | /* Don't make it constant as underscore mode gets possibly overriden |
||
250 | by target or -(no-)leading-underscore option. */ |
||
251 | static pe_details_type pe_detail_list[] = |
||
252 | { |
||
253 | { |
||
254 | #ifdef pe_use_x86_64 |
||
255 | "pei-x86-64", |
||
256 | "pe-x86-64", |
||
257 | 3 /* R_IMAGEBASE */, |
||
258 | #else |
||
259 | "pei-i386", |
||
260 | "pe-i386", |
||
261 | 7 /* R_IMAGEBASE */, |
||
262 | #endif |
||
263 | PE_ARCH_i386, |
||
264 | bfd_arch_i386, |
||
265 | #ifdef pe_use_x86_64 |
||
266 | FALSE, |
||
267 | #else |
||
268 | TRUE, |
||
269 | #endif |
||
270 | autofilter_symbollist_i386 |
||
271 | }, |
||
272 | { |
||
273 | "pei-shl", |
||
274 | "pe-shl", |
||
275 | 16 /* R_SH_IMAGEBASE */, |
||
276 | PE_ARCH_sh, |
||
277 | bfd_arch_sh, |
||
278 | TRUE, |
||
279 | autofilter_symbollist_generic |
||
280 | }, |
||
281 | { |
||
282 | "pei-mips", |
||
283 | "pe-mips", |
||
284 | 34 /* MIPS_R_RVA */, |
||
285 | PE_ARCH_mips, |
||
286 | bfd_arch_mips, |
||
287 | FALSE, |
||
288 | autofilter_symbollist_generic |
||
289 | }, |
||
290 | { |
||
291 | "pei-arm-little", |
||
292 | "pe-arm-little", |
||
293 | 11 /* ARM_RVA32 */, |
||
294 | PE_ARCH_arm, |
||
295 | bfd_arch_arm, |
||
296 | TRUE, |
||
297 | autofilter_symbollist_generic |
||
298 | }, |
||
299 | { |
||
300 | "epoc-pei-arm-little", |
||
301 | "epoc-pe-arm-little", |
||
302 | 11 /* ARM_RVA32 */, |
||
303 | PE_ARCH_arm_epoc, |
||
304 | bfd_arch_arm, |
||
305 | FALSE, |
||
306 | autofilter_symbollist_generic |
||
307 | }, |
||
308 | { |
||
309 | "pei-arm-wince-little", |
||
310 | "pe-arm-wince-little", |
||
311 | 2, /* ARM_RVA32 on Windows CE, see bfd/coff-arm.c. */ |
||
312 | PE_ARCH_arm_wince, |
||
313 | bfd_arch_arm, |
||
314 | FALSE, |
||
315 | autofilter_symbollist_generic |
||
316 | }, |
||
317 | { NULL, NULL, 0, 0, 0, FALSE, NULL } |
||
318 | }; |
||
319 | |||
320 | static const pe_details_type *pe_details; |
||
321 | |||
322 | /* Do not specify library suffix explicitly, to allow for dllized versions. */ |
||
323 | static const autofilter_entry_type autofilter_liblist[] = |
||
324 | { |
||
325 | { STRING_COMMA_LEN ("libcegcc") }, |
||
326 | { STRING_COMMA_LEN ("libcygwin") }, |
||
327 | { STRING_COMMA_LEN ("libgcc") }, |
||
328 | { STRING_COMMA_LEN ("libgcc_s") }, |
||
329 | { STRING_COMMA_LEN ("libstdc++") }, |
||
330 | { STRING_COMMA_LEN ("libmingw32") }, |
||
331 | { STRING_COMMA_LEN ("libmingwex") }, |
||
332 | { STRING_COMMA_LEN ("libg2c") }, |
||
333 | { STRING_COMMA_LEN ("libsupc++") }, |
||
334 | { STRING_COMMA_LEN ("libobjc") }, |
||
335 | { STRING_COMMA_LEN ("libgcj") }, |
||
336 | { NULL, 0 } |
||
337 | }; |
||
338 | |||
339 | /* Regardless of the suffix issue mentioned above, we must ensure that |
||
340 | we do not falsely match on a leading substring, such as when libtool |
||
341 | builds libstdc++ as a DLL using libsupc++convenience.a as an intermediate. |
||
342 | This routine ensures that the leading part of the name matches and that |
||
343 | it is followed by only an optional version suffix and a file extension, |
||
344 | returning zero if so or -1 if not. */ |
||
345 | static int libnamencmp (const char *libname, const autofilter_entry_type *afptr) |
||
346 | { |
||
347 | if (filename_ncmp (libname, afptr->name, afptr->len)) |
||
348 | return -1; |
||
349 | |||
350 | libname += afptr->len; |
||
351 | |||
352 | /* Be liberal in interpreting what counts as a version suffix; we |
||
353 | accept anything that has a dash to separate it from the name and |
||
354 | begins with a digit. */ |
||
355 | if (libname[0] == '-') |
||
356 | { |
||
357 | if (!ISDIGIT (*++libname)) |
||
358 | return -1; |
||
359 | /* Ensure the filename has an extension. */ |
||
360 | while (*++libname != '.') |
||
361 | if (!*libname) |
||
362 | return -1; |
||
363 | } |
||
364 | else if (libname[0] != '.') |
||
365 | return -1; |
||
366 | |||
367 | return 0; |
||
368 | } |
||
369 | |||
370 | static const autofilter_entry_type autofilter_objlist[] = |
||
371 | { |
||
372 | { STRING_COMMA_LEN ("crt0.o") }, |
||
373 | { STRING_COMMA_LEN ("crt1.o") }, |
||
374 | { STRING_COMMA_LEN ("crt2.o") }, |
||
375 | { STRING_COMMA_LEN ("dllcrt1.o") }, |
||
376 | { STRING_COMMA_LEN ("dllcrt2.o") }, |
||
377 | { STRING_COMMA_LEN ("gcrt0.o") }, |
||
378 | { STRING_COMMA_LEN ("gcrt1.o") }, |
||
379 | { STRING_COMMA_LEN ("gcrt2.o") }, |
||
380 | { STRING_COMMA_LEN ("crtbegin.o") }, |
||
381 | { STRING_COMMA_LEN ("crtend.o") }, |
||
382 | { NULL, 0 } |
||
383 | }; |
||
384 | |||
385 | static const autofilter_entry_type autofilter_symbolprefixlist[] = |
||
386 | { |
||
387 | /* _imp_ is treated specially, as it is always underscored. */ |
||
388 | /* { STRING_COMMA_LEN ("_imp_") }, */ |
||
389 | /* Don't export some c++ symbols. */ |
||
390 | { STRING_COMMA_LEN ("__rtti_") }, |
||
391 | { STRING_COMMA_LEN ("__builtin_") }, |
||
392 | /* Don't re-export auto-imported symbols. */ |
||
393 | { STRING_COMMA_LEN ("__nm_") }, |
||
394 | /* Don't export symbols specifying internal DLL layout. */ |
||
395 | { STRING_COMMA_LEN ("_head_") }, |
||
396 | { STRING_COMMA_LEN ("_IMPORT_DESCRIPTOR_") }, |
||
397 | /* Don't export section labels or artificial symbols |
||
398 | (eg ".weak.foo". */ |
||
399 | { STRING_COMMA_LEN (".") }, |
||
400 | { NULL, 0 } |
||
401 | }; |
||
402 | |||
403 | static const autofilter_entry_type autofilter_symbolsuffixlist[] = |
||
404 | { |
||
405 | { STRING_COMMA_LEN ("_iname") }, |
||
406 | { STRING_COMMA_LEN ("_NULL_THUNK_DATA") }, |
||
407 | { NULL, 0 } |
||
408 | }; |
||
409 | |||
410 | #define U(str) (pe_details->underscored ? "_" str : str) |
||
411 | |||
412 | void |
||
413 | pe_dll_id_target (const char *target) |
||
414 | { |
||
415 | int i; |
||
416 | |||
417 | for (i = 0; pe_detail_list[i].target_name; i++) |
||
418 | if (strcmp (pe_detail_list[i].target_name, target) == 0 |
||
419 | || strcmp (pe_detail_list[i].object_target, target) == 0) |
||
420 | { |
||
421 | int u = pe_leading_underscore; /* Underscoring mode. -1 for use default. */ |
||
422 | if (u == -1) |
||
423 | bfd_get_target_info (target, NULL, NULL, &u, NULL); |
||
424 | if (u == -1) |
||
425 | abort (); |
||
426 | pe_detail_list[i].underscored = (u != 0 ? TRUE : FALSE); |
||
427 | pe_details = pe_detail_list + i; |
||
428 | pe_leading_underscore = (u != 0 ? 1 : 0); |
||
429 | return; |
||
430 | } |
||
431 | einfo (_("%XUnsupported PEI architecture: %s\n"), target); |
||
432 | exit (1); |
||
433 | } |
||
434 | |||
435 | /* Helper functions for qsort. Relocs must be sorted so that we can write |
||
436 | them out by pages. */ |
||
437 | |||
438 | typedef struct |
||
439 | { |
||
440 | bfd_vma vma; |
||
441 | char type; |
||
442 | short extra; |
||
443 | } |
||
444 | reloc_data_type; |
||
445 | |||
446 | static int |
||
447 | reloc_sort (const void *va, const void *vb) |
||
448 | { |
||
449 | bfd_vma a = ((const reloc_data_type *) va)->vma; |
||
450 | bfd_vma b = ((const reloc_data_type *) vb)->vma; |
||
451 | |||
452 | return (a > b) ? 1 : ((a < b) ? -1 : 0); |
||
453 | } |
||
454 | |||
455 | static int |
||
456 | pe_export_sort (const void *va, const void *vb) |
||
457 | { |
||
458 | const def_file_export *a = va; |
||
459 | const def_file_export *b = vb; |
||
460 | char *an = a->name; |
||
461 | char *bn = b->name; |
||
462 | if (a->its_name) |
||
463 | an = a->its_name; |
||
464 | if (b->its_name) |
||
465 | bn = b->its_name; |
||
466 | |||
467 | return strcmp (an, bn); |
||
468 | } |
||
469 | |||
470 | /* Read and process the .DEF file. */ |
||
471 | |||
472 | /* These correspond to the entries in pe_def_file->exports[]. I use |
||
473 | exported_symbol_sections[i] to tag whether or not the symbol was |
||
474 | defined, since we can't export symbols we don't have. */ |
||
475 | |||
476 | static bfd_vma *exported_symbol_offsets; |
||
477 | static struct bfd_section **exported_symbol_sections; |
||
478 | static int export_table_size; |
||
479 | static int count_exported; |
||
480 | static int count_exported_byname; |
||
481 | static int count_with_ordinals; |
||
482 | static const char *dll_name; |
||
483 | static int min_ordinal, max_ordinal; |
||
484 | static int *exported_symbols; |
||
485 | |||
486 | typedef struct exclude_list_struct |
||
487 | { |
||
488 | char *string; |
||
489 | struct exclude_list_struct *next; |
||
490 | exclude_type type; |
||
491 | } |
||
492 | exclude_list_struct; |
||
493 | |||
494 | static struct exclude_list_struct *excludes = 0; |
||
495 | |||
496 | void |
||
497 | pe_dll_add_excludes (const char *new_excludes, const exclude_type type) |
||
498 | { |
||
499 | char *local_copy; |
||
500 | char *exclude_string; |
||
501 | |||
502 | local_copy = xstrdup (new_excludes); |
||
503 | |||
504 | exclude_string = strtok (local_copy, ",:"); |
||
505 | for (; exclude_string; exclude_string = strtok (NULL, ",:")) |
||
506 | { |
||
507 | struct exclude_list_struct *new_exclude; |
||
508 | |||
509 | new_exclude = xmalloc (sizeof (struct exclude_list_struct)); |
||
510 | new_exclude->string = xmalloc (strlen (exclude_string) + 1); |
||
511 | strcpy (new_exclude->string, exclude_string); |
||
512 | new_exclude->type = type; |
||
513 | new_exclude->next = excludes; |
||
514 | excludes = new_exclude; |
||
515 | } |
||
516 | |||
517 | free (local_copy); |
||
518 | } |
||
519 | |||
520 | static bfd_boolean |
||
521 | is_import (const char* n) |
||
522 | { |
||
523 | return (CONST_STRNEQ (n, "__imp_")); |
||
524 | } |
||
525 | |||
526 | /* abfd is a bfd containing n (or NULL) |
||
527 | It can be used for contextual checks. */ |
||
528 | |||
529 | static int |
||
530 | auto_export (bfd *abfd, def_file *d, const char *n) |
||
531 | { |
||
532 | def_file_export key; |
||
533 | struct exclude_list_struct *ex; |
||
534 | const autofilter_entry_type *afptr; |
||
535 | const char * libname = NULL; |
||
536 | |||
537 | if (abfd && abfd->my_archive) |
||
538 | libname = lbasename (abfd->my_archive->filename); |
||
539 | |||
540 | key.name = key.its_name = (char *) n; |
||
541 | |||
542 | /* Return false if n is in the d->exports table. */ |
||
543 | if (bsearch (&key, d->exports, d->num_exports, |
||
544 | sizeof (pe_def_file->exports[0]), pe_export_sort)) |
||
545 | return 0; |
||
546 | |||
547 | if (pe_dll_do_default_excludes) |
||
548 | { |
||
549 | const char * p; |
||
550 | int len; |
||
551 | |||
552 | if (pe_dll_extra_pe_debug) |
||
553 | printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n", |
||
554 | n, abfd, abfd->my_archive); |
||
555 | |||
556 | /* First of all, make context checks: |
||
557 | Don't export anything from standard libs. */ |
||
558 | if (libname) |
||
559 | { |
||
560 | afptr = autofilter_liblist; |
||
561 | |||
562 | while (afptr->name) |
||
563 | { |
||
564 | if (libnamencmp (libname, afptr) == 0 ) |
||
565 | return 0; |
||
566 | afptr++; |
||
567 | } |
||
568 | } |
||
569 | |||
570 | /* Next, exclude symbols from certain startup objects. */ |
||
571 | |||
572 | if (abfd && (p = lbasename (abfd->filename))) |
||
573 | { |
||
574 | afptr = autofilter_objlist; |
||
575 | while (afptr->name) |
||
576 | { |
||
577 | if (strcmp (p, afptr->name) == 0) |
||
578 | return 0; |
||
579 | afptr++; |
||
580 | } |
||
581 | } |
||
582 | |||
583 | /* Don't try to blindly exclude all symbols |
||
584 | that begin with '__'; this was tried and |
||
585 | it is too restrictive. Instead we have |
||
586 | a target specific list to use: */ |
||
587 | afptr = pe_details->autofilter_symbollist; |
||
588 | |||
589 | while (afptr->name) |
||
590 | { |
||
591 | if (strcmp (n, afptr->name) == 0) |
||
592 | return 0; |
||
593 | |||
594 | afptr++; |
||
595 | } |
||
596 | |||
597 | /* Next, exclude symbols starting with ... */ |
||
598 | afptr = autofilter_symbolprefixlist; |
||
599 | while (afptr->name) |
||
600 | { |
||
601 | if (strncmp (n, afptr->name, afptr->len) == 0) |
||
602 | return 0; |
||
603 | |||
604 | afptr++; |
||
605 | } |
||
606 | |||
607 | /* Finally, exclude symbols ending with ... */ |
||
608 | len = strlen (n); |
||
609 | afptr = autofilter_symbolsuffixlist; |
||
610 | while (afptr->name) |
||
611 | { |
||
612 | if ((len >= afptr->len) |
||
613 | /* Add 1 to insure match with trailing '\0'. */ |
||
614 | && strncmp (n + len - afptr->len, afptr->name, |
||
615 | afptr->len + 1) == 0) |
||
616 | return 0; |
||
617 | |||
618 | afptr++; |
||
619 | } |
||
620 | } |
||
621 | |||
622 | for (ex = excludes; ex; ex = ex->next) |
||
623 | { |
||
624 | if (ex->type == EXCLUDELIBS) |
||
625 | { |
||
626 | if (libname |
||
627 | && ((filename_cmp (libname, ex->string) == 0) |
||
628 | || (strcasecmp ("ALL", ex->string) == 0))) |
||
629 | return 0; |
||
630 | } |
||
631 | else if (ex->type == EXCLUDEFORIMPLIB) |
||
632 | { |
||
633 | if (filename_cmp (abfd->filename, ex->string) == 0) |
||
634 | return 0; |
||
635 | } |
||
636 | else if (strcmp (n, ex->string) == 0) |
||
637 | return 0; |
||
638 | } |
||
639 | |||
640 | return 1; |
||
641 | } |
||
642 | |||
643 | static void |
||
644 | process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) |
||
645 | { |
||
646 | int i, j; |
||
647 | struct bfd_link_hash_entry *blhe; |
||
648 | bfd *b; |
||
649 | struct bfd_section *s; |
||
650 | def_file_export *e = 0; |
||
651 | bfd_boolean resort_needed; |
||
652 | |||
653 | if (!pe_def_file) |
||
654 | pe_def_file = def_file_empty (); |
||
655 | |||
656 | /* First, run around to all the objects looking for the .drectve |
||
657 | sections, and push those into the def file too. */ |
||
658 | for (b = info->input_bfds; b; b = b->link_next) |
||
659 | { |
||
660 | s = bfd_get_section_by_name (b, ".drectve"); |
||
661 | if (s) |
||
662 | { |
||
663 | long size = s->size; |
||
664 | char *buf = xmalloc (size); |
||
665 | |||
666 | bfd_get_section_contents (b, s, buf, 0, size); |
||
667 | def_file_add_directive (pe_def_file, buf, size); |
||
668 | free (buf); |
||
669 | } |
||
670 | } |
||
671 | |||
672 | /* Process aligned common symbol information from the |
||
673 | .drectve sections now; common symbol allocation is |
||
674 | done before final link, so it will be too late to |
||
675 | process them in process_embedded_commands() called |
||
676 | from _bfd_coff_link_input_bfd(). */ |
||
677 | if (pe_def_file->aligncomms) |
||
678 | { |
||
679 | def_file_aligncomm *ac = pe_def_file->aligncomms; |
||
680 | while (ac) |
||
681 | { |
||
682 | struct coff_link_hash_entry *sym_hash; |
||
683 | sym_hash = coff_link_hash_lookup (coff_hash_table (info), |
||
684 | ac->symbol_name, FALSE, FALSE, FALSE); |
||
685 | if (sym_hash && sym_hash->root.type == bfd_link_hash_common |
||
686 | && sym_hash->root.u.c.p->alignment_power < (unsigned) ac->alignment) |
||
687 | { |
||
688 | sym_hash->root.u.c.p->alignment_power = (unsigned) ac->alignment; |
||
689 | } |
||
690 | ac = ac->next; |
||
691 | } |
||
692 | } |
||
693 | |||
694 | /* If we are building an executable and there is nothing |
||
695 | to export, we do not build an export table at all. */ |
||
696 | if (info->executable && pe_def_file->num_exports == 0 |
||
697 | && (!pe_dll_export_everything || pe_dll_exclude_all_symbols)) |
||
698 | return; |
||
699 | |||
700 | /* Now, maybe export everything else the default way. */ |
||
701 | if ((pe_dll_export_everything || pe_def_file->num_exports == 0) |
||
702 | && !pe_dll_exclude_all_symbols) |
||
703 | { |
||
704 | for (b = info->input_bfds; b; b = b->link_next) |
||
705 | { |
||
706 | asymbol **symbols; |
||
707 | int nsyms; |
||
708 | |||
709 | if (!bfd_generic_link_read_symbols (b)) |
||
710 | { |
||
711 | einfo (_("%B%F: could not read symbols: %E\n"), b); |
||
712 | return; |
||
713 | } |
||
714 | |||
715 | symbols = bfd_get_outsymbols (b); |
||
716 | nsyms = bfd_get_symcount (b); |
||
717 | |||
718 | for (j = 0; j < nsyms; j++) |
||
719 | { |
||
720 | /* We should export symbols which are either global or not |
||
721 | anything at all. (.bss data is the latter) |
||
722 | We should not export undefined symbols. */ |
||
723 | bfd_boolean would_export |
||
724 | = (symbols[j]->section != bfd_und_section_ptr |
||
725 | && ((symbols[j]->flags & BSF_GLOBAL) |
||
726 | || (symbols[j]->flags == 0))); |
||
727 | if (link_info.version_info && would_export) |
||
728 | would_export |
||
729 | = !bfd_hide_sym_by_version (link_info.version_info, |
||
730 | symbols[j]->name); |
||
731 | if (would_export) |
||
732 | { |
||
733 | const char *sn = symbols[j]->name; |
||
734 | |||
735 | /* We should not re-export imported stuff. */ |
||
736 | { |
||
737 | char *name; |
||
738 | if (is_import (sn)) |
||
739 | continue; |
||
740 | |||
741 | name = xmalloc (strlen ("__imp_") + strlen (sn) + 1); |
||
742 | sprintf (name, "%s%s", "__imp_", sn); |
||
743 | |||
744 | blhe = bfd_link_hash_lookup (info->hash, name, |
||
745 | FALSE, FALSE, FALSE); |
||
746 | free (name); |
||
747 | |||
748 | if (blhe && blhe->type == bfd_link_hash_defined) |
||
749 | continue; |
||
750 | } |
||
751 | |||
752 | if (pe_details->underscored && *sn == '_') |
||
753 | sn++; |
||
754 | |||
755 | if (auto_export (b, pe_def_file, sn)) |
||
756 | { |
||
757 | int is_dup = 0; |
||
758 | def_file_export *p; |
||
759 | |||
760 | p = def_file_add_export (pe_def_file, sn, 0, -1, |
||
761 | NULL, &is_dup); |
||
762 | /* Fill data flag properly, from dlltool.c. */ |
||
763 | if (!is_dup) |
||
764 | p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); |
||
765 | } |
||
766 | } |
||
767 | } |
||
768 | } |
||
769 | } |
||
770 | |||
771 | #undef NE |
||
772 | #define NE pe_def_file->num_exports |
||
773 | |||
774 | /* Don't create an empty export table. */ |
||
775 | if (NE == 0) |
||
776 | return; |
||
777 | |||
778 | resort_needed = FALSE; |
||
779 | |||
780 | /* Canonicalize the export list. */ |
||
781 | if (pe_dll_kill_ats) |
||
782 | { |
||
783 | for (i = 0; i < NE; i++) |
||
784 | { |
||
785 | /* Check for fastcall/stdcall-decoration, but ignore |
||
786 | C++ mangled names. */ |
||
787 | if (pe_def_file->exports[i].name[0] != '?' |
||
788 | && strchr (pe_def_file->exports[i].name, '@')) |
||
789 | { |
||
790 | /* This will preserve internal_name, which may have been |
||
791 | pointing to the same memory as name, or might not |
||
792 | have. */ |
||
793 | int lead_at = (*pe_def_file->exports[i].name == '@'); |
||
794 | char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at); |
||
795 | char *tmp_at = strrchr (tmp, '@'); |
||
796 | |||
797 | if (tmp_at) |
||
798 | *tmp_at = 0; |
||
799 | else |
||
800 | einfo (_("%XCannot export %s: invalid export name\n"), |
||
801 | pe_def_file->exports[i].name); |
||
802 | pe_def_file->exports[i].name = tmp; |
||
803 | resort_needed = TRUE; |
||
804 | } |
||
805 | } |
||
806 | } |
||
807 | |||
808 | /* Re-sort the exports table as we have possibly changed the order |
||
809 | by removing leading @. */ |
||
810 | if (resort_needed) |
||
811 | qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]), |
||
812 | pe_export_sort); |
||
813 | |||
814 | if (pe_dll_stdcall_aliases) |
||
815 | { |
||
816 | for (i = 0; i < NE; i++) |
||
817 | { |
||
818 | if (is_import (pe_def_file->exports[i].name)) |
||
819 | continue; |
||
820 | |||
821 | if (strchr (pe_def_file->exports[i].name, '@')) |
||
822 | { |
||
823 | int is_dup = 1; |
||
824 | int lead_at = (*pe_def_file->exports[i].name == '@'); |
||
825 | char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at); |
||
826 | |||
827 | *(strchr (tmp, '@')) = 0; |
||
828 | if (auto_export (NULL, pe_def_file, tmp)) |
||
829 | def_file_add_export (pe_def_file, tmp, |
||
830 | pe_def_file->exports[i].internal_name, |
||
831 | -1, NULL, &is_dup); |
||
832 | if (is_dup) |
||
833 | free (tmp); |
||
834 | } |
||
835 | } |
||
836 | } |
||
837 | |||
838 | /* Convenience, but watch out for it changing. */ |
||
839 | e = pe_def_file->exports; |
||
840 | |||
841 | for (i = 0, j = 0; i < NE; i++) |
||
842 | { |
||
843 | if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0) |
||
844 | { |
||
845 | /* This is a duplicate. */ |
||
846 | if (e[j - 1].ordinal != -1 |
||
847 | && e[i].ordinal != -1 |
||
848 | && e[j - 1].ordinal != e[i].ordinal) |
||
849 | { |
||
850 | if (pe_dll_warn_dup_exports) |
||
851 | /* xgettext:c-format */ |
||
852 | einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"), |
||
853 | e[j - 1].name, e[j - 1].ordinal, e[i].ordinal); |
||
854 | } |
||
855 | else |
||
856 | { |
||
857 | if (pe_dll_warn_dup_exports) |
||
858 | /* xgettext:c-format */ |
||
859 | einfo (_("Warning, duplicate EXPORT: %s\n"), |
||
860 | e[j - 1].name); |
||
861 | } |
||
862 | |||
863 | if (e[i].ordinal != -1) |
||
864 | e[j - 1].ordinal = e[i].ordinal; |
||
865 | e[j - 1].flag_private |= e[i].flag_private; |
||
866 | e[j - 1].flag_constant |= e[i].flag_constant; |
||
867 | e[j - 1].flag_noname |= e[i].flag_noname; |
||
868 | e[j - 1].flag_data |= e[i].flag_data; |
||
869 | if (e[i].name) |
||
870 | free (e[i].name); |
||
871 | if (e[i].internal_name) |
||
872 | free (e[i].internal_name); |
||
873 | if (e[i].its_name) |
||
874 | free (e[i].its_name); |
||
875 | } |
||
876 | else |
||
877 | { |
||
878 | if (i != j) |
||
879 | e[j] = e[i]; |
||
880 | j++; |
||
881 | } |
||
882 | } |
||
883 | pe_def_file->num_exports = j; /* == NE */ |
||
884 | |||
885 | exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma)); |
||
886 | exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *)); |
||
887 | |||
888 | memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *)); |
||
889 | max_ordinal = 0; |
||
890 | min_ordinal = 65536; |
||
891 | count_exported = 0; |
||
892 | count_exported_byname = 0; |
||
893 | count_with_ordinals = 0; |
||
894 | |||
895 | for (i = 0; i < NE; i++) |
||
896 | { |
||
897 | char *name; |
||
898 | name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); |
||
899 | if (pe_details->underscored |
||
900 | && (*pe_def_file->exports[i].internal_name != '@')) |
||
901 | { |
||
902 | *name = '_'; |
||
903 | strcpy (name + 1, pe_def_file->exports[i].internal_name); |
||
904 | } |
||
905 | else |
||
906 | strcpy (name, pe_def_file->exports[i].internal_name); |
||
907 | |||
908 | blhe = bfd_link_hash_lookup (info->hash, |
||
909 | name, |
||
910 | FALSE, FALSE, TRUE); |
||
911 | |||
912 | if (blhe |
||
913 | && (blhe->type == bfd_link_hash_defined |
||
914 | || (blhe->type == bfd_link_hash_common))) |
||
915 | { |
||
916 | count_exported++; |
||
917 | if (!pe_def_file->exports[i].flag_noname) |
||
918 | count_exported_byname++; |
||
919 | |||
920 | /* Only fill in the sections. The actual offsets are computed |
||
921 | in fill_exported_offsets() after common symbols are laid |
||
922 | out. */ |
||
923 | if (blhe->type == bfd_link_hash_defined) |
||
924 | exported_symbol_sections[i] = blhe->u.def.section; |
||
925 | else |
||
926 | exported_symbol_sections[i] = blhe->u.c.p->section; |
||
927 | |||
928 | if (pe_def_file->exports[i].ordinal != -1) |
||
929 | { |
||
930 | if (max_ordinal < pe_def_file->exports[i].ordinal) |
||
931 | max_ordinal = pe_def_file->exports[i].ordinal; |
||
932 | if (min_ordinal > pe_def_file->exports[i].ordinal) |
||
933 | min_ordinal = pe_def_file->exports[i].ordinal; |
||
934 | count_with_ordinals++; |
||
935 | } |
||
936 | } |
||
937 | /* Check for forward exports. These are indicated in DEF files by an |
||
938 | export directive of the form NAME1 = MODULE-NAME.EXTERNAL-NAME |
||
939 | but we must take care not to be fooled when the user wants to export |
||
940 | a symbol that actually really has a dot in it, so we only check |
||
941 | for them here, after real defined symbols have already been matched. */ |
||
942 | else if (strchr (pe_def_file->exports[i].internal_name, '.')) |
||
943 | { |
||
944 | count_exported++; |
||
945 | if (!pe_def_file->exports[i].flag_noname) |
||
946 | count_exported_byname++; |
||
947 | |||
948 | pe_def_file->exports[i].flag_forward = 1; |
||
949 | |||
950 | if (pe_def_file->exports[i].ordinal != -1) |
||
951 | { |
||
952 | if (max_ordinal < pe_def_file->exports[i].ordinal) |
||
953 | max_ordinal = pe_def_file->exports[i].ordinal; |
||
954 | if (min_ordinal > pe_def_file->exports[i].ordinal) |
||
955 | min_ordinal = pe_def_file->exports[i].ordinal; |
||
956 | count_with_ordinals++; |
||
957 | } |
||
958 | } |
||
959 | else if (blhe && blhe->type == bfd_link_hash_undefined) |
||
960 | { |
||
961 | /* xgettext:c-format */ |
||
962 | einfo (_("%XCannot export %s: symbol not defined\n"), |
||
963 | pe_def_file->exports[i].internal_name); |
||
964 | } |
||
965 | else if (blhe) |
||
966 | { |
||
967 | /* xgettext:c-format */ |
||
968 | einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"), |
||
969 | pe_def_file->exports[i].internal_name, |
||
970 | blhe->type, bfd_link_hash_defined); |
||
971 | } |
||
972 | else |
||
973 | { |
||
974 | /* xgettext:c-format */ |
||
975 | einfo (_("%XCannot export %s: symbol not found\n"), |
||
976 | pe_def_file->exports[i].internal_name); |
||
977 | } |
||
978 | free (name); |
||
979 | } |
||
980 | } |
||
981 | |||
982 | /* Build the bfd that will contain .edata and .reloc sections. */ |
||
983 | |||
984 | static void |
||
985 | build_filler_bfd (int include_edata) |
||
986 | { |
||
987 | lang_input_statement_type *filler_file; |
||
988 | filler_file = lang_add_input_file ("dll stuff", |
||
989 | lang_input_file_is_fake_enum, |
||
990 | NULL); |
||
991 | filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", |
||
992 | link_info.output_bfd); |
||
993 | if (filler_bfd == NULL |
||
994 | || !bfd_set_arch_mach (filler_bfd, |
||
995 | bfd_get_arch (link_info.output_bfd), |
||
996 | bfd_get_mach (link_info.output_bfd))) |
||
997 | { |
||
998 | einfo ("%X%P: can not create BFD: %E\n"); |
||
999 | return; |
||
1000 | } |
||
1001 | |||
1002 | if (include_edata) |
||
1003 | { |
||
1004 | edata_s = bfd_make_section_old_way (filler_bfd, ".edata"); |
||
1005 | if (edata_s == NULL |
||
1006 | || !bfd_set_section_flags (filler_bfd, edata_s, |
||
1007 | (SEC_HAS_CONTENTS |
||
1008 | | SEC_ALLOC |
||
1009 | | SEC_LOAD |
||
1010 | | SEC_KEEP |
||
1011 | | SEC_IN_MEMORY))) |
||
1012 | { |
||
1013 | einfo ("%X%P: can not create .edata section: %E\n"); |
||
1014 | return; |
||
1015 | } |
||
1016 | bfd_set_section_size (filler_bfd, edata_s, edata_sz); |
||
1017 | } |
||
1018 | |||
1019 | reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc"); |
||
1020 | if (reloc_s == NULL |
||
1021 | || !bfd_set_section_flags (filler_bfd, reloc_s, |
||
1022 | (SEC_HAS_CONTENTS |
||
1023 | | SEC_ALLOC |
||
1024 | | SEC_LOAD |
||
1025 | | SEC_KEEP |
||
1026 | | SEC_IN_MEMORY))) |
||
1027 | { |
||
1028 | einfo ("%X%P: can not create .reloc section: %E\n"); |
||
1029 | return; |
||
1030 | } |
||
1031 | |||
1032 | bfd_set_section_size (filler_bfd, reloc_s, 0); |
||
1033 | |||
1034 | ldlang_add_file (filler_file); |
||
1035 | } |
||
1036 | |||
1037 | /* Gather all the exported symbols and build the .edata section. */ |
||
1038 | |||
1039 | static void |
||
1040 | generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) |
||
1041 | { |
||
1042 | int i, next_ordinal; |
||
1043 | int name_table_size = 0; |
||
1044 | const char *dlnp; |
||
1045 | |||
1046 | /* First, we need to know how many exported symbols there are, |
||
1047 | and what the range of ordinals is. */ |
||
1048 | if (pe_def_file->name) |
||
1049 | dll_name = pe_def_file->name; |
||
1050 | else |
||
1051 | { |
||
1052 | dll_name = abfd->filename; |
||
1053 | |||
1054 | for (dlnp = dll_name; *dlnp; dlnp++) |
||
1055 | if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':') |
||
1056 | dll_name = dlnp + 1; |
||
1057 | } |
||
1058 | |||
1059 | if (count_with_ordinals && max_ordinal > count_exported) |
||
1060 | { |
||
1061 | if (min_ordinal > max_ordinal - count_exported + 1) |
||
1062 | min_ordinal = max_ordinal - count_exported + 1; |
||
1063 | } |
||
1064 | else |
||
1065 | { |
||
1066 | min_ordinal = 1; |
||
1067 | max_ordinal = count_exported; |
||
1068 | } |
||
1069 | |||
1070 | export_table_size = max_ordinal - min_ordinal + 1; |
||
1071 | exported_symbols = xmalloc (export_table_size * sizeof (int)); |
||
1072 | for (i = 0; i < export_table_size; i++) |
||
1073 | exported_symbols[i] = -1; |
||
1074 | |||
1075 | /* Now we need to assign ordinals to those that don't have them. */ |
||
1076 | for (i = 0; i < NE; i++) |
||
1077 | { |
||
1078 | if (exported_symbol_sections[i] || |
||
1079 | pe_def_file->exports[i].flag_forward) |
||
1080 | { |
||
1081 | if (pe_def_file->exports[i].ordinal != -1) |
||
1082 | { |
||
1083 | int ei = pe_def_file->exports[i].ordinal - min_ordinal; |
||
1084 | int pi = exported_symbols[ei]; |
||
1085 | |||
1086 | if (pi != -1) |
||
1087 | { |
||
1088 | /* xgettext:c-format */ |
||
1089 | einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"), |
||
1090 | pe_def_file->exports[i].ordinal, |
||
1091 | pe_def_file->exports[i].name, |
||
1092 | pe_def_file->exports[pi].name); |
||
1093 | } |
||
1094 | exported_symbols[ei] = i; |
||
1095 | } |
||
1096 | if (pe_def_file->exports[i].its_name) |
||
1097 | name_table_size += strlen (pe_def_file->exports[i].its_name) + 1; |
||
1098 | else |
||
1099 | name_table_size += strlen (pe_def_file->exports[i].name) + 1; |
||
1100 | } |
||
1101 | |||
1102 | /* Reserve space for the forward name. */ |
||
1103 | if (pe_def_file->exports[i].flag_forward) |
||
1104 | { |
||
1105 | name_table_size += strlen (pe_def_file->exports[i].internal_name) + 1; |
||
1106 | } |
||
1107 | } |
||
1108 | |||
1109 | next_ordinal = min_ordinal; |
||
1110 | for (i = 0; i < NE; i++) |
||
1111 | if ((exported_symbol_sections[i] || |
||
1112 | pe_def_file->exports[i].flag_forward) && |
||
1113 | pe_def_file->exports[i].ordinal == -1) |
||
1114 | { |
||
1115 | while (exported_symbols[next_ordinal - min_ordinal] != -1) |
||
1116 | next_ordinal++; |
||
1117 | |||
1118 | exported_symbols[next_ordinal - min_ordinal] = i; |
||
1119 | pe_def_file->exports[i].ordinal = next_ordinal; |
||
1120 | } |
||
1121 | |||
1122 | /* OK, now we can allocate some memory. */ |
||
1123 | edata_sz = (40 /* directory */ |
||
1124 | + 4 * export_table_size /* addresses */ |
||
1125 | + 4 * count_exported_byname /* name ptrs */ |
||
1126 | + 2 * count_exported_byname /* ordinals */ |
||
1127 | + name_table_size + strlen (dll_name) + 1); |
||
1128 | } |
||
1129 | |||
1130 | /* Fill the exported symbol offsets. The preliminary work has already |
||
1131 | been done in process_def_file_and_drectve(). */ |
||
1132 | |||
1133 | static void |
||
1134 | fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) |
||
1135 | { |
||
1136 | int i; |
||
1137 | struct bfd_link_hash_entry *blhe; |
||
1138 | |||
1139 | for (i = 0; i < pe_def_file->num_exports; i++) |
||
1140 | { |
||
1141 | char *name; |
||
1142 | |||
1143 | name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); |
||
1144 | if (pe_details->underscored |
||
1145 | && *pe_def_file->exports[i].internal_name != '@') |
||
1146 | { |
||
1147 | *name = '_'; |
||
1148 | strcpy (name + 1, pe_def_file->exports[i].internal_name); |
||
1149 | } |
||
1150 | else |
||
1151 | strcpy (name, pe_def_file->exports[i].internal_name); |
||
1152 | |||
1153 | blhe = bfd_link_hash_lookup (info->hash, |
||
1154 | name, |
||
1155 | FALSE, FALSE, TRUE); |
||
1156 | |||
1157 | if (blhe && blhe->type == bfd_link_hash_defined) |
||
1158 | exported_symbol_offsets[i] = blhe->u.def.value; |
||
1159 | |||
1160 | free (name); |
||
1161 | } |
||
1162 | } |
||
1163 | |||
1164 | static void |
||
1165 | fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) |
||
1166 | { |
||
1167 | int s, hint; |
||
1168 | unsigned char *edirectory; |
||
1169 | unsigned char *eaddresses; |
||
1170 | unsigned char *enameptrs; |
||
1171 | unsigned char *eordinals; |
||
1172 | char *enamestr; |
||
1173 | |||
1174 | edata_d = xmalloc (edata_sz); |
||
1175 | |||
1176 | /* Note use of array pointer math here. */ |
||
1177 | edirectory = edata_d; |
||
1178 | eaddresses = edirectory + 40; |
||
1179 | enameptrs = eaddresses + 4 * export_table_size; |
||
1180 | eordinals = enameptrs + 4 * count_exported_byname; |
||
1181 | enamestr = (char *) eordinals + 2 * count_exported_byname; |
||
1182 | |||
1183 | #define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \ |
||
1184 | + edata_s->output_section->vma - image_base) |
||
1185 | |||
1186 | memset (edata_d, 0, edata_sz); |
||
1187 | |||
1188 | if (pe_data (abfd)->insert_timestamp) |
||
1189 | H_PUT_32 (abfd, time (0), edata_d + 4); |
||
1190 | |||
1191 | if (pe_def_file->version_major != -1) |
||
1192 | { |
||
1193 | bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8); |
||
1194 | bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10); |
||
1195 | } |
||
1196 | |||
1197 | bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12); |
||
1198 | strcpy (enamestr, dll_name); |
||
1199 | enamestr += strlen (enamestr) + 1; |
||
1200 | bfd_put_32 (abfd, min_ordinal, edata_d + 16); |
||
1201 | bfd_put_32 (abfd, export_table_size, edata_d + 20); |
||
1202 | bfd_put_32 (abfd, count_exported_byname, edata_d + 24); |
||
1203 | bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28); |
||
1204 | bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32); |
||
1205 | bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36); |
||
1206 | |||
1207 | fill_exported_offsets (abfd, info); |
||
1208 | |||
1209 | /* Ok, now for the filling in part. |
||
1210 | Scan alphabetically - ie the ordering in the exports[] table, |
||
1211 | rather than by ordinal - the ordering in the exported_symbol[] |
||
1212 | table. See dlltool.c and: |
||
1213 | http://sources.redhat.com/ml/binutils/2003-04/msg00379.html |
||
1214 | for more information. */ |
||
1215 | hint = 0; |
||
1216 | for (s = 0; s < NE; s++) |
||
1217 | { |
||
1218 | struct bfd_section *ssec = exported_symbol_sections[s]; |
||
1219 | if (pe_def_file->exports[s].ordinal != -1 && |
||
1220 | (pe_def_file->exports[s].flag_forward || ssec != NULL)) |
||
1221 | { |
||
1222 | int ord = pe_def_file->exports[s].ordinal; |
||
1223 | |||
1224 | if (pe_def_file->exports[s].flag_forward) |
||
1225 | { |
||
1226 | bfd_put_32 (abfd, ERVA (enamestr), |
||
1227 | eaddresses + 4 * (ord - min_ordinal)); |
||
1228 | |||
1229 | strcpy (enamestr, pe_def_file->exports[s].internal_name); |
||
1230 | enamestr += strlen (pe_def_file->exports[s].internal_name) + 1; |
||
1231 | } |
||
1232 | else |
||
1233 | { |
||
1234 | bfd_vma srva = (exported_symbol_offsets[s] |
||
1235 | + ssec->output_section->vma |
||
1236 | + ssec->output_offset); |
||
1237 | |||
1238 | bfd_put_32 (abfd, srva - image_base, |
||
1239 | eaddresses + 4 * (ord - min_ordinal)); |
||
1240 | } |
||
1241 | |||
1242 | if (!pe_def_file->exports[s].flag_noname) |
||
1243 | { |
||
1244 | char *ename = pe_def_file->exports[s].name; |
||
1245 | if (pe_def_file->exports[s].its_name) |
||
1246 | ename = pe_def_file->exports[s].its_name; |
||
1247 | |||
1248 | bfd_put_32 (abfd, ERVA (enamestr), enameptrs); |
||
1249 | enameptrs += 4; |
||
1250 | strcpy (enamestr, ename); |
||
1251 | enamestr += strlen (enamestr) + 1; |
||
1252 | bfd_put_16 (abfd, ord - min_ordinal, eordinals); |
||
1253 | eordinals += 2; |
||
1254 | pe_def_file->exports[s].hint = hint++; |
||
1255 | } |
||
1256 | } |
||
1257 | } |
||
1258 | } |
||
1259 | |||
1260 | |||
1261 | static struct bfd_section *current_sec; |
||
1262 | |||
1263 | void |
||
1264 | pe_walk_relocs_of_symbol (struct bfd_link_info *info, |
||
1265 | const char *name, |
||
1266 | int (*cb) (arelent *, asection *)) |
||
1267 | { |
||
1268 | bfd *b; |
||
1269 | asection *s; |
||
1270 | |||
1271 | for (b = info->input_bfds; b; b = b->link_next) |
||
1272 | { |
||
1273 | asymbol **symbols; |
||
1274 | |||
1275 | if (!bfd_generic_link_read_symbols (b)) |
||
1276 | { |
||
1277 | einfo (_("%B%F: could not read symbols: %E\n"), b); |
||
1278 | return; |
||
1279 | } |
||
1280 | |||
1281 | symbols = bfd_get_outsymbols (b); |
||
1282 | |||
1283 | for (s = b->sections; s; s = s->next) |
||
1284 | { |
||
1285 | arelent **relocs; |
||
1286 | int relsize, nrelocs, i; |
||
1287 | int flags = bfd_get_section_flags (b, s); |
||
1288 | |||
1289 | /* Skip discarded linkonce sections. */ |
||
1290 | if (flags & SEC_LINK_ONCE |
||
1291 | && s->output_section == bfd_abs_section_ptr) |
||
1292 | continue; |
||
1293 | |||
1294 | current_sec = s; |
||
1295 | |||
1296 | relsize = bfd_get_reloc_upper_bound (b, s); |
||
1297 | relocs = xmalloc (relsize); |
||
1298 | nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); |
||
1299 | |||
1300 | for (i = 0; i < nrelocs; i++) |
||
1301 | { |
||
1302 | struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr; |
||
1303 | |||
1304 | if (!strcmp (name, sym->name)) |
||
1305 | cb (relocs[i], s); |
||
1306 | } |
||
1307 | |||
1308 | free (relocs); |
||
1309 | |||
1310 | /* Warning: the allocated symbols are remembered in BFD and reused |
||
1311 | later, so don't free them! */ |
||
1312 | /* free (symbols); */ |
||
1313 | } |
||
1314 | } |
||
1315 | } |
||
1316 | |||
1317 | /* Gather all the relocations and build the .reloc section. */ |
||
1318 | |||
1319 | static void |
||
1320 | generate_reloc (bfd *abfd, struct bfd_link_info *info) |
||
1321 | { |
||
1322 | |||
1323 | /* For .reloc stuff. */ |
||
1324 | reloc_data_type *reloc_data; |
||
1325 | int total_relocs = 0; |
||
1326 | int i; |
||
1327 | bfd_vma sec_page = (bfd_vma) -1; |
||
1328 | bfd_vma page_ptr, page_count; |
||
1329 | int bi; |
||
1330 | bfd *b; |
||
1331 | struct bfd_section *s; |
||
1332 | |||
1333 | total_relocs = 0; |
||
1334 | for (b = info->input_bfds; b; b = b->link_next) |
||
1335 | for (s = b->sections; s; s = s->next) |
||
1336 | total_relocs += s->reloc_count; |
||
1337 | |||
1338 | reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type)); |
||
1339 | |||
1340 | total_relocs = 0; |
||
1341 | bi = 0; |
||
1342 | for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next) |
||
1343 | { |
||
1344 | arelent **relocs; |
||
1345 | int relsize, nrelocs; |
||
1346 | |||
1347 | for (s = b->sections; s; s = s->next) |
||
1348 | { |
||
1349 | bfd_vma sec_vma = s->output_section->vma + s->output_offset; |
||
1350 | asymbol **symbols; |
||
1351 | |||
1352 | /* If it's not loaded, we don't need to relocate it this way. */ |
||
1353 | if (!(s->output_section->flags & SEC_LOAD)) |
||
1354 | continue; |
||
1355 | |||
1356 | /* I don't know why there would be a reloc for these, but I've |
||
1357 | seen it happen - DJ */ |
||
1358 | if (s->output_section == bfd_abs_section_ptr) |
||
1359 | continue; |
||
1360 | |||
1361 | if (s->output_section->vma == 0) |
||
1362 | { |
||
1363 | /* Huh? Shouldn't happen, but punt if it does. */ |
||
1364 | einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n", |
||
1365 | s->output_section->name, s->output_section->index, |
||
1366 | s->output_section->flags); |
||
1367 | continue; |
||
1368 | } |
||
1369 | |||
1370 | if (!bfd_generic_link_read_symbols (b)) |
||
1371 | { |
||
1372 | einfo (_("%B%F: could not read symbols: %E\n"), b); |
||
1373 | return; |
||
1374 | } |
||
1375 | |||
1376 | symbols = bfd_get_outsymbols (b); |
||
1377 | relsize = bfd_get_reloc_upper_bound (b, s); |
||
1378 | relocs = xmalloc (relsize); |
||
1379 | nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); |
||
1380 | |||
1381 | for (i = 0; i < nrelocs; i++) |
||
1382 | { |
||
1383 | if (pe_dll_extra_pe_debug) |
||
1384 | { |
||
1385 | struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr; |
||
1386 | printf ("rel: %s\n", sym->name); |
||
1387 | } |
||
1388 | if (!relocs[i]->howto->pc_relative |
||
1389 | && relocs[i]->howto->type != pe_details->imagebase_reloc) |
||
1390 | { |
||
1391 | struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr; |
||
1392 | |||
1393 | /* Don't create relocs for undefined weak symbols. */ |
||
1394 | if (sym->flags == BSF_WEAK) |
||
1395 | { |
||
1396 | struct bfd_link_hash_entry *blhe |
||
1397 | = bfd_wrapped_link_hash_lookup (abfd, info, sym->name, |
||
1398 | FALSE, FALSE, FALSE); |
||
1399 | if (blhe && blhe->type == bfd_link_hash_undefweak) |
||
1400 | { |
||
1401 | /* Check aux sym and see if it is defined or not. */ |
||
1402 | struct coff_link_hash_entry *h, *h2; |
||
1403 | h = (struct coff_link_hash_entry *)blhe; |
||
1404 | if (h->symbol_class != C_NT_WEAK || h->numaux != 1) |
||
1405 | continue; |
||
1406 | h2 = h->auxbfd->tdata.coff_obj_data->sym_hashes |
||
1407 | [h->aux->x_sym.x_tagndx.l]; |
||
1408 | /* We don't want a base reloc if the aux sym is not |
||
1409 | found, undefined, or if it is the constant ABS |
||
1410 | zero default value. (We broaden that slightly by |
||
1411 | not testing the value, just the section; there's |
||
1412 | no reason we'd want a reference to any absolute |
||
1413 | address to get relocated during rebasing). */ |
||
1414 | if (!h2 || h2->root.type == bfd_link_hash_undefined |
||
1415 | || h2->root.u.def.section == bfd_abs_section_ptr) |
||
1416 | continue; |
||
1417 | } |
||
1418 | else if (!blhe || blhe->type != bfd_link_hash_defined) |
||
1419 | continue; |
||
1420 | } |
||
1421 | /* Nor for Dwarf FDE references to discarded sections. */ |
||
1422 | else if (bfd_is_abs_section (sym->section->output_section)) |
||
1423 | { |
||
1424 | /* We only ignore relocs from .eh_frame sections, as |
||
1425 | they are discarded by the final link rather than |
||
1426 | resolved against the kept section. */ |
||
1427 | if (!strcmp (s->name, ".eh_frame")) |
||
1428 | continue; |
||
1429 | } |
||
1430 | |||
1431 | reloc_data[total_relocs].vma = sec_vma + relocs[i]->address; |
||
1432 | |||
1433 | #define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift) |
||
1434 | |||
1435 | switch BITS_AND_SHIFT (relocs[i]->howto->bitsize, |
||
1436 | relocs[i]->howto->rightshift) |
||
1437 | { |
||
1438 | #ifdef pe_use_x86_64 |
||
1439 | case BITS_AND_SHIFT (64, 0): |
||
1440 | reloc_data[total_relocs].type = 10; |
||
1441 | total_relocs++; |
||
1442 | break; |
||
1443 | #endif |
||
1444 | case BITS_AND_SHIFT (32, 0): |
||
1445 | reloc_data[total_relocs].type = 3; |
||
1446 | total_relocs++; |
||
1447 | break; |
||
1448 | case BITS_AND_SHIFT (16, 0): |
||
1449 | reloc_data[total_relocs].type = 2; |
||
1450 | total_relocs++; |
||
1451 | break; |
||
1452 | case BITS_AND_SHIFT (16, 16): |
||
1453 | reloc_data[total_relocs].type = 4; |
||
1454 | /* FIXME: we can't know the symbol's right value |
||
1455 | yet, but we probably can safely assume that |
||
1456 | CE will relocate us in 64k blocks, so leaving |
||
1457 | it zero is safe. */ |
||
1458 | reloc_data[total_relocs].extra = 0; |
||
1459 | total_relocs++; |
||
1460 | break; |
||
1461 | case BITS_AND_SHIFT (26, 2): |
||
1462 | reloc_data[total_relocs].type = 5; |
||
1463 | total_relocs++; |
||
1464 | break; |
||
1465 | case BITS_AND_SHIFT (24, 2): |
||
1466 | /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c |
||
1467 | Those ARM_xxx definitions should go in proper |
||
1468 | header someday. */ |
||
1469 | if (relocs[i]->howto->type == 0 |
||
1470 | /* Older GNU linkers used 5 instead of 0 for this reloc. */ |
||
1471 | || relocs[i]->howto->type == 5) |
||
1472 | /* This is an ARM_26D reloc, which is an ARM_26 reloc |
||
1473 | that has already been fully processed during a |
||
1474 | previous link stage, so ignore it here. */ |
||
1475 | break; |
||
1476 | /* Fall through. */ |
||
1477 | default: |
||
1478 | /* xgettext:c-format */ |
||
1479 | einfo (_("%XError: %d-bit reloc in dll\n"), |
||
1480 | relocs[i]->howto->bitsize); |
||
1481 | break; |
||
1482 | } |
||
1483 | } |
||
1484 | } |
||
1485 | free (relocs); |
||
1486 | /* Warning: the allocated symbols are remembered in BFD and |
||
1487 | reused later, so don't free them! */ |
||
1488 | } |
||
1489 | } |
||
1490 | |||
1491 | /* At this point, we have total_relocs relocation addresses in |
||
1492 | reloc_addresses, which are all suitable for the .reloc section. |
||
1493 | We must now create the new sections. */ |
||
1494 | qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort); |
||
1495 | |||
1496 | for (i = 0; i < total_relocs; i++) |
||
1497 | { |
||
1498 | bfd_vma this_page = (reloc_data[i].vma >> 12); |
||
1499 | |||
1500 | if (this_page != sec_page) |
||
1501 | { |
||
1502 | reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ |
||
1503 | reloc_sz += 8; |
||
1504 | sec_page = this_page; |
||
1505 | } |
||
1506 | |||
1507 | reloc_sz += 2; |
||
1508 | |||
1509 | if (reloc_data[i].type == 4) |
||
1510 | reloc_sz += 2; |
||
1511 | } |
||
1512 | |||
1513 | reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ |
||
1514 | reloc_d = xmalloc (reloc_sz); |
||
1515 | sec_page = (bfd_vma) -1; |
||
1516 | reloc_sz = 0; |
||
1517 | page_ptr = (bfd_vma) -1; |
||
1518 | page_count = 0; |
||
1519 | |||
1520 | for (i = 0; i < total_relocs; i++) |
||
1521 | { |
||
1522 | bfd_vma rva = reloc_data[i].vma - image_base; |
||
1523 | bfd_vma this_page = (rva & ~0xfff); |
||
1524 | |||
1525 | if (this_page != sec_page) |
||
1526 | { |
||
1527 | while (reloc_sz & 3) |
||
1528 | reloc_d[reloc_sz++] = 0; |
||
1529 | |||
1530 | if (page_ptr != (bfd_vma) -1) |
||
1531 | bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); |
||
1532 | |||
1533 | bfd_put_32 (abfd, this_page, reloc_d + reloc_sz); |
||
1534 | page_ptr = reloc_sz; |
||
1535 | reloc_sz += 8; |
||
1536 | sec_page = this_page; |
||
1537 | page_count = 0; |
||
1538 | } |
||
1539 | |||
1540 | bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12), |
||
1541 | reloc_d + reloc_sz); |
||
1542 | reloc_sz += 2; |
||
1543 | |||
1544 | if (reloc_data[i].type == 4) |
||
1545 | { |
||
1546 | bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz); |
||
1547 | reloc_sz += 2; |
||
1548 | } |
||
1549 | |||
1550 | page_count++; |
||
1551 | } |
||
1552 | |||
1553 | while (reloc_sz & 3) |
||
1554 | reloc_d[reloc_sz++] = 0; |
||
1555 | |||
1556 | if (page_ptr != (bfd_vma) -1) |
||
1557 | bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); |
||
1558 | |||
1559 | while (reloc_sz < reloc_s->size) |
||
1560 | reloc_d[reloc_sz++] = 0; |
||
1561 | } |
||
1562 | |||
1563 | /* Given the exiting def_file structure, print out a .DEF file that |
||
1564 | corresponds to it. */ |
||
1565 | |||
1566 | static void |
||
1567 | quoteput (char *s, FILE *f, int needs_quotes) |
||
1568 | { |
||
1569 | char *cp; |
||
1570 | |||
1571 | for (cp = s; *cp; cp++) |
||
1572 | if (*cp == '\'' |
||
1573 | || *cp == '"' |
||
1574 | || *cp == '\\' |
||
1575 | || ISSPACE (*cp) |
||
1576 | || *cp == ',' |
||
1577 | || *cp == ';') |
||
1578 | needs_quotes = 1; |
||
1579 | |||
1580 | if (needs_quotes) |
||
1581 | { |
||
1582 | putc ('"', f); |
||
1583 | |||
1584 | while (*s) |
||
1585 | { |
||
1586 | if (*s == '"' || *s == '\\') |
||
1587 | putc ('\\', f); |
||
1588 | |||
1589 | putc (*s, f); |
||
1590 | s++; |
||
1591 | } |
||
1592 | |||
1593 | putc ('"', f); |
||
1594 | } |
||
1595 | else |
||
1596 | fputs (s, f); |
||
1597 | } |
||
1598 | |||
1599 | void |
||
1600 | pe_dll_generate_def_file (const char *pe_out_def_filename) |
||
1601 | { |
||
1602 | int i; |
||
1603 | FILE *out = fopen (pe_out_def_filename, "w"); |
||
1604 | |||
1605 | if (out == NULL) |
||
1606 | /* xgettext:c-format */ |
||
1607 | einfo (_("%s: Can't open output def file %s\n"), |
||
1608 | program_name, pe_out_def_filename); |
||
1609 | |||
1610 | if (pe_def_file) |
||
1611 | { |
||
1612 | if (pe_def_file->name) |
||
1613 | { |
||
1614 | if (pe_def_file->is_dll) |
||
1615 | fprintf (out, "LIBRARY "); |
||
1616 | else |
||
1617 | fprintf (out, "NAME "); |
||
1618 | |||
1619 | quoteput (pe_def_file->name, out, 1); |
||
1620 | |||
1621 | if (pe_data (link_info.output_bfd)->pe_opthdr.ImageBase) |
||
1622 | { |
||
1623 | fprintf (out, " BASE=0x"); |
||
1624 | fprintf_vma (out, ((bfd_vma) pe_data (link_info.output_bfd)->pe_opthdr.ImageBase)); |
||
1625 | } |
||
1626 | fprintf (out, "\n"); |
||
1627 | } |
||
1628 | |||
1629 | if (pe_def_file->description) |
||
1630 | { |
||
1631 | fprintf (out, "DESCRIPTION "); |
||
1632 | quoteput (pe_def_file->description, out, 1); |
||
1633 | fprintf (out, "\n"); |
||
1634 | } |
||
1635 | |||
1636 | if (pe_def_file->version_minor != -1) |
||
1637 | fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major, |
||
1638 | pe_def_file->version_minor); |
||
1639 | else if (pe_def_file->version_major != -1) |
||
1640 | fprintf (out, "VERSION %d\n", pe_def_file->version_major); |
||
1641 | |||
1642 | if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1) |
||
1643 | fprintf (out, "\n"); |
||
1644 | |||
1645 | if (pe_def_file->stack_commit != -1) |
||
1646 | fprintf (out, "STACKSIZE 0x%x,0x%x\n", |
||
1647 | pe_def_file->stack_reserve, pe_def_file->stack_commit); |
||
1648 | else if (pe_def_file->stack_reserve != -1) |
||
1649 | fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve); |
||
1650 | |||
1651 | if (pe_def_file->heap_commit != -1) |
||
1652 | fprintf (out, "HEAPSIZE 0x%x,0x%x\n", |
||
1653 | pe_def_file->heap_reserve, pe_def_file->heap_commit); |
||
1654 | else if (pe_def_file->heap_reserve != -1) |
||
1655 | fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve); |
||
1656 | |||
1657 | if (pe_def_file->num_section_defs > 0) |
||
1658 | { |
||
1659 | fprintf (out, "\nSECTIONS\n\n"); |
||
1660 | |||
1661 | for (i = 0; i < pe_def_file->num_section_defs; i++) |
||
1662 | { |
||
1663 | fprintf (out, " "); |
||
1664 | quoteput (pe_def_file->section_defs[i].name, out, 0); |
||
1665 | |||
1666 | if (pe_def_file->section_defs[i].class) |
||
1667 | { |
||
1668 | fprintf (out, " CLASS "); |
||
1669 | quoteput (pe_def_file->section_defs[i].class, out, 0); |
||
1670 | } |
||
1671 | |||
1672 | if (pe_def_file->section_defs[i].flag_read) |
||
1673 | fprintf (out, " READ"); |
||
1674 | |||
1675 | if (pe_def_file->section_defs[i].flag_write) |
||
1676 | fprintf (out, " WRITE"); |
||
1677 | |||
1678 | if (pe_def_file->section_defs[i].flag_execute) |
||
1679 | fprintf (out, " EXECUTE"); |
||
1680 | |||
1681 | if (pe_def_file->section_defs[i].flag_shared) |
||
1682 | fprintf (out, " SHARED"); |
||
1683 | |||
1684 | fprintf (out, "\n"); |
||
1685 | } |
||
1686 | } |
||
1687 | |||
1688 | if (pe_def_file->num_exports > 0) |
||
1689 | { |
||
1690 | fprintf (out, "EXPORTS\n"); |
||
1691 | |||
1692 | for (i = 0; i < pe_def_file->num_exports; i++) |
||
1693 | { |
||
1694 | def_file_export *e = pe_def_file->exports + i; |
||
1695 | fprintf (out, " "); |
||
1696 | quoteput (e->name, out, 0); |
||
1697 | |||
1698 | if (e->internal_name && strcmp (e->internal_name, e->name)) |
||
1699 | { |
||
1700 | fprintf (out, " = "); |
||
1701 | quoteput (e->internal_name, out, 0); |
||
1702 | } |
||
1703 | |||
1704 | if (e->ordinal != -1) |
||
1705 | fprintf (out, " @%d", e->ordinal); |
||
1706 | |||
1707 | if (e->flag_private) |
||
1708 | fprintf (out, " PRIVATE"); |
||
1709 | |||
1710 | if (e->flag_constant) |
||
1711 | fprintf (out, " CONSTANT"); |
||
1712 | |||
1713 | if (e->flag_noname) |
||
1714 | fprintf (out, " NONAME"); |
||
1715 | |||
1716 | if (e->flag_data) |
||
1717 | fprintf (out, " DATA"); |
||
1718 | |||
1719 | fprintf (out, "\n"); |
||
1720 | } |
||
1721 | } |
||
1722 | |||
1723 | if (pe_def_file->num_imports > 0) |
||
1724 | { |
||
1725 | fprintf (out, "\nIMPORTS\n\n"); |
||
1726 | |||
1727 | for (i = 0; i < pe_def_file->num_imports; i++) |
||
1728 | { |
||
1729 | def_file_import *im = pe_def_file->imports + i; |
||
1730 | fprintf (out, " "); |
||
1731 | |||
1732 | if (im->internal_name |
||
1733 | && (!im->name || strcmp (im->internal_name, im->name))) |
||
1734 | { |
||
1735 | quoteput (im->internal_name, out, 0); |
||
1736 | fprintf (out, " = "); |
||
1737 | } |
||
1738 | |||
1739 | quoteput (im->module->name, out, 0); |
||
1740 | fprintf (out, "."); |
||
1741 | |||
1742 | if (im->name) |
||
1743 | quoteput (im->name, out, 0); |
||
1744 | else |
||
1745 | fprintf (out, "%d", im->ordinal); |
||
1746 | |||
1747 | if (im->its_name) |
||
1748 | { |
||
1749 | fprintf (out, " == "); |
||
1750 | quoteput (im->its_name, out, 0); |
||
1751 | } |
||
1752 | |||
1753 | fprintf (out, "\n"); |
||
1754 | } |
||
1755 | } |
||
1756 | } |
||
1757 | else |
||
1758 | fprintf (out, _("; no contents available\n")); |
||
1759 | |||
1760 | if (fclose (out) == EOF) |
||
1761 | /* xgettext:c-format */ |
||
1762 | einfo (_("%P: Error closing file `%s'\n"), pe_out_def_filename); |
||
1763 | } |
||
1764 | |||
1765 | /* Generate the import library. */ |
||
1766 | |||
1767 | static asymbol **symtab; |
||
1768 | static int symptr; |
||
1769 | static int tmp_seq; |
||
1770 | static int tmp_seq2; |
||
1771 | static const char *dll_filename; |
||
1772 | static char *dll_symname; |
||
1773 | |||
1774 | #define UNDSEC bfd_und_section_ptr |
||
1775 | |||
1776 | static asection * |
||
1777 | quick_section (bfd *abfd, const char *name, int flags, int align) |
||
1778 | { |
||
1779 | asection *sec; |
||
1780 | asymbol *sym; |
||
1781 | |||
1782 | sec = bfd_make_section_old_way (abfd, name); |
||
1783 | bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP); |
||
1784 | bfd_set_section_alignment (abfd, sec, align); |
||
1785 | /* Remember to undo this before trying to link internally! */ |
||
1786 | sec->output_section = sec; |
||
1787 | |||
1788 | sym = bfd_make_empty_symbol (abfd); |
||
1789 | symtab[symptr++] = sym; |
||
1790 | sym->name = sec->name; |
||
1791 | sym->section = sec; |
||
1792 | sym->flags = BSF_LOCAL; |
||
1793 | sym->value = 0; |
||
1794 | |||
1795 | return sec; |
||
1796 | } |
||
1797 | |||
1798 | static void |
||
1799 | quick_symbol (bfd *abfd, |
||
1800 | const char *n1, |
||
1801 | const char *n2, |
||
1802 | const char *n3, |
||
1803 | asection *sec, |
||
1804 | int flags, |
||
1805 | int addr) |
||
1806 | { |
||
1807 | asymbol *sym; |
||
1808 | char *name = xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1); |
||
1809 | |||
1810 | strcpy (name, n1); |
||
1811 | strcat (name, n2); |
||
1812 | strcat (name, n3); |
||
1813 | sym = bfd_make_empty_symbol (abfd); |
||
1814 | sym->name = name; |
||
1815 | sym->section = sec; |
||
1816 | sym->flags = flags; |
||
1817 | sym->value = addr; |
||
1818 | symtab[symptr++] = sym; |
||
1819 | } |
||
1820 | |||
1821 | static arelent *reltab = 0; |
||
1822 | static int relcount = 0, relsize = 0; |
||
1823 | |||
1824 | static void |
||
1825 | quick_reloc (bfd *abfd, bfd_size_type address, int which_howto, int symidx) |
||
1826 | { |
||
1827 | if (relcount >= relsize - 1) |
||
1828 | { |
||
1829 | relsize += 10; |
||
1830 | if (reltab) |
||
1831 | reltab = xrealloc (reltab, relsize * sizeof (arelent)); |
||
1832 | else |
||
1833 | reltab = xmalloc (relsize * sizeof (arelent)); |
||
1834 | } |
||
1835 | reltab[relcount].address = address; |
||
1836 | reltab[relcount].addend = 0; |
||
1837 | reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto); |
||
1838 | reltab[relcount].sym_ptr_ptr = symtab + symidx; |
||
1839 | relcount++; |
||
1840 | } |
||
1841 | |||
1842 | static void |
||
1843 | save_relocs (asection *sec) |
||
1844 | { |
||
1845 | int i; |
||
1846 | |||
1847 | sec->relocation = reltab; |
||
1848 | sec->reloc_count = relcount; |
||
1849 | sec->orelocation = xmalloc ((relcount + 1) * sizeof (arelent *)); |
||
1850 | for (i = 0; i < relcount; i++) |
||
1851 | sec->orelocation[i] = sec->relocation + i; |
||
1852 | sec->orelocation[relcount] = 0; |
||
1853 | sec->flags |= SEC_RELOC; |
||
1854 | reltab = 0; |
||
1855 | relcount = relsize = 0; |
||
1856 | } |
||
1857 | |||
1858 | /* .section .idata$2 |
||
1859 | .global __head_my_dll |
||
1860 | __head_my_dll: |
||
1861 | .rva hname |
||
1862 | .long 0 |
||
1863 | .long 0 |
||
1864 | .rva __my_dll_iname |
||
1865 | .rva fthunk |
||
1866 | |||
1867 | .section .idata$5 |
||
1868 | .long 0 |
||
1869 | fthunk: |
||
1870 | |||
1871 | .section .idata$4 |
||
1872 | .long 0 |
||
1873 | hname: */ |
||
1874 | |||
1875 | static bfd * |
||
1876 | make_head (bfd *parent) |
||
1877 | { |
||
1878 | asection *id2, *id5, *id4; |
||
1879 | unsigned char *d2, *d5, *d4; |
||
1880 | char *oname; |
||
1881 | bfd *abfd; |
||
1882 | |||
1883 | oname = xmalloc (20); |
||
1884 | sprintf (oname, "d%06d.o", tmp_seq); |
||
1885 | tmp_seq++; |
||
1886 | |||
1887 | abfd = bfd_create (oname, parent); |
||
1888 | bfd_find_target (pe_details->object_target, abfd); |
||
1889 | bfd_make_writable (abfd); |
||
1890 | |||
1891 | bfd_set_format (abfd, bfd_object); |
||
1892 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
1893 | |||
1894 | symptr = 0; |
||
1895 | symtab = xmalloc (6 * sizeof (asymbol *)); |
||
1896 | id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2); |
||
1897 | id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); |
||
1898 | id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); |
||
1899 | quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0); |
||
1900 | quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0); |
||
1901 | |||
1902 | /* OK, pay attention here. I got confused myself looking back at |
||
1903 | it. We create a four-byte section to mark the beginning of the |
||
1904 | list, and we include an offset of 4 in the section, so that the |
||
1905 | pointer to the list points to the *end* of this section, which is |
||
1906 | the start of the list of sections from other objects. */ |
||
1907 | |||
1908 | bfd_set_section_size (abfd, id2, 20); |
||
1909 | d2 = xmalloc (20); |
||
1910 | id2->contents = d2; |
||
1911 | memset (d2, 0, 20); |
||
1912 | if (pe_use_nul_prefixed_import_tables) |
||
1913 | d2[0] = d2[16] = PE_IDATA5_SIZE; /* Reloc addend. */ |
||
1914 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); |
||
1915 | quick_reloc (abfd, 12, BFD_RELOC_RVA, 4); |
||
1916 | quick_reloc (abfd, 16, BFD_RELOC_RVA, 1); |
||
1917 | save_relocs (id2); |
||
1918 | |||
1919 | if (pe_use_nul_prefixed_import_tables) |
||
1920 | bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE); |
||
1921 | else |
||
1922 | bfd_set_section_size (abfd, id5, 0); |
||
1923 | d5 = xmalloc (PE_IDATA5_SIZE); |
||
1924 | id5->contents = d5; |
||
1925 | memset (d5, 0, PE_IDATA5_SIZE); |
||
1926 | if (pe_use_nul_prefixed_import_tables) |
||
1927 | bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE); |
||
1928 | else |
||
1929 | bfd_set_section_size (abfd, id4, 0); |
||
1930 | d4 = xmalloc (PE_IDATA4_SIZE); |
||
1931 | id4->contents = d4; |
||
1932 | memset (d4, 0, PE_IDATA4_SIZE); |
||
1933 | |||
1934 | bfd_set_symtab (abfd, symtab, symptr); |
||
1935 | |||
1936 | bfd_set_section_contents (abfd, id2, d2, 0, 20); |
||
1937 | if (pe_use_nul_prefixed_import_tables) |
||
1938 | { |
||
1939 | bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE); |
||
1940 | bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE); |
||
1941 | } |
||
1942 | else |
||
1943 | { |
||
1944 | bfd_set_section_contents (abfd, id5, d5, 0, 0); |
||
1945 | bfd_set_section_contents (abfd, id4, d4, 0, 0); |
||
1946 | } |
||
1947 | |||
1948 | bfd_make_readable (abfd); |
||
1949 | return abfd; |
||
1950 | } |
||
1951 | |||
1952 | /* .section .idata$4 |
||
1953 | .long 0 |
||
1954 | [.long 0] for PE+ |
||
1955 | .section .idata$5 |
||
1956 | .long 0 |
||
1957 | [.long 0] for PE+ |
||
1958 | .section idata$7 |
||
1959 | .global __my_dll_iname |
||
1960 | __my_dll_iname: |
||
1961 | .asciz "my.dll" */ |
||
1962 | |||
1963 | static bfd * |
||
1964 | make_tail (bfd *parent) |
||
1965 | { |
||
1966 | asection *id4, *id5, *id7; |
||
1967 | unsigned char *d4, *d5, *d7; |
||
1968 | int len; |
||
1969 | char *oname; |
||
1970 | bfd *abfd; |
||
1971 | |||
1972 | oname = xmalloc (20); |
||
1973 | sprintf (oname, "d%06d.o", tmp_seq); |
||
1974 | tmp_seq++; |
||
1975 | |||
1976 | abfd = bfd_create (oname, parent); |
||
1977 | bfd_find_target (pe_details->object_target, abfd); |
||
1978 | bfd_make_writable (abfd); |
||
1979 | |||
1980 | bfd_set_format (abfd, bfd_object); |
||
1981 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
1982 | |||
1983 | symptr = 0; |
||
1984 | symtab = xmalloc (5 * sizeof (asymbol *)); |
||
1985 | id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); |
||
1986 | id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); |
||
1987 | id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); |
||
1988 | quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0); |
||
1989 | |||
1990 | bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE); |
||
1991 | d4 = xmalloc (PE_IDATA4_SIZE); |
||
1992 | id4->contents = d4; |
||
1993 | memset (d4, 0, PE_IDATA4_SIZE); |
||
1994 | |||
1995 | bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE); |
||
1996 | d5 = xmalloc (PE_IDATA5_SIZE); |
||
1997 | id5->contents = d5; |
||
1998 | memset (d5, 0, PE_IDATA5_SIZE); |
||
1999 | |||
2000 | len = strlen (dll_filename) + 1; |
||
2001 | if (len & 1) |
||
2002 | len++; |
||
2003 | bfd_set_section_size (abfd, id7, len); |
||
2004 | d7 = xmalloc (len); |
||
2005 | id7->contents = d7; |
||
2006 | strcpy ((char *) d7, dll_filename); |
||
2007 | /* If len was odd, the above |
||
2008 | strcpy leaves behind an undefined byte. That is harmless, |
||
2009 | but we set it to 0 just so the binary dumps are pretty. */ |
||
2010 | d7[len - 1] = 0; |
||
2011 | |||
2012 | bfd_set_symtab (abfd, symtab, symptr); |
||
2013 | |||
2014 | bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE); |
||
2015 | bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE); |
||
2016 | bfd_set_section_contents (abfd, id7, d7, 0, len); |
||
2017 | |||
2018 | bfd_make_readable (abfd); |
||
2019 | return abfd; |
||
2020 | } |
||
2021 | |||
2022 | /* .text |
||
2023 | .global _function |
||
2024 | .global ___imp_function |
||
2025 | .global __imp__function |
||
2026 | _function: |
||
2027 | jmp *__imp__function: |
||
2028 | |||
2029 | .section idata$7 |
||
2030 | .long __head_my_dll |
||
2031 | |||
2032 | .section .idata$5 |
||
2033 | ___imp_function: |
||
2034 | __imp__function: |
||
2035 | iat? |
||
2036 | .section .idata$4 |
||
2037 | iat? |
||
2038 | .section .idata$6 |
||
2039 | ID |
||
2040 | .short |
||
2041 | .asciz "function" xlate? (add underscore, kill at) */ |
||
2042 | |||
2043 | static const unsigned char jmp_ix86_bytes[] = |
||
2044 | { |
||
2045 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 |
||
2046 | }; |
||
2047 | |||
2048 | /* _function: |
||
2049 | mov.l ip+8,r0 |
||
2050 | mov.l @r0,r0 |
||
2051 | jmp @r0 |
||
2052 | nop |
||
2053 | .dw __imp_function */ |
||
2054 | |||
2055 | static const unsigned char jmp_sh_bytes[] = |
||
2056 | { |
||
2057 | 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 |
||
2058 | }; |
||
2059 | |||
2060 | /* _function: |
||
2061 | lui $t0, |
||
2062 | lw $t0, |
||
2063 | jr $t0 |
||
2064 | nop */ |
||
2065 | |||
2066 | static const unsigned char jmp_mips_bytes[] = |
||
2067 | { |
||
2068 | 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d, |
||
2069 | 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 |
||
2070 | }; |
||
2071 | |||
2072 | static const unsigned char jmp_arm_bytes[] = |
||
2073 | { |
||
2074 | 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */ |
||
2075 | 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */ |
||
2076 | 0, 0, 0, 0 |
||
2077 | }; |
||
2078 | |||
2079 | |||
2080 | static bfd * |
||
2081 | make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub) |
||
2082 | { |
||
2083 | asection *tx, *id7, *id5, *id4, *id6; |
||
2084 | unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL; |
||
2085 | int len; |
||
2086 | char *oname; |
||
2087 | bfd *abfd; |
||
2088 | const unsigned char *jmp_bytes = NULL; |
||
2089 | int jmp_byte_count = 0; |
||
2090 | |||
2091 | /* Include the jump stub section only if it is needed. A jump |
||
2092 | stub is needed if the symbol being imported |
||
2093 | symbol and there is at least one undefined reference to that |
||
2094 | symbol. In other words, if all the import references to |
||
2095 | explicitly through _declspec(dllimport) then the jump stub is not |
||
2096 | needed. */ |
||
2097 | if (include_jmp_stub) |
||
2098 | { |
||
2099 | switch (pe_details->pe_arch) |
||
2100 | { |
||
2101 | case PE_ARCH_i386: |
||
2102 | jmp_bytes = jmp_ix86_bytes; |
||
2103 | jmp_byte_count = sizeof (jmp_ix86_bytes); |
||
2104 | break; |
||
2105 | case PE_ARCH_sh: |
||
2106 | jmp_bytes = jmp_sh_bytes; |
||
2107 | jmp_byte_count = sizeof (jmp_sh_bytes); |
||
2108 | break; |
||
2109 | case PE_ARCH_mips: |
||
2110 | jmp_bytes = jmp_mips_bytes; |
||
2111 | jmp_byte_count = sizeof (jmp_mips_bytes); |
||
2112 | break; |
||
2113 | case PE_ARCH_arm: |
||
2114 | case PE_ARCH_arm_epoc: |
||
2115 | case PE_ARCH_arm_wince: |
||
2116 | jmp_bytes = jmp_arm_bytes; |
||
2117 | jmp_byte_count = sizeof (jmp_arm_bytes); |
||
2118 | break; |
||
2119 | default: |
||
2120 | abort (); |
||
2121 | } |
||
2122 | } |
||
2123 | |||
2124 | oname = xmalloc (20); |
||
2125 | sprintf (oname, "d%06d.o", tmp_seq); |
||
2126 | tmp_seq++; |
||
2127 | |||
2128 | abfd = bfd_create (oname, parent); |
||
2129 | bfd_find_target (pe_details->object_target, abfd); |
||
2130 | bfd_make_writable (abfd); |
||
2131 | |||
2132 | bfd_set_format (abfd, bfd_object); |
||
2133 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
2134 | |||
2135 | symptr = 0; |
||
2136 | symtab = xmalloc (12 * sizeof (asymbol *)); |
||
2137 | |||
2138 | tx = quick_section (abfd, ".text", SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY, 2); |
||
2139 | id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); |
||
2140 | id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); |
||
2141 | id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); |
||
2142 | id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2); |
||
2143 | |||
2144 | if (*exp->internal_name == '@') |
||
2145 | { |
||
2146 | quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, |
||
2147 | BSF_GLOBAL, 0); |
||
2148 | if (include_jmp_stub) |
||
2149 | quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0); |
||
2150 | quick_symbol (abfd, "__imp_", exp->internal_name, "", id5, |
||
2151 | BSF_GLOBAL, 0); |
||
2152 | /* Fastcall applies only to functions, |
||
2153 | so no need for auto-import symbol. */ |
||
2154 | } |
||
2155 | else |
||
2156 | { |
||
2157 | quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, |
||
2158 | BSF_GLOBAL, 0); |
||
2159 | if (include_jmp_stub) |
||
2160 | quick_symbol (abfd, U (""), exp->internal_name, "", tx, |
||
2161 | BSF_GLOBAL, 0); |
||
2162 | quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5, |
||
2163 | BSF_GLOBAL, 0); |
||
2164 | /* Symbol to reference ord/name of imported |
||
2165 | data symbol, used to implement auto-import. */ |
||
2166 | if (exp->flag_data) |
||
2167 | quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6, |
||
2168 | BSF_GLOBAL,0); |
||
2169 | } |
||
2170 | if (pe_dll_compat_implib) |
||
2171 | quick_symbol (abfd, "___imp_", exp->internal_name, "", id5, |
||
2172 | BSF_GLOBAL, 0); |
||
2173 | |||
2174 | if (include_jmp_stub) |
||
2175 | { |
||
2176 | bfd_set_section_size (abfd, tx, jmp_byte_count); |
||
2177 | td = xmalloc (jmp_byte_count); |
||
2178 | tx->contents = td; |
||
2179 | memcpy (td, jmp_bytes, jmp_byte_count); |
||
2180 | |||
2181 | switch (pe_details->pe_arch) |
||
2182 | { |
||
2183 | case PE_ARCH_i386: |
||
2184 | #ifdef pe_use_x86_64 |
||
2185 | quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2); |
||
2186 | #else |
||
2187 | /* Mark this object as SAFESEH compatible. */ |
||
2188 | quick_symbol (abfd, "", "@feat.00", "", bfd_abs_section_ptr, |
||
2189 | BSF_LOCAL, 1); |
||
2190 | quick_reloc (abfd, 2, BFD_RELOC_32, 2); |
||
2191 | #endif |
||
2192 | break; |
||
2193 | case PE_ARCH_sh: |
||
2194 | quick_reloc (abfd, 8, BFD_RELOC_32, 2); |
||
2195 | break; |
||
2196 | case PE_ARCH_mips: |
||
2197 | quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2); |
||
2198 | quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */ |
||
2199 | quick_reloc (abfd, 4, BFD_RELOC_LO16, 2); |
||
2200 | break; |
||
2201 | case PE_ARCH_arm: |
||
2202 | case PE_ARCH_arm_epoc: |
||
2203 | case PE_ARCH_arm_wince: |
||
2204 | quick_reloc (abfd, 8, BFD_RELOC_32, 2); |
||
2205 | break; |
||
2206 | default: |
||
2207 | abort (); |
||
2208 | } |
||
2209 | save_relocs (tx); |
||
2210 | } |
||
2211 | else |
||
2212 | bfd_set_section_size (abfd, tx, 0); |
||
2213 | |||
2214 | bfd_set_section_size (abfd, id7, 4); |
||
2215 | d7 = xmalloc (4); |
||
2216 | id7->contents = d7; |
||
2217 | memset (d7, 0, 4); |
||
2218 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 5); |
||
2219 | save_relocs (id7); |
||
2220 | |||
2221 | bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE); |
||
2222 | d5 = xmalloc (PE_IDATA5_SIZE); |
||
2223 | id5->contents = d5; |
||
2224 | memset (d5, 0, PE_IDATA5_SIZE); |
||
2225 | |||
2226 | if (exp->flag_noname) |
||
2227 | { |
||
2228 | d5[0] = exp->ordinal; |
||
2229 | d5[1] = exp->ordinal >> 8; |
||
2230 | d5[PE_IDATA5_SIZE - 1] = 0x80; |
||
2231 | } |
||
2232 | else |
||
2233 | { |
||
2234 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); |
||
2235 | save_relocs (id5); |
||
2236 | } |
||
2237 | |||
2238 | bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE); |
||
2239 | d4 = xmalloc (PE_IDATA4_SIZE); |
||
2240 | id4->contents = d4; |
||
2241 | memset (d4, 0, PE_IDATA4_SIZE); |
||
2242 | |||
2243 | if (exp->flag_noname) |
||
2244 | { |
||
2245 | d4[0] = exp->ordinal; |
||
2246 | d4[1] = exp->ordinal >> 8; |
||
2247 | d4[PE_IDATA4_SIZE - 1] = 0x80; |
||
2248 | } |
||
2249 | else |
||
2250 | { |
||
2251 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); |
||
2252 | save_relocs (id4); |
||
2253 | } |
||
2254 | |||
2255 | if (exp->flag_noname) |
||
2256 | { |
||
2257 | len = 0; |
||
2258 | bfd_set_section_size (abfd, id6, 0); |
||
2259 | } |
||
2260 | else |
||
2261 | { |
||
2262 | /* { short, asciz } */ |
||
2263 | if (exp->its_name) |
||
2264 | len = 2 + strlen (exp->its_name) + 1; |
||
2265 | else |
||
2266 | len = 2 + strlen (exp->name) + 1; |
||
2267 | if (len & 1) |
||
2268 | len++; |
||
2269 | bfd_set_section_size (abfd, id6, len); |
||
2270 | d6 = xmalloc (len); |
||
2271 | id6->contents = d6; |
||
2272 | memset (d6, 0, len); |
||
2273 | d6[0] = exp->hint & 0xff; |
||
2274 | d6[1] = exp->hint >> 8; |
||
2275 | if (exp->its_name) |
||
2276 | strcpy ((char*) d6 + 2, exp->its_name); |
||
2277 | else |
||
2278 | strcpy ((char *) d6 + 2, exp->name); |
||
2279 | } |
||
2280 | |||
2281 | bfd_set_symtab (abfd, symtab, symptr); |
||
2282 | |||
2283 | if (include_jmp_stub) |
||
2284 | bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count); |
||
2285 | bfd_set_section_contents (abfd, id7, d7, 0, 4); |
||
2286 | bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE); |
||
2287 | bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE); |
||
2288 | if (!exp->flag_noname) |
||
2289 | bfd_set_section_contents (abfd, id6, d6, 0, len); |
||
2290 | |||
2291 | bfd_make_readable (abfd); |
||
2292 | return abfd; |
||
2293 | } |
||
2294 | |||
2295 | static bfd * |
||
2296 | make_singleton_name_imp (const char *import, bfd *parent) |
||
2297 | { |
||
2298 | /* Name thunks go to idata$4. */ |
||
2299 | asection *id5; |
||
2300 | unsigned char *d5; |
||
2301 | char *oname; |
||
2302 | bfd *abfd; |
||
2303 | |||
2304 | oname = xmalloc (20); |
||
2305 | sprintf (oname, "nmimp%06d.o", tmp_seq2); |
||
2306 | tmp_seq2++; |
||
2307 | |||
2308 | abfd = bfd_create (oname, parent); |
||
2309 | bfd_find_target (pe_details->object_target, abfd); |
||
2310 | bfd_make_writable (abfd); |
||
2311 | |||
2312 | bfd_set_format (abfd, bfd_object); |
||
2313 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
2314 | |||
2315 | symptr = 0; |
||
2316 | symtab = xmalloc (3 * sizeof (asymbol *)); |
||
2317 | id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); |
||
2318 | quick_symbol (abfd, "__imp_", import, "", id5, BSF_GLOBAL, 0); |
||
2319 | |||
2320 | /* We need space for the real thunk and for the null terminator. */ |
||
2321 | bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE * 2); |
||
2322 | d5 = xmalloc (PE_IDATA5_SIZE * 2); |
||
2323 | id5->contents = d5; |
||
2324 | memset (d5, 0, PE_IDATA5_SIZE * 2); |
||
2325 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); |
||
2326 | save_relocs (id5); |
||
2327 | |||
2328 | bfd_set_symtab (abfd, symtab, symptr); |
||
2329 | |||
2330 | bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA4_SIZE * 2); |
||
2331 | |||
2332 | bfd_make_readable (abfd); |
||
2333 | return abfd; |
||
2334 | } |
||
2335 | |||
2336 | static bfd * |
||
2337 | make_singleton_name_thunk (const char *import, bfd *parent) |
||
2338 | { |
||
2339 | /* Name thunks go to idata$4. */ |
||
2340 | asection *id4; |
||
2341 | unsigned char *d4; |
||
2342 | char *oname; |
||
2343 | bfd *abfd; |
||
2344 | |||
2345 | oname = xmalloc (20); |
||
2346 | sprintf (oname, "nmth%06d.o", tmp_seq); |
||
2347 | tmp_seq++; |
||
2348 | |||
2349 | abfd = bfd_create (oname, parent); |
||
2350 | bfd_find_target (pe_details->object_target, abfd); |
||
2351 | bfd_make_writable (abfd); |
||
2352 | |||
2353 | bfd_set_format (abfd, bfd_object); |
||
2354 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
2355 | |||
2356 | symptr = 0; |
||
2357 | symtab = xmalloc (3 * sizeof (asymbol *)); |
||
2358 | id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); |
||
2359 | quick_symbol (abfd, "__nm_thnk_", import, "", id4, BSF_GLOBAL, 0); |
||
2360 | quick_symbol (abfd, "__nm_", import, "", UNDSEC, BSF_GLOBAL, 0); |
||
2361 | |||
2362 | /* We need space for the real thunk and for the null terminator. */ |
||
2363 | bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE * 2); |
||
2364 | d4 = xmalloc (PE_IDATA4_SIZE * 2); |
||
2365 | id4->contents = d4; |
||
2366 | memset (d4, 0, PE_IDATA4_SIZE * 2); |
||
2367 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); |
||
2368 | save_relocs (id4); |
||
2369 | |||
2370 | bfd_set_symtab (abfd, symtab, symptr); |
||
2371 | |||
2372 | bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE * 2); |
||
2373 | |||
2374 | bfd_make_readable (abfd); |
||
2375 | return abfd; |
||
2376 | } |
||
2377 | |||
2378 | static char * |
||
2379 | make_import_fixup_mark (arelent *rel) |
||
2380 | { |
||
2381 | /* We convert reloc to symbol, for later reference. */ |
||
2382 | static int counter; |
||
2383 | static char *fixup_name = NULL; |
||
2384 | static size_t buffer_len = 0; |
||
2385 | |||
2386 | struct bfd_symbol *sym = *rel->sym_ptr_ptr; |
||
2387 | |||
2388 | bfd *abfd = bfd_asymbol_bfd (sym); |
||
2389 | struct bfd_link_hash_entry *bh; |
||
2390 | |||
2391 | if (!fixup_name) |
||
2392 | { |
||
2393 | fixup_name = xmalloc (384); |
||
2394 | buffer_len = 384; |
||
2395 | } |
||
2396 | |||
2397 | if (strlen (sym->name) + 25 > buffer_len) |
||
2398 | /* Assume 25 chars for "__fu" + counter + "_". If counter is |
||
2399 | bigger than 20 digits long, we've got worse problems than |
||
2400 | overflowing this buffer... */ |
||
2401 | { |
||
2402 | free (fixup_name); |
||
2403 | /* New buffer size is length of symbol, plus 25, but |
||
2404 | then rounded up to the nearest multiple of 128. */ |
||
2405 | buffer_len = ((strlen (sym->name) + 25) + 127) & ~127; |
||
2406 | fixup_name = xmalloc (buffer_len); |
||
2407 | } |
||
2408 | |||
2409 | sprintf (fixup_name, "__fu%d_%s", counter++, sym->name); |
||
2410 | |||
2411 | bh = NULL; |
||
2412 | bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL, |
||
2413 | current_sec, /* sym->section, */ |
||
2414 | rel->address, NULL, TRUE, FALSE, &bh); |
||
2415 | |||
2416 | return fixup_name; |
||
2417 | } |
||
2418 | |||
2419 | /* .section .idata$2 |
||
2420 | .rva __nm_thnk_SYM (singleton thunk with name of func) |
||
2421 | .long 0 |
||
2422 | .long 0 |
||
2423 | .rva __my_dll_iname (name of dll) |
||
2424 | .rva __fuNN_SYM (pointer to reference (address) in text) */ |
||
2425 | |||
2426 | static bfd * |
||
2427 | make_import_fixup_entry (const char *name, |
||
2428 | const char *fixup_name, |
||
2429 | const char *symname, |
||
2430 | bfd *parent) |
||
2431 | { |
||
2432 | asection *id2; |
||
2433 | unsigned char *d2; |
||
2434 | char *oname; |
||
2435 | bfd *abfd; |
||
2436 | |||
2437 | oname = xmalloc (20); |
||
2438 | sprintf (oname, "fu%06d.o", tmp_seq); |
||
2439 | tmp_seq++; |
||
2440 | |||
2441 | abfd = bfd_create (oname, parent); |
||
2442 | bfd_find_target (pe_details->object_target, abfd); |
||
2443 | bfd_make_writable (abfd); |
||
2444 | |||
2445 | bfd_set_format (abfd, bfd_object); |
||
2446 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
2447 | |||
2448 | symptr = 0; |
||
2449 | symtab = xmalloc (6 * sizeof (asymbol *)); |
||
2450 | id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2); |
||
2451 | |||
2452 | quick_symbol (abfd, "__nm_thnk_", name, "", UNDSEC, BSF_GLOBAL, 0); |
||
2453 | quick_symbol (abfd, U (""), symname, "_iname", UNDSEC, BSF_GLOBAL, 0); |
||
2454 | /* For relocator v2 we have to use the .idata$5 element and not |
||
2455 | fixup_name. */ |
||
2456 | if (link_info.pei386_runtime_pseudo_reloc == 2) |
||
2457 | quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0); |
||
2458 | else |
||
2459 | quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0); |
||
2460 | |||
2461 | bfd_set_section_size (abfd, id2, 20); |
||
2462 | d2 = xmalloc (20); |
||
2463 | id2->contents = d2; |
||
2464 | memset (d2, 0, 20); |
||
2465 | |||
2466 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 1); |
||
2467 | quick_reloc (abfd, 12, BFD_RELOC_RVA, 2); |
||
2468 | quick_reloc (abfd, 16, BFD_RELOC_RVA, 3); |
||
2469 | save_relocs (id2); |
||
2470 | |||
2471 | bfd_set_symtab (abfd, symtab, symptr); |
||
2472 | |||
2473 | bfd_set_section_contents (abfd, id2, d2, 0, 20); |
||
2474 | |||
2475 | bfd_make_readable (abfd); |
||
2476 | return abfd; |
||
2477 | } |
||
2478 | |||
2479 | /* .section .rdata_runtime_pseudo_reloc |
||
2480 | .long addend |
||
2481 | .rva __fuNN_SYM (pointer to reference (address) in text) */ |
||
2482 | |||
2483 | static bfd * |
||
2484 | make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED, |
||
2485 | const char *fixup_name, |
||
2486 | bfd_vma addend ATTRIBUTE_UNUSED, |
||
2487 | bfd_vma bitsize, |
||
2488 | bfd *parent) |
||
2489 | { |
||
2490 | asection *rt_rel; |
||
2491 | unsigned char *rt_rel_d; |
||
2492 | char *oname; |
||
2493 | bfd *abfd; |
||
2494 | oname = xmalloc (20); |
||
2495 | sprintf (oname, "rtr%06d.o", tmp_seq); |
||
2496 | tmp_seq++; |
||
2497 | |||
2498 | abfd = bfd_create (oname, parent); |
||
2499 | bfd_find_target (pe_details->object_target, abfd); |
||
2500 | bfd_make_writable (abfd); |
||
2501 | |||
2502 | bfd_set_format (abfd, bfd_object); |
||
2503 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
2504 | |||
2505 | symptr = 0; |
||
2506 | if (link_info.pei386_runtime_pseudo_reloc == 2) |
||
2507 | { |
||
2508 | symtab = xmalloc ((runtime_pseudp_reloc_v2_init ? 3 : 6) * sizeof (asymbol *)); |
||
2509 | } |
||
2510 | else |
||
2511 | { |
||
2512 | symtab = xmalloc (2 * sizeof (asymbol *)); |
||
2513 | } |
||
2514 | rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc", |
||
2515 | SEC_HAS_CONTENTS, 2); |
||
2516 | |||
2517 | quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0); |
||
2518 | |||
2519 | if (link_info.pei386_runtime_pseudo_reloc == 2) |
||
2520 | { |
||
2521 | size_t size = 12; |
||
2522 | if (! runtime_pseudp_reloc_v2_init) |
||
2523 | { |
||
2524 | size += 12; |
||
2525 | runtime_pseudp_reloc_v2_init = 1; |
||
2526 | } |
||
2527 | quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0); |
||
2528 | |||
2529 | bfd_set_section_size (abfd, rt_rel, size); |
||
2530 | rt_rel_d = xmalloc (size); |
||
2531 | rt_rel->contents = rt_rel_d; |
||
2532 | memset (rt_rel_d, 0, size); |
||
2533 | quick_reloc (abfd, size - 8, BFD_RELOC_RVA, 1); |
||
2534 | quick_reloc (abfd, size - 12, BFD_RELOC_RVA, 2); |
||
2535 | bfd_put_32 (abfd, bitsize, rt_rel_d + (size - 4)); |
||
2536 | if (size != 12) |
||
2537 | bfd_put_32 (abfd, 1, rt_rel_d + 8); |
||
2538 | save_relocs (rt_rel); |
||
2539 | |||
2540 | bfd_set_symtab (abfd, symtab, symptr); |
||
2541 | |||
2542 | bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, size); |
||
2543 | } |
||
2544 | else |
||
2545 | { |
||
2546 | bfd_set_section_size (abfd, rt_rel, 8); |
||
2547 | rt_rel_d = xmalloc (8); |
||
2548 | rt_rel->contents = rt_rel_d; |
||
2549 | memset (rt_rel_d, 0, 8); |
||
2550 | |||
2551 | bfd_put_32 (abfd, addend, rt_rel_d); |
||
2552 | quick_reloc (abfd, 4, BFD_RELOC_RVA, 1); |
||
2553 | |||
2554 | save_relocs (rt_rel); |
||
2555 | |||
2556 | bfd_set_symtab (abfd, symtab, symptr); |
||
2557 | |||
2558 | bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8); |
||
2559 | } |
||
2560 | bfd_make_readable (abfd); |
||
2561 | return abfd; |
||
2562 | } |
||
2563 | |||
2564 | /* .section .rdata |
||
2565 | .rva __pei386_runtime_relocator */ |
||
2566 | |||
2567 | static bfd * |
||
2568 | pe_create_runtime_relocator_reference (bfd *parent) |
||
2569 | { |
||
2570 | asection *extern_rt_rel; |
||
2571 | unsigned char *extern_rt_rel_d; |
||
2572 | char *oname; |
||
2573 | bfd *abfd; |
||
2574 | |||
2575 | oname = xmalloc (20); |
||
2576 | sprintf (oname, "ertr%06d.o", tmp_seq); |
||
2577 | tmp_seq++; |
||
2578 | |||
2579 | abfd = bfd_create (oname, parent); |
||
2580 | bfd_find_target (pe_details->object_target, abfd); |
||
2581 | bfd_make_writable (abfd); |
||
2582 | |||
2583 | bfd_set_format (abfd, bfd_object); |
||
2584 | bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); |
||
2585 | |||
2586 | symptr = 0; |
||
2587 | symtab = xmalloc (2 * sizeof (asymbol *)); |
||
2588 | extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2); |
||
2589 | |||
2590 | quick_symbol (abfd, "", U ("_pei386_runtime_relocator"), "", UNDSEC, |
||
2591 | BSF_NO_FLAGS, 0); |
||
2592 | |||
2593 | bfd_set_section_size (abfd, extern_rt_rel, PE_IDATA5_SIZE); |
||
2594 | extern_rt_rel_d = xmalloc (PE_IDATA5_SIZE); |
||
2595 | extern_rt_rel->contents = extern_rt_rel_d; |
||
2596 | |||
2597 | quick_reloc (abfd, 0, BFD_RELOC_RVA, 1); |
||
2598 | save_relocs (extern_rt_rel); |
||
2599 | |||
2600 | bfd_set_symtab (abfd, symtab, symptr); |
||
2601 | |||
2602 | bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, PE_IDATA5_SIZE); |
||
2603 | |||
2604 | bfd_make_readable (abfd); |
||
2605 | return abfd; |
||
2606 | } |
||
2607 | |||
2608 | void |
||
2609 | pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend) |
||
2610 | { |
||
2611 | char buf[300]; |
||
2612 | struct bfd_symbol *sym = *rel->sym_ptr_ptr; |
||
2613 | struct bfd_link_hash_entry *name_thunk_sym; |
||
2614 | struct bfd_link_hash_entry *name_imp_sym; |
||
2615 | const char *name = sym->name; |
||
2616 | char *fixup_name = make_import_fixup_mark (rel); |
||
2617 | bfd *b; |
||
2618 | int need_import_table = 1; |
||
2619 | |||
2620 | sprintf (buf, "__imp_%s", name); |
||
2621 | name_imp_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); |
||
2622 | |||
2623 | sprintf (buf, "__nm_thnk_%s", name); |
||
2624 | |||
2625 | name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); |
||
2626 | |||
2627 | /* For version 2 pseudo relocation we don't need to add an import |
||
2628 | if the import symbol is already present. */ |
||
2629 | if (link_info.pei386_runtime_pseudo_reloc == 2 |
||
2630 | && name_imp_sym |
||
2631 | && name_imp_sym->type == bfd_link_hash_defined) |
||
2632 | need_import_table = 0; |
||
2633 | |||
2634 | if (need_import_table == 1 |
||
2635 | && (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined)) |
||
2636 | { |
||
2637 | b = make_singleton_name_thunk (name, link_info.output_bfd); |
||
2638 | add_bfd_to_link (b, b->filename, &link_info); |
||
2639 | |||
2640 | /* If we ever use autoimport, we have to cast text section writable. |
||
2641 | But not for version 2. */ |
||
2642 | if (link_info.pei386_runtime_pseudo_reloc != 2) |
||
2643 | { |
||
2644 | config.text_read_only = FALSE; |
||
2645 | link_info.output_bfd->flags &= ~WP_TEXT; |
||
2646 | } |
||
2647 | if (link_info.pei386_runtime_pseudo_reloc == 2) |
||
2648 | { |
||
2649 | b = make_singleton_name_imp (name, link_info.output_bfd); |
||
2650 | add_bfd_to_link (b, b->filename, &link_info); |
||
2651 | } |
||
2652 | } |
||
2653 | |||
2654 | if ((addend == 0 || link_info.pei386_runtime_pseudo_reloc) |
||
2655 | && need_import_table == 1) |
||
2656 | { |
||
2657 | extern char * pe_data_import_dll; |
||
2658 | char * symname = pe_data_import_dll ? pe_data_import_dll : "unknown"; |
||
2659 | |||
2660 | b = make_import_fixup_entry (name, fixup_name, symname, |
||
2661 | link_info.output_bfd); |
||
2662 | add_bfd_to_link (b, b->filename, &link_info); |
||
2663 | } |
||
2664 | |||
2665 | if ((link_info.pei386_runtime_pseudo_reloc != 0 && addend != 0) |
||
2666 | || link_info.pei386_runtime_pseudo_reloc == 2) |
||
2667 | { |
||
2668 | if (pe_dll_extra_pe_debug) |
||
2669 | printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n", |
||
2670 | fixup_name, (int) addend); |
||
2671 | |||
2672 | b = make_runtime_pseudo_reloc (name, fixup_name, addend, rel->howto->bitsize, |
||
2673 | link_info.output_bfd); |
||
2674 | add_bfd_to_link (b, b->filename, &link_info); |
||
2675 | |||
2676 | if (runtime_pseudo_relocs_created == 0) |
||
2677 | { |
||
2678 | b = pe_create_runtime_relocator_reference (link_info.output_bfd); |
||
2679 | add_bfd_to_link (b, b->filename, &link_info); |
||
2680 | } |
||
2681 | runtime_pseudo_relocs_created++; |
||
2682 | } |
||
2683 | else if (addend != 0) |
||
2684 | { |
||
2685 | einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"), |
||
2686 | s->owner, s, rel->address, sym->name); |
||
2687 | einfo ("%X"); |
||
2688 | } |
||
2689 | } |
||
2690 | |||
2691 | |||
2692 | void |
||
2693 | pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_info *info) |
||
2694 | { |
||
2695 | int i; |
||
2696 | bfd *ar_head; |
||
2697 | bfd *ar_tail; |
||
2698 | bfd *outarch; |
||
2699 | bfd *ibfd; |
||
2700 | bfd *head = 0; |
||
2701 | |||
2702 | dll_filename = (def->name) ? def->name : dll_name; |
||
2703 | dll_symname = xstrdup (dll_filename); |
||
2704 | for (i = 0; dll_symname[i]; i++) |
||
2705 | if (!ISALNUM (dll_symname[i])) |
||
2706 | dll_symname[i] = '_'; |
||
2707 | |||
2708 | unlink_if_ordinary (impfilename); |
||
2709 | |||
2710 | outarch = bfd_openw (impfilename, 0); |
||
2711 | |||
2712 | if (!outarch) |
||
2713 | { |
||
2714 | /* xgettext:c-format */ |
||
2715 | einfo (_("%XCan't open .lib file: %s\n"), impfilename); |
||
2716 | return; |
||
2717 | } |
||
2718 | |||
2719 | if (verbose) |
||
2720 | /* xgettext:c-format */ |
||
2721 | info_msg (_("Creating library file: %s\n"), impfilename); |
||
2722 | |||
2723 | bfd_set_format (outarch, bfd_archive); |
||
2724 | outarch->has_armap = 1; |
||
2725 | |||
2726 | /* Work out a reasonable size of things to put onto one line. */ |
||
2727 | ar_head = make_head (outarch); |
||
2728 | |||
2729 | /* Iterate the input BFDs, looking for exclude-modules-for-implib. */ |
||
2730 | for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next) |
||
2731 | { |
||
2732 | /* Iterate the exclude list. */ |
||
2733 | struct exclude_list_struct *ex; |
||
2734 | char found; |
||
2735 | for (ex = excludes, found = 0; ex && !found; ex = ex->next) |
||
2736 | { |
||
2737 | if (ex->type != EXCLUDEFORIMPLIB) |
||
2738 | continue; |
||
2739 | found = (filename_cmp (ex->string, ibfd->filename) == 0); |
||
2740 | } |
||
2741 | /* If it matched, we must open a fresh BFD for it (the original |
||
2742 | input BFD is still needed for the DLL's final link) and add |
||
2743 | it into the archive member chain. */ |
||
2744 | if (found) |
||
2745 | { |
||
2746 | bfd *newbfd = bfd_openr (ibfd->my_archive |
||
2747 | ? ibfd->my_archive->filename : ibfd->filename, NULL); |
||
2748 | if (!newbfd) |
||
2749 | { |
||
2750 | einfo (_("%Xbfd_openr %s: %E\n"), ibfd->filename); |
||
2751 | return; |
||
2752 | } |
||
2753 | if (ibfd->my_archive) |
||
2754 | { |
||
2755 | /* Must now iterate through archive until we find the |
||
2756 | required member. A minor shame that we'll open the |
||
2757 | archive once per member that we require from it, and |
||
2758 | leak those archive bfds rather than reuse them. */ |
||
2759 | bfd *arbfd = newbfd; |
||
2760 | if (!bfd_check_format_matches (arbfd, bfd_archive, NULL)) |
||
2761 | { |
||
2762 | einfo (_("%X%s(%s): can't find member in non-archive file"), |
||
2763 | ibfd->my_archive->filename, ibfd->filename); |
||
2764 | return; |
||
2765 | } |
||
2766 | newbfd = NULL; |
||
2767 | while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0) |
||
2768 | { |
||
2769 | if (filename_cmp (newbfd->filename, ibfd->filename) == 0) |
||
2770 | break; |
||
2771 | } |
||
2772 | if (!newbfd) |
||
2773 | { |
||
2774 | einfo (_("%X%s(%s): can't find member in archive"), |
||
2775 | ibfd->my_archive->filename, ibfd->filename); |
||
2776 | return; |
||
2777 | } |
||
2778 | } |
||
2779 | newbfd->archive_next = head; |
||
2780 | head = newbfd; |
||
2781 | } |
||
2782 | } |
||
2783 | |||
2784 | for (i = 0; i < def->num_exports; i++) |
||
2785 | { |
||
2786 | /* The import library doesn't know about the internal name. */ |
||
2787 | char *internal = def->exports[i].internal_name; |
||
2788 | bfd *n; |
||
2789 | |||
2790 | /* Don't add PRIVATE entries to import lib. */ |
||
2791 | if (pe_def_file->exports[i].flag_private) |
||
2792 | continue; |
||
2793 | def->exports[i].internal_name = def->exports[i].name; |
||
2794 | n = make_one (def->exports + i, outarch, |
||
2795 | ! (def->exports + i)->flag_data); |
||
2796 | n->archive_next = head; |
||
2797 | head = n; |
||
2798 | def->exports[i].internal_name = internal; |
||
2799 | } |
||
2800 | |||
2801 | ar_tail = make_tail (outarch); |
||
2802 | |||
2803 | if (ar_head == NULL || ar_tail == NULL) |
||
2804 | return; |
||
2805 | |||
2806 | /* Now stick them all into the archive. */ |
||
2807 | ar_head->archive_next = head; |
||
2808 | ar_tail->archive_next = ar_head; |
||
2809 | head = ar_tail; |
||
2810 | |||
2811 | if (! bfd_set_archive_head (outarch, head)) |
||
2812 | einfo ("%Xbfd_set_archive_head: %E\n"); |
||
2813 | |||
2814 | if (! bfd_close (outarch)) |
||
2815 | einfo ("%Xbfd_close %s: %E\n", impfilename); |
||
2816 | |||
2817 | while (head != NULL) |
||
2818 | { |
||
2819 | bfd *n = head->archive_next; |
||
2820 | bfd_close (head); |
||
2821 | head = n; |
||
2822 | } |
||
2823 | } |
||
2824 | |||
2825 | static int undef_count = 0; |
||
2826 | |||
2827 | struct key_value |
||
2828 | { |
||
2829 | char *key; |
||
2830 | const char *oname; |
||
2831 | }; |
||
2832 | |||
2833 | static struct key_value *udef_table; |
||
2834 | |||
2835 | static int undef_sort_cmp (const void *l1, const void *r1) |
||
2836 | { |
||
2837 | const struct key_value *l = l1; |
||
2838 | const struct key_value *r = r1; |
||
2839 | |||
2840 | return strcmp (l->key, r->key); |
||
2841 | } |
||
2842 | |||
2843 | static struct bfd_link_hash_entry * |
||
2844 | pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name) |
||
2845 | { |
||
2846 | struct bfd_link_hash_entry *h = NULL; |
||
2847 | struct key_value *kv; |
||
2848 | struct key_value key; |
||
2849 | char *at, *lname = (char *) alloca (strlen (name) + 3); |
||
2850 | |||
2851 | strcpy (lname, name); |
||
2852 | |||
2853 | at = strchr (lname + (lname[0] == '@'), '@'); |
||
2854 | if (at) |
||
2855 | at[1] = 0; |
||
2856 | |||
2857 | key.key = lname; |
||
2858 | kv = bsearch (&key, udef_table, undef_count, sizeof (struct key_value), |
||
2859 | undef_sort_cmp); |
||
2860 | |||
2861 | if (kv) |
||
2862 | { |
||
2863 | h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); |
||
2864 | if (h->type == bfd_link_hash_undefined) |
||
2865 | return h; |
||
2866 | } |
||
2867 | if (lname[0] == '?') |
||
2868 | return NULL; |
||
2869 | if (at || lname[0] == '@') |
||
2870 | { |
||
2871 | if (lname[0] == '@') |
||
2872 | { |
||
2873 | if (pe_details->underscored) |
||
2874 | lname[0] = '_'; |
||
2875 | else |
||
2876 | strcpy (lname, lname + 1); |
||
2877 | key.key = lname; |
||
2878 | kv = bsearch (&key, udef_table, undef_count, |
||
2879 | sizeof (struct key_value), undef_sort_cmp); |
||
2880 | if (kv) |
||
2881 | { |
||
2882 | h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); |
||
2883 | if (h->type == bfd_link_hash_undefined) |
||
2884 | return h; |
||
2885 | } |
||
2886 | } |
||
2887 | if (at) |
||
2888 | *strchr (lname, '@') = 0; |
||
2889 | key.key = lname; |
||
2890 | kv = bsearch (&key, udef_table, undef_count, |
||
2891 | sizeof (struct key_value), undef_sort_cmp); |
||
2892 | if (kv) |
||
2893 | { |
||
2894 | h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); |
||
2895 | if (h->type == bfd_link_hash_undefined) |
||
2896 | return h; |
||
2897 | } |
||
2898 | return NULL; |
||
2899 | } |
||
2900 | |||
2901 | strcat (lname, "@"); |
||
2902 | key.key = lname; |
||
2903 | kv = bsearch (&key, udef_table, undef_count, |
||
2904 | sizeof (struct key_value), undef_sort_cmp); |
||
2905 | |||
2906 | if (kv) |
||
2907 | { |
||
2908 | h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); |
||
2909 | if (h->type == bfd_link_hash_undefined) |
||
2910 | return h; |
||
2911 | } |
||
2912 | |||
2913 | if (lname[0] == '_' && pe_details->underscored) |
||
2914 | lname[0] = '@'; |
||
2915 | else |
||
2916 | { |
||
2917 | memmove (lname + 1, lname, strlen (lname) + 1); |
||
2918 | lname[0] = '@'; |
||
2919 | } |
||
2920 | key.key = lname; |
||
2921 | |||
2922 | kv = bsearch (&key, udef_table, undef_count, |
||
2923 | sizeof (struct key_value), undef_sort_cmp); |
||
2924 | |||
2925 | if (kv) |
||
2926 | { |
||
2927 | h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); |
||
2928 | if (h->type == bfd_link_hash_undefined) |
||
2929 | return h; |
||
2930 | } |
||
2931 | |||
2932 | return NULL; |
||
2933 | } |
||
2934 | |||
2935 | static bfd_boolean |
||
2936 | pe_undef_count (struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED, |
||
2937 | void *inf ATTRIBUTE_UNUSED) |
||
2938 | { |
||
2939 | if (h->type == bfd_link_hash_undefined) |
||
2940 | undef_count++; |
||
2941 | return TRUE; |
||
2942 | } |
||
2943 | |||
2944 | static bfd_boolean |
||
2945 | pe_undef_fill (struct bfd_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) |
||
2946 | { |
||
2947 | if (h->type == bfd_link_hash_undefined) |
||
2948 | { |
||
2949 | char *at; |
||
2950 | |||
2951 | udef_table[undef_count].key = xstrdup (h->root.string); |
||
2952 | at = strchr (udef_table[undef_count].key |
||
2953 | + (udef_table[undef_count].key[0] == '@'), '@'); |
||
2954 | if (at) |
||
2955 | at[1] = 0; |
||
2956 | udef_table[undef_count].oname = h->root.string; |
||
2957 | undef_count++; |
||
2958 | } |
||
2959 | return TRUE; |
||
2960 | } |
||
2961 | |||
2962 | static void |
||
2963 | pe_create_undef_table (void) |
||
2964 | { |
||
2965 | undef_count = 0; |
||
2966 | |||
2967 | /* count undefined symbols */ |
||
2968 | |||
2969 | bfd_link_hash_traverse (link_info.hash, pe_undef_count, ""); |
||
2970 | |||
2971 | /* create and fill the corresponding table */ |
||
2972 | udef_table = xmalloc (undef_count * sizeof (struct key_value)); |
||
2973 | |||
2974 | undef_count = 0; |
||
2975 | bfd_link_hash_traverse (link_info.hash, pe_undef_fill, ""); |
||
2976 | |||
2977 | /* sort items */ |
||
2978 | qsort (udef_table, undef_count, sizeof (struct key_value), undef_sort_cmp); |
||
2979 | } |
||
2980 | |||
2981 | static void |
||
2982 | add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *linfo) |
||
2983 | { |
||
2984 | lang_input_statement_type *fake_file; |
||
2985 | |||
2986 | fake_file = lang_add_input_file (name, |
||
2987 | lang_input_file_is_fake_enum, |
||
2988 | NULL); |
||
2989 | fake_file->the_bfd = abfd; |
||
2990 | ldlang_add_file (fake_file); |
||
2991 | |||
2992 | if (!bfd_link_add_symbols (abfd, linfo)) |
||
2993 | einfo ("%Xaddsym %s: %E\n", name); |
||
2994 | } |
||
2995 | |||
2996 | void |
||
2997 | pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo) |
||
2998 | { |
||
2999 | int i, j; |
||
3000 | def_file_module *module; |
||
3001 | def_file_import *imp; |
||
3002 | |||
3003 | pe_dll_id_target (bfd_get_target (output_bfd)); |
||
3004 | |||
3005 | if (!pe_def_file) |
||
3006 | return; |
||
3007 | |||
3008 | imp = pe_def_file->imports; |
||
3009 | |||
3010 | pe_create_undef_table (); |
||
3011 | |||
3012 | for (module = pe_def_file->modules; module; module = module->next) |
||
3013 | { |
||
3014 | int do_this_dll = 0; |
||
3015 | |||
3016 | for (i = 0; i < pe_def_file->num_imports && imp[i].module != module; i++) |
||
3017 | ; |
||
3018 | if (i >= pe_def_file->num_imports) |
||
3019 | continue; |
||
3020 | |||
3021 | dll_filename = module->name; |
||
3022 | dll_symname = xstrdup (module->name); |
||
3023 | for (j = 0; dll_symname[j]; j++) |
||
3024 | if (!ISALNUM (dll_symname[j])) |
||
3025 | dll_symname[j] = '_'; |
||
3026 | |||
3027 | for (; i < pe_def_file->num_imports && imp[i].module == module; i++) |
||
3028 | { |
||
3029 | def_file_export exp; |
||
3030 | struct bfd_link_hash_entry *blhe; |
||
3031 | int lead_at = (*imp[i].internal_name == '@'); |
||
3032 | /* See if we need this import. */ |
||
3033 | size_t len = strlen (imp[i].internal_name); |
||
3034 | char *name = xmalloc (len + 2 + 6); |
||
3035 | bfd_boolean include_jmp_stub = FALSE; |
||
3036 | bfd_boolean is_cdecl = FALSE; |
||
3037 | bfd_boolean is_undef = FALSE; |
||
3038 | |||
3039 | if (!lead_at && strchr (imp[i].internal_name, '@') == NULL) |
||
3040 | is_cdecl = TRUE; |
||
3041 | |||
3042 | if (lead_at) |
||
3043 | sprintf (name, "%s", imp[i].internal_name); |
||
3044 | else |
||
3045 | sprintf (name, "%s%s",U (""), imp[i].internal_name); |
||
3046 | |||
3047 | blhe = bfd_link_hash_lookup (linfo->hash, name, |
||
3048 | FALSE, FALSE, FALSE); |
||
3049 | |||
3050 | /* Include the jump stub for |
||
3051 | is undefined. */ |
||
3052 | if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)) |
||
3053 | { |
||
3054 | if (lead_at) |
||
3055 | sprintf (name, "%s%s", "__imp_", imp[i].internal_name); |
||
3056 | else |
||
3057 | sprintf (name, "%s%s%s", "__imp_", U (""), |
||
3058 | imp[i].internal_name); |
||
3059 | |||
3060 | blhe = bfd_link_hash_lookup (linfo->hash, name, |
||
3061 | FALSE, FALSE, FALSE); |
||
3062 | if (blhe) |
||
3063 | is_undef = (blhe->type == bfd_link_hash_undefined); |
||
3064 | } |
||
3065 | else |
||
3066 | { |
||
3067 | include_jmp_stub = TRUE; |
||
3068 | is_undef = (blhe->type == bfd_link_hash_undefined); |
||
3069 | } |
||
3070 | |||
3071 | if (is_cdecl && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))) |
||
3072 | { |
||
3073 | sprintf (name, "%s%s",U (""), imp[i].internal_name); |
||
3074 | blhe = pe_find_cdecl_alias_match (linfo, name); |
||
3075 | include_jmp_stub = TRUE; |
||
3076 | if (blhe) |
||
3077 | is_undef = (blhe->type == bfd_link_hash_undefined); |
||
3078 | } |
||
3079 | |||
3080 | free (name); |
||
3081 | |||
3082 | if (is_undef) |
||
3083 | { |
||
3084 | bfd *one; |
||
3085 | /* We do. */ |
||
3086 | if (!do_this_dll) |
||
3087 | { |
||
3088 | bfd *ar_head = make_head (output_bfd); |
||
3089 | add_bfd_to_link (ar_head, ar_head->filename, linfo); |
||
3090 | do_this_dll = 1; |
||
3091 | } |
||
3092 | exp.internal_name = imp[i].internal_name; |
||
3093 | exp.name = imp[i].name; |
||
3094 | exp.its_name = imp[i].its_name; |
||
3095 | exp.ordinal = imp[i].ordinal; |
||
3096 | exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0; |
||
3097 | exp.flag_private = 0; |
||
3098 | exp.flag_constant = 0; |
||
3099 | exp.flag_data = imp[i].data; |
||
3100 | exp.flag_noname = exp.name ? 0 : 1; |
||
3101 | one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub); |
||
3102 | add_bfd_to_link (one, one->filename, linfo); |
||
3103 | } |
||
3104 | } |
||
3105 | if (do_this_dll) |
||
3106 | { |
||
3107 | bfd *ar_tail = make_tail (output_bfd); |
||
3108 | add_bfd_to_link (ar_tail, ar_tail->filename, linfo); |
||
3109 | } |
||
3110 | |||
3111 | free (dll_symname); |
||
3112 | } |
||
3113 | |||
3114 | while (undef_count) |
||
3115 | { |
||
3116 | --undef_count; |
||
3117 | free (udef_table[undef_count].key); |
||
3118 | } |
||
3119 | free (udef_table); |
||
3120 | } |
||
3121 | |||
3122 | /* We were handed a *.DLL file. Parse it and turn it into a set of |
||
3123 | IMPORTS directives in the def file. Return TRUE if the file was |
||
3124 | handled, FALSE if not. */ |
||
3125 | |||
3126 | static unsigned int |
||
3127 | pe_get16 (bfd *abfd, int where) |
||
3128 | { |
||
3129 | unsigned char b[2]; |
||
3130 | |||
3131 | bfd_seek (abfd, (file_ptr) where, SEEK_SET); |
||
3132 | bfd_bread (b, (bfd_size_type) 2, abfd); |
||
3133 | return b[0] + (b[1] << 8); |
||
3134 | } |
||
3135 | |||
3136 | static unsigned int |
||
3137 | pe_get32 (bfd *abfd, int where) |
||
3138 | { |
||
3139 | unsigned char b[4]; |
||
3140 | |||
3141 | bfd_seek (abfd, (file_ptr) where, SEEK_SET); |
||
3142 | bfd_bread (b, (bfd_size_type) 4, abfd); |
||
3143 | return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); |
||
3144 | } |
||
3145 | |||
3146 | static unsigned int |
||
3147 | pe_as32 (void *ptr) |
||
3148 | { |
||
3149 | unsigned char *b = ptr; |
||
3150 | |||
3151 | return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); |
||
3152 | } |
||
3153 | |||
3154 | bfd_boolean |
||
3155 | pe_implied_import_dll (const char *filename) |
||
3156 | { |
||
3157 | bfd *dll; |
||
3158 | bfd_vma pe_header_offset, opthdr_ofs, num_entries, i; |
||
3159 | bfd_vma export_rva, export_size, nsections, secptr, expptr; |
||
3160 | bfd_vma exp_funcbase; |
||
3161 | unsigned char *expdata; |
||
3162 | char *erva; |
||
3163 | bfd_vma name_rvas, nexp; |
||
3164 | const char *dllname; |
||
3165 | /* Initialization with start > end guarantees that is_data |
||
3166 | will not be set by mistake, and avoids compiler warning. */ |
||
3167 | bfd_vma data_start = 1; |
||
3168 | bfd_vma data_end = 0; |
||
3169 | bfd_vma rdata_start = 1; |
||
3170 | bfd_vma rdata_end = 0; |
||
3171 | bfd_vma bss_start = 1; |
||
3172 | bfd_vma bss_end = 0; |
||
3173 | |||
3174 | /* No, I can't use bfd here. kernel32.dll puts its export table in |
||
3175 | the middle of the .rdata section. */ |
||
3176 | dll = bfd_openr (filename, pe_details->target_name); |
||
3177 | if (!dll) |
||
3178 | { |
||
3179 | einfo ("%Xopen %s: %E\n", filename); |
||
3180 | return FALSE; |
||
3181 | } |
||
3182 | |||
3183 | /* PEI dlls seem to be bfd_objects. */ |
||
3184 | if (!bfd_check_format (dll, bfd_object)) |
||
3185 | { |
||
3186 | einfo ("%X%s: this doesn't appear to be a DLL\n", filename); |
||
3187 | return FALSE; |
||
3188 | } |
||
3189 | |||
3190 | /* Get pe_header, optional header and numbers of directory entries. */ |
||
3191 | pe_header_offset = pe_get32 (dll, 0x3c); |
||
3192 | opthdr_ofs = pe_header_offset + 4 + 20; |
||
3193 | #ifdef pe_use_x86_64 |
||
3194 | num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /* & NumberOfRvaAndSizes. */ |
||
3195 | #else |
||
3196 | num_entries = pe_get32 (dll, opthdr_ofs + 92); |
||
3197 | #endif |
||
3198 | |||
3199 | /* No import or export directory entry. */ |
||
3200 | if (num_entries < 1) |
||
3201 | return FALSE; |
||
3202 | |||
3203 | #ifdef pe_use_x86_64 |
||
3204 | export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4); |
||
3205 | export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4); |
||
3206 | #else |
||
3207 | export_rva = pe_get32 (dll, opthdr_ofs + 96); |
||
3208 | export_size = pe_get32 (dll, opthdr_ofs + 100); |
||
3209 | #endif |
||
3210 | |||
3211 | /* No export table - nothing to export. */ |
||
3212 | if (export_size == 0) |
||
3213 | return FALSE; |
||
3214 | |||
3215 | nsections = pe_get16 (dll, pe_header_offset + 4 + 2); |
||
3216 | secptr = (pe_header_offset + 4 + 20 + |
||
3217 | pe_get16 (dll, pe_header_offset + 4 + 16)); |
||
3218 | expptr = 0; |
||
3219 | |||
3220 | /* Get the rva and size of the export section. */ |
||
3221 | for (i = 0; i < nsections; i++) |
||
3222 | { |
||
3223 | char sname[8]; |
||
3224 | bfd_vma secptr1 = secptr + 40 * i; |
||
3225 | bfd_vma vaddr = pe_get32 (dll, secptr1 + 12); |
||
3226 | bfd_vma vsize = pe_get32 (dll, secptr1 + 16); |
||
3227 | bfd_vma fptr = pe_get32 (dll, secptr1 + 20); |
||
3228 | |||
3229 | bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); |
||
3230 | bfd_bread (sname, (bfd_size_type) 8, dll); |
||
3231 | |||
3232 | if (vaddr <= export_rva && vaddr + vsize > export_rva) |
||
3233 | { |
||
3234 | expptr = fptr + (export_rva - vaddr); |
||
3235 | if (export_rva + export_size > vaddr + vsize) |
||
3236 | export_size = vsize - (export_rva - vaddr); |
||
3237 | break; |
||
3238 | } |
||
3239 | } |
||
3240 | |||
3241 | /* Scan sections and store the base and size of the |
||
3242 | data and bss segments in data/base_start/end. */ |
||
3243 | for (i = 0; i < nsections; i++) |
||
3244 | { |
||
3245 | bfd_vma secptr1 = secptr + 40 * i; |
||
3246 | bfd_vma vsize = pe_get32 (dll, secptr1 + 8); |
||
3247 | bfd_vma vaddr = pe_get32 (dll, secptr1 + 12); |
||
3248 | bfd_vma flags = pe_get32 (dll, secptr1 + 36); |
||
3249 | char sec_name[9]; |
||
3250 | |||
3251 | sec_name[8] = '\0'; |
||
3252 | bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); |
||
3253 | bfd_bread (sec_name, (bfd_size_type) 8, dll); |
||
3254 | |||
3255 | if (strcmp(sec_name,".data") == 0) |
||
3256 | { |
||
3257 | data_start = vaddr; |
||
3258 | data_end = vaddr + vsize; |
||
3259 | |||
3260 | if (pe_dll_extra_pe_debug) |
||
3261 | printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", |
||
3262 | __FUNCTION__, sec_name, (unsigned long) vaddr, |
||
3263 | (unsigned long) (vaddr + vsize), (unsigned long) flags); |
||
3264 | } |
||
3265 | else if (strcmp(sec_name,".rdata") == 0) |
||
3266 | { |
||
3267 | rdata_start = vaddr; |
||
3268 | rdata_end = vaddr + vsize; |
||
3269 | |||
3270 | if (pe_dll_extra_pe_debug) |
||
3271 | printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", |
||
3272 | __FUNCTION__, sec_name, (unsigned long) vaddr, |
||
3273 | (unsigned long) (vaddr + vsize), (unsigned long) flags); |
||
3274 | } |
||
3275 | else if (strcmp (sec_name,".bss") == 0) |
||
3276 | { |
||
3277 | bss_start = vaddr; |
||
3278 | bss_end = vaddr + vsize; |
||
3279 | |||
3280 | if (pe_dll_extra_pe_debug) |
||
3281 | printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", |
||
3282 | __FUNCTION__, sec_name, (unsigned long) vaddr, |
||
3283 | (unsigned long) (vaddr + vsize), (unsigned long) flags); |
||
3284 | } |
||
3285 | } |
||
3286 | |||
3287 | expdata = xmalloc (export_size); |
||
3288 | bfd_seek (dll, (file_ptr) expptr, SEEK_SET); |
||
3289 | bfd_bread (expdata, (bfd_size_type) export_size, dll); |
||
3290 | erva = (char *) expdata - export_rva; |
||
3291 | |||
3292 | if (pe_def_file == 0) |
||
3293 | pe_def_file = def_file_empty (); |
||
3294 | |||
3295 | nexp = pe_as32 (expdata + 24); |
||
3296 | name_rvas = pe_as32 (expdata + 32); |
||
3297 | exp_funcbase = pe_as32 (expdata + 28); |
||
3298 | |||
3299 | /* Use internal dll name instead of filename |
||
3300 | to enable symbolic dll linking. */ |
||
3301 | dllname = erva + pe_as32 (expdata + 12); |
||
3302 | |||
3303 | /* Check to see if the dll has already been added to |
||
3304 | the definition list and if so return without error. |
||
3305 | This avoids multiple symbol definitions. */ |
||
3306 | if (def_get_module (pe_def_file, dllname)) |
||
3307 | { |
||
3308 | if (pe_dll_extra_pe_debug) |
||
3309 | printf ("%s is already loaded\n", dllname); |
||
3310 | return TRUE; |
||
3311 | } |
||
3312 | |||
3313 | /* Iterate through the list of symbols. */ |
||
3314 | for (i = 0; i < nexp; i++) |
||
3315 | { |
||
3316 | /* Pointer to the names vector. */ |
||
3317 | bfd_vma name_rva = pe_as32 (erva + name_rvas + i * 4); |
||
3318 | def_file_import *imp; |
||
3319 | /* Pointer to the function address vector. */ |
||
3320 | bfd_vma func_rva = pe_as32 (erva + exp_funcbase + i * 4); |
||
3321 | int is_data = 0; |
||
3322 | |||
3323 | /* Skip unwanted symbols, which are |
||
3324 | exported in buggy auto-import releases. */ |
||
3325 | if (! CONST_STRNEQ (erva + name_rva, "__nm_")) |
||
3326 | { |
||
3327 | int is_dup = 0; |
||
3328 | /* is_data is true if the address is in the data, rdata or bss |
||
3329 | segment. */ |
||
3330 | is_data = |
||
3331 | (func_rva >= data_start && func_rva < data_end) |
||
3332 | || (func_rva >= rdata_start && func_rva < rdata_end) |
||
3333 | || (func_rva >= bss_start && func_rva < bss_end); |
||
3334 | |||
3335 | imp = def_file_add_import (pe_def_file, erva + name_rva, |
||
3336 | dllname, i, NULL, NULL, &is_dup); |
||
3337 | /* Mark symbol type. */ |
||
3338 | if (!is_dup) |
||
3339 | imp->data = is_data; |
||
3340 | |||
3341 | if (pe_dll_extra_pe_debug) |
||
3342 | printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n", |
||
3343 | __FUNCTION__, dllname, erva + name_rva, |
||
3344 | (unsigned long) func_rva, is_data ? "(data)" : ""); |
||
3345 | } |
||
3346 | } |
||
3347 | |||
3348 | return TRUE; |
||
3349 | } |
||
3350 | |||
3351 | void |
||
3352 | pe_output_file_set_long_section_names (bfd *abfd) |
||
3353 | { |
||
3354 | if (pe_use_coff_long_section_names < 0) |
||
3355 | return; |
||
3356 | if (!bfd_coff_set_long_section_names (abfd, pe_use_coff_long_section_names)) |
||
3357 | einfo (_("%XError: can't use long section names on this arch\n")); |
||
3358 | } |
||
3359 | |||
3360 | /* These are the main functions, called from the emulation. The first |
||
3361 | is called after the bfds are read, so we can guess at how much space |
||
3362 | we need. The second is called after everything is placed, so we |
||
3363 | can put the right values in place. */ |
||
3364 | |||
3365 | void |
||
3366 | pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info) |
||
3367 | { |
||
3368 | pe_dll_id_target (bfd_get_target (abfd)); |
||
3369 | pe_output_file_set_long_section_names (abfd); |
||
3370 | process_def_file_and_drectve (abfd, info); |
||
3371 | |||
3372 | if (pe_def_file->num_exports == 0 && !info->shared) |
||
3373 | return; |
||
3374 | |||
3375 | generate_edata (abfd, info); |
||
3376 | build_filler_bfd (1); |
||
3377 | pe_output_file_set_long_section_names (filler_bfd); |
||
3378 | } |
||
3379 | |||
3380 | void |
||
3381 | pe_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) |
||
3382 | { |
||
3383 | pe_dll_id_target (bfd_get_target (abfd)); |
||
3384 | pe_output_file_set_long_section_names (abfd); |
||
3385 | build_filler_bfd (0); |
||
3386 | pe_output_file_set_long_section_names (filler_bfd); |
||
3387 | } |
||
3388 | |||
3389 | void |
||
3390 | pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info) |
||
3391 | { |
||
3392 | pe_dll_id_target (bfd_get_target (abfd)); |
||
3393 | pe_output_file_set_long_section_names (abfd); |
||
3394 | image_base = pe_data (abfd)->pe_opthdr.ImageBase; |
||
3395 | |||
3396 | generate_reloc (abfd, info); |
||
3397 | if (reloc_sz > 0) |
||
3398 | { |
||
3399 | bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); |
||
3400 | |||
3401 | /* Resize the sections. */ |
||
3402 | lang_reset_memory_regions (); |
||
3403 | lang_size_sections (NULL, TRUE); |
||
3404 | |||
3405 | /* Redo special stuff. */ |
||
3406 | ldemul_after_allocation (); |
||
3407 | |||
3408 | /* Do the assignments again. */ |
||
3409 | lang_do_assignments (lang_final_phase_enum); |
||
3410 | } |
||
3411 | |||
3412 | fill_edata (abfd, info); |
||
3413 | |||
3414 | if (info->shared && !info->pie) |
||
3415 | pe_data (abfd)->dll = 1; |
||
3416 | |||
3417 | edata_s->contents = edata_d; |
||
3418 | reloc_s->contents = reloc_d; |
||
3419 | } |
||
3420 | |||
3421 | void |
||
3422 | pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info) |
||
3423 | { |
||
3424 | pe_dll_id_target (bfd_get_target (abfd)); |
||
3425 | pe_output_file_set_long_section_names (abfd); |
||
3426 | image_base = pe_data (abfd)->pe_opthdr.ImageBase; |
||
3427 | |||
3428 | generate_reloc (abfd, info); |
||
3429 | if (reloc_sz > 0) |
||
3430 | { |
||
3431 | bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); |
||
3432 | |||
3433 | /* Resize the sections. */ |
||
3434 | lang_reset_memory_regions (); |
||
3435 | lang_size_sections (NULL, TRUE); |
||
3436 | |||
3437 | /* Redo special stuff. */ |
||
3438 | ldemul_after_allocation (); |
||
3439 | |||
3440 | /* Do the assignments again. */ |
||
3441 | lang_do_assignments (lang_final_phase_enum); |
||
3442 | } |
||
3443 | reloc_s->contents = reloc_d; |
||
3444 | } |
||
3445 | |||
3446 | bfd_boolean |
||
3447 | pe_bfd_is_dll (bfd *abfd) |
||
3448 | { |
||
3449 | return (bfd_get_format (abfd) == bfd_object |
||
3450 | && obj_pe (abfd) |
||
3451 | && pe_data (abfd)->dll); |
||
3452 | }>>>>>>=>>>><>><>><>><>><>><>><>>>>>>>>>><>>>>>>>>>>>>>>>>>>> |