1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include "sysdep.h"
24: #include "bfd.h"
25: #include "bfdlink.h"
26: #include "libiberty.h"
27: #include "safe-ctype.h"
28:
29: #include <time.h>
30:
31: #include "ld.h"
32: #include "ldexp.h"
33: #include "ldlang.h"
34: #include "ldwrite.h"
35: #include "ldmisc.h"
36: #include <ldgram.h>
37: #include "ldmain.h"
38: #include "ldfile.h"
39: #include "ldemul.h"
40: #include "coff/internal.h"
41: #include "../bfd/libcoff.h"
42: #include "deffile.h"
43: #include "pe-dll.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:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147: static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *);
148:
149:
150:
151: def_file * pe_def_file = 0;
152: int pe_dll_export_everything = 0;
153: int pe_dll_do_default_excludes = 1;
154: int pe_dll_kill_ats = 0;
155: int pe_dll_stdcall_aliases = 0;
156: int pe_dll_warn_dup_exports = 0;
157: int pe_dll_compat_implib = 0;
158: int pe_dll_extra_pe_debug = 0;
159:
160:
161:
162: static bfd_vma image_base;
163: static bfd *filler_bfd;
164: static struct bfd_section *edata_s, *reloc_s;
165: static unsigned char *edata_d, *reloc_d;
166: static size_t edata_sz, reloc_sz;
167: static int runtime_pseudo_relocs_created = 0;
168:
169: typedef struct
170: {
171: const char *name;
172: int len;
173: }
174: autofilter_entry_type;
175:
176: typedef struct
177: {
178: const char *target_name;
179: const char *object_target;
180: unsigned int imagebase_reloc;
181: int pe_arch;
182: int bfd_arch;
183: bfd_boolean underscored;
184: const autofilter_entry_type* autofilter_symbollist;
185: }
186: pe_details_type;
187:
188: static const autofilter_entry_type autofilter_symbollist_generic[] =
189: {
190: { STRING_COMMA_LEN (".text") },
191:
192: { STRING_COMMA_LEN ("DllMain") },
193: { STRING_COMMA_LEN ("DllMainCRTStartup") },
194: { STRING_COMMA_LEN ("_DllMainCRTStartup") },
195:
196: { STRING_COMMA_LEN ("_pei386_runtime_relocator") },
197: { STRING_COMMA_LEN ("do_pseudo_reloc") },
198: { STRING_COMMA_LEN (NULL) }
199: };
200:
201: static const autofilter_entry_type autofilter_symbollist_i386[] =
202: {
203: { STRING_COMMA_LEN (".text") },
204:
205: { STRING_COMMA_LEN ("cygwin_crt0") },
206: #ifdef pe_use_x86_64
207: { STRING_COMMA_LEN ("DllMain") },
208: { STRING_COMMA_LEN ("DllEntryPoint") },
209: { STRING_COMMA_LEN ("DllMainCRTStartup") },
210: { STRING_COMMA_LEN ("_cygwin_dll_entry") },
211: { STRING_COMMA_LEN ("_cygwin_crt0_common") },
212: { STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry") },
213: #else
214: { STRING_COMMA_LEN ("DllMain@12") },
215: { STRING_COMMA_LEN ("DllEntryPoint@0") },
216: { STRING_COMMA_LEN ("DllMainCRTStartup@12") },
217: { STRING_COMMA_LEN ("_cygwin_dll_entry@12") },
218: { STRING_COMMA_LEN ("_cygwin_crt0_common@8") },
219: { STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry@12") },
220: { STRING_COMMA_LEN ("cygwin_attach_dll") },
221: #endif
222: { STRING_COMMA_LEN ("cygwin_premain0") },
223: { STRING_COMMA_LEN ("cygwin_premain1") },
224: { STRING_COMMA_LEN ("cygwin_premain2") },
225: { STRING_COMMA_LEN ("cygwin_premain3") },
226:
227: { STRING_COMMA_LEN ("_pei386_runtime_relocator") },
228: { STRING_COMMA_LEN ("do_pseudo_reloc") },
229:
230: { STRING_COMMA_LEN ("impure_ptr") },
231: { STRING_COMMA_LEN ("_impure_ptr") },
232: { STRING_COMMA_LEN ("_fmode") },
233: { STRING_COMMA_LEN ("environ") },
234: { STRING_COMMA_LEN (NULL) }
235: };
236:
237: #define PE_ARCH_i386 1
238: #define PE_ARCH_sh 2
239: #define PE_ARCH_mips 3
240: #define PE_ARCH_arm 4
241: #define PE_ARCH_arm_epoc 5
242: #define PE_ARCH_arm_wince 6
243:
244: static const pe_details_type pe_detail_list[] =
245: {
246: {
247: #ifdef pe_use_x86_64
248: "pei-x86-64",
249: "pe-x86-64",
250: 3 ,
251: #else
252: "pei-i386",
253: "pe-i386",
254: 7 ,
255: #endif
256: PE_ARCH_i386,
257: bfd_arch_i386,
258: TRUE,
259: autofilter_symbollist_i386
260: },
261: {
262: "pei-shl",
263: "pe-shl",
264: 16 ,
265: PE_ARCH_sh,
266: bfd_arch_sh,
267: TRUE,
268: autofilter_symbollist_generic
269: },
270: {
271: "pei-mips",
272: "pe-mips",
273: 34 ,
274: PE_ARCH_mips,
275: bfd_arch_mips,
276: FALSE,
277: autofilter_symbollist_generic
278: },
279: {
280: "pei-arm-little",
281: "pe-arm-little",
282: 11 ,
283: PE_ARCH_arm,
284: bfd_arch_arm,
285: TRUE,
286: autofilter_symbollist_generic
287: },
288: {
289: "epoc-pei-arm-little",
290: "epoc-pe-arm-little",
291: 11 ,
292: PE_ARCH_arm_epoc,
293: bfd_arch_arm,
294: FALSE,
295: autofilter_symbollist_generic
296: },
297: {
298: "pei-arm-wince-little",
299: "pe-arm-wince-little",
300: 2,
301: PE_ARCH_arm_wince,
302: bfd_arch_arm,
303: FALSE,
304: autofilter_symbollist_generic
305: },
306: { NULL, NULL, 0, 0, 0, FALSE, NULL }
307: };
308:
309: static const pe_details_type *pe_details;
310:
311:
312: static const autofilter_entry_type autofilter_liblist[] =
313: {
314: { STRING_COMMA_LEN ("libcegcc") },
315: { STRING_COMMA_LEN ("libcygwin") },
316: { STRING_COMMA_LEN ("libgcc") },
317: { STRING_COMMA_LEN ("libstdc++") },
318: { STRING_COMMA_LEN ("libmingw32") },
319: { STRING_COMMA_LEN ("libmingwex") },
320: { STRING_COMMA_LEN ("libg2c") },
321: { STRING_COMMA_LEN ("libsupc++") },
322: { STRING_COMMA_LEN ("libobjc") },
323: { STRING_COMMA_LEN ("libgcj") },
324: { STRING_COMMA_LEN (NULL) }
325: };
326:
327: static const autofilter_entry_type autofilter_objlist[] =
328: {
329: { STRING_COMMA_LEN ("crt0.o") },
330: { STRING_COMMA_LEN ("crt1.o") },
331: { STRING_COMMA_LEN ("crt2.o") },
332: { STRING_COMMA_LEN ("dllcrt1.o") },
333: { STRING_COMMA_LEN ("dllcrt2.o") },
334: { STRING_COMMA_LEN ("gcrt0.o") },
335: { STRING_COMMA_LEN ("gcrt1.o") },
336: { STRING_COMMA_LEN ("gcrt2.o") },
337: { STRING_COMMA_LEN ("crtbegin.o") },
338: { STRING_COMMA_LEN ("crtend.o") },
339: { STRING_COMMA_LEN (NULL) }
340: };
341:
342: static const autofilter_entry_type autofilter_symbolprefixlist[] =
343: {
344:
345:
346:
347: { STRING_COMMA_LEN ("__rtti_") },
348: { STRING_COMMA_LEN ("__builtin_") },
349:
350: { STRING_COMMA_LEN ("_nm_") },
351:
352: { STRING_COMMA_LEN ("_head_") },
353: { STRING_COMMA_LEN (NULL) }
354: };
355:
356: static const autofilter_entry_type autofilter_symbolsuffixlist[] =
357: {
358: { STRING_COMMA_LEN ("_iname") },
359: { STRING_COMMA_LEN (NULL) }
360: };
361:
362: #define U(str) (pe_details->underscored ? "_" str : str)
363:
364: void
365: pe_dll_id_target (const char *target)
366: {
367: int i;
368:
369: for (i = 0; pe_detail_list[i].target_name; i++)
370: if (strcmp (pe_detail_list[i].target_name, target) == 0
371: || strcmp (pe_detail_list[i].object_target, target) == 0)
372: {
373: pe_details = pe_detail_list + i;
374: return;
375: }
376: einfo (_("%XUnsupported PEI architecture: %s\n"), target);
377: exit (1);
378: }
379:
380:
381:
382:
383: typedef struct
384: {
385: bfd_vma vma;
386: char type;
387: short extra;
388: }
389: reloc_data_type;
390:
391: static int
392: reloc_sort (const void *va, const void *vb)
393: {
394: bfd_vma a = ((const reloc_data_type *) va)->vma;
395: bfd_vma b = ((const reloc_data_type *) vb)->vma;
396:
397: return (a > b) ? 1 : ((a < b) ? -1 : 0);
398: }
399:
400: static int
401: pe_export_sort (const void *va, const void *vb)
402: {
403: const def_file_export *a = va;
404: const def_file_export *b = vb;
405:
406: return strcmp (a->name, b->name);
407: }
408:
409:
410:
411:
412:
413:
414:
415: static bfd_vma *exported_symbol_offsets;
416: static struct bfd_section **exported_symbol_sections;
417: static int export_table_size;
418: static int count_exported;
419: static int count_exported_byname;
420: static int count_with_ordinals;
421: static const char *dll_name;
422: static int min_ordinal, max_ordinal;
423: static int *exported_symbols;
424:
425: typedef struct exclude_list_struct
426: {
427: char *string;
428: struct exclude_list_struct *next;
429: int type;
430: }
431: exclude_list_struct;
432:
433: static struct exclude_list_struct *excludes = 0;
434:
435: void
436: pe_dll_add_excludes (const char *new_excludes, const int type)
437: {
438: char *local_copy;
439: char *exclude_string;
440:
441: local_copy = xstrdup (new_excludes);
442:
443: exclude_string = strtok (local_copy, ",:");
444: for (; exclude_string; exclude_string = strtok (NULL, ",:"))
445: {
446: struct exclude_list_struct *new_exclude;
447:
448: new_exclude = xmalloc (sizeof (struct exclude_list_struct));
449: new_exclude->string = xmalloc (strlen (exclude_string) + 1);
450: strcpy (new_exclude->string, exclude_string);
451: new_exclude->type = type;
452: new_exclude->next = excludes;
453: excludes = new_exclude;
454: }
455:
456: free (local_copy);
457: }
458:
459: static bfd_boolean
460: is_import (const char* n)
461: {
462: return (CONST_STRNEQ (n, "__imp_"));
463: }
464:
465:
466:
467:
468: static int
469: auto_export (bfd *abfd, def_file *d, const char *n)
470: {
471: int i;
472: struct exclude_list_struct *ex;
473: const autofilter_entry_type *afptr;
474: const char * libname = 0;
475: if (abfd && abfd->my_archive)
476: libname = lbasename (abfd->my_archive->filename);
477:
478: for (i = 0; i < d->num_exports; i++)
479: if (strcmp (d->exports[i].name, n) == 0)
480: return 0;
481:
482: if (pe_dll_do_default_excludes)
483: {
484: const char * p;
485: int len;
486:
487: if (pe_dll_extra_pe_debug)
488: printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n",
489: n, abfd, abfd->my_archive);
490:
491:
492:
493: if (libname)
494: {
495: afptr = autofilter_liblist;
496:
497: while (afptr->name)
498: {
499: if (strncmp (libname, afptr->name, afptr->len) == 0 )
500: return 0;
501: afptr++;
502: }
503: }
504:
505:
506:
507: if (abfd && (p = lbasename (abfd->filename)))
508: {
509: afptr = autofilter_objlist;
510: while (afptr->name)
511: {
512: if (strcmp (p, afptr->name) == 0)
513: return 0;
514: afptr++;
515: }
516: }
517:
518:
519:
520:
521:
522: afptr = pe_details->autofilter_symbollist;
523:
524: while (afptr->name)
525: {
526: if (strcmp (n, afptr->name) == 0)
527: return 0;
528:
529: afptr++;
530: }
531:
532:
533: afptr = autofilter_symbolprefixlist;
534: while (afptr->name)
535: {
536: if (strncmp (n, afptr->name, afptr->len) == 0)
537: return 0;
538:
539: afptr++;
540: }
541:
542:
543: len = strlen (n);
544: afptr = autofilter_symbolsuffixlist;
545: while (afptr->name)
546: {
547: if ((len >= afptr->len)
548:
549: && strncmp (n + len - afptr->len, afptr->name,
550: afptr->len + 1) == 0)
551: return 0;
552:
553: afptr++;
554: }
555: }
556:
557: for (ex = excludes; ex; ex = ex->next)
558: {
559: if (ex->type == 1)
560: {
561: if (libname
562: && ((strcmp (libname, ex->string) == 0)
563: || (strcasecmp ("ALL", ex->string) == 0)))
564: return 0;
565: }
566: else if (strcmp (n, ex->string) == 0)
567: return 0;
568: }
569:
570: return 1;
571: }
572:
573: static void
574: process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
575: {
576: int i, j;
577: struct bfd_link_hash_entry *blhe;
578: bfd *b;
579: struct bfd_section *s;
580: def_file_export *e = 0;
581:
582: if (!pe_def_file)
583: pe_def_file = def_file_empty ();
584:
585:
586:
587: for (b = info->input_bfds; b; b = b->link_next)
588: {
589: s = bfd_get_section_by_name (b, ".drectve");
590: if (s)
591: {
592: long size = s->size;
593: char *buf = xmalloc (size);
594:
595: bfd_get_section_contents (b, s, buf, 0, size);
596: def_file_add_directive (pe_def_file, buf, size);
597: free (buf);
598: }
599: }
600:
601:
602:
603: if (!pe_dll_export_everything && pe_def_file->num_exports == 0
604: && info->executable)
605: return;
606:
607:
608: if (pe_dll_export_everything || pe_def_file->num_exports == 0)
609: {
610: for (b = info->input_bfds; b; b = b->