00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "bfd.h"
00028 #include "sysdep.h"
00029 #include "bfdlink.h"
00030 #include "libiberty.h"
00031 #include "safe-ctype.h"
00032
00033 #include <time.h>
00034
00035 #include "ld.h"
00036 #include "ldexp.h"
00037 #include "ldlang.h"
00038 #include "ldwrite.h"
00039 #include "ldmisc.h"
00040 #include <ldgram.h>
00041 #include "ldmain.h"
00042 #include "ldfile.h"
00043 #include "ldemul.h"
00044 #include "coff/internal.h"
00045 #include "../bfd/libcoff.h"
00046 #include "deffile.h"
00047 #include "pe-dll.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *);
00129
00130
00131
00132 def_file * pe_def_file = 0;
00133 int pe_dll_export_everything = 0;
00134 int pe_dll_do_default_excludes = 1;
00135 int pe_dll_kill_ats = 0;
00136 int pe_dll_stdcall_aliases = 0;
00137 int pe_dll_warn_dup_exports = 0;
00138 int pe_dll_compat_implib = 0;
00139 int pe_dll_extra_pe_debug = 0;
00140
00141
00142
00143 static bfd_vma image_base;
00144 static bfd *filler_bfd;
00145 static struct bfd_section *edata_s, *reloc_s;
00146 static unsigned char *edata_d, *reloc_d;
00147 static size_t edata_sz, reloc_sz;
00148 static int runtime_pseudo_relocs_created = 0;
00149
00150 typedef struct
00151 {
00152 char *target_name;
00153 char *object_target;
00154 unsigned int imagebase_reloc;
00155 int pe_arch;
00156 int bfd_arch;
00157 int underscored;
00158 }
00159 pe_details_type;
00160
00161 typedef struct
00162 {
00163 char *name;
00164 int len;
00165 }
00166 autofilter_entry_type;
00167
00168 #define PE_ARCH_i386 1
00169 #define PE_ARCH_sh 2
00170 #define PE_ARCH_mips 3
00171 #define PE_ARCH_arm 4
00172 #define PE_ARCH_arm_epoc 5
00173
00174 static pe_details_type pe_detail_list[] =
00175 {
00176 {
00177 "pei-i386",
00178 "pe-i386",
00179 7 ,
00180 PE_ARCH_i386,
00181 bfd_arch_i386,
00182 1
00183 },
00184 {
00185 "pei-shl",
00186 "pe-shl",
00187 16 ,
00188 PE_ARCH_sh,
00189 bfd_arch_sh,
00190 1
00191 },
00192 {
00193 "pei-mips",
00194 "pe-mips",
00195 34 ,
00196 PE_ARCH_mips,
00197 bfd_arch_mips,
00198 0
00199 },
00200 {
00201 "pei-arm-little",
00202 "pe-arm-little",
00203 11 ,
00204 PE_ARCH_arm,
00205 bfd_arch_arm,
00206 1
00207 },
00208 {
00209 "epoc-pei-arm-little",
00210 "epoc-pe-arm-little",
00211 11 ,
00212 PE_ARCH_arm_epoc,
00213 bfd_arch_arm,
00214 0
00215 },
00216 { NULL, NULL, 0, 0, 0, 0 }
00217 };
00218
00219 static pe_details_type *pe_details;
00220
00221 static autofilter_entry_type autofilter_symbollist[] =
00222 {
00223 { "DllMain@12", 10 },
00224 { "DllEntryPoint@0", 15 },
00225 { "DllMainCRTStartup@12", 20 },
00226 { "_cygwin_dll_entry@12", 20 },
00227 { "_cygwin_crt0_common@8", 21 },
00228 { "_cygwin_noncygwin_dll_entry@12", 30 },
00229 { "impure_ptr", 10 },
00230 { "_pei386_runtime_relocator", 25 },
00231 { "do_pseudo_reloc", 15 },
00232 { "cygwin_crt0", 11 },
00233 { NULL, 0 }
00234 };
00235
00236
00237 static autofilter_entry_type autofilter_liblist[] =
00238 {
00239 { "libcygwin", 9 },
00240 { "libgcc", 6 },
00241 { "libstdc++", 9 },
00242 { "libmingw32", 10 },
00243 { "libmingwex", 10 },
00244 { "libg2c", 6 },
00245 { "libsupc++", 9 },
00246 { "libobjc", 7 },
00247 { "libgcj", 6 },
00248 { NULL, 0 }
00249 };
00250
00251 static autofilter_entry_type autofilter_objlist[] =
00252 {
00253 { "crt0.o", 6 },
00254 { "crt1.o", 6 },
00255 { "crt2.o", 6 },
00256 { "dllcrt1.o", 9 },
00257 { "dllcrt2.o", 9 },
00258 { "gcrt0.o", 7 },
00259 { "gcrt1.o", 7 },
00260 { "gcrt2.o", 7 },
00261 { "crtbegin.o", 10 },
00262 { "crtend.o", 8 },
00263 { NULL, 0 }
00264 };
00265
00266 static autofilter_entry_type autofilter_symbolprefixlist[] =
00267 {
00268
00269
00270 { "__rtti_", 7 },
00271
00272 { "_nm_", 4 },
00273 { "__builtin_", 10 },
00274
00275 { "_head_", 6 },
00276 { "_fmode", 6 },
00277 { "_impure_ptr", 11 },
00278 { "cygwin_attach_dll", 17 },
00279 { "cygwin_premain0", 15 },
00280 { "cygwin_premain1", 15 },
00281 { "cygwin_premain2", 15 },
00282 { "cygwin_premain3", 15 },
00283 { "environ", 7 },
00284 { NULL, 0 }
00285 };
00286
00287 static autofilter_entry_type autofilter_symbolsuffixlist[] =
00288 {
00289 { "_iname", 6 },
00290 { NULL, 0 }
00291 };
00292
00293 #define U(str) (pe_details->underscored ? "_" str : str)
00294
00295 void
00296 pe_dll_id_target (const char *target)
00297 {
00298 int i;
00299
00300 for (i = 0; pe_detail_list[i].target_name; i++)
00301 if (strcmp (pe_detail_list[i].target_name, target) == 0
00302 || strcmp (pe_detail_list[i].object_target, target) == 0)
00303 {
00304 pe_details = pe_detail_list + i;
00305 return;
00306 }
00307 einfo (_("%XUnsupported PEI architecture: %s\n"), target);
00308 exit (1);
00309 }
00310
00311
00312
00313
00314 typedef struct
00315 {
00316 bfd_vma vma;
00317 char type;
00318 short extra;
00319 }
00320 reloc_data_type;
00321
00322 static int
00323 reloc_sort (const void *va, const void *vb)
00324 {
00325 bfd_vma a = ((const reloc_data_type *) va)->vma;
00326 bfd_vma b = ((const reloc_data_type *) vb)->vma;
00327
00328 return (a > b) ? 1 : ((a < b) ? -1 : 0);
00329 }
00330
00331 static int
00332 pe_export_sort (const void *va, const void *vb)
00333 {
00334 const def_file_export *a = va;
00335 const def_file_export *b = vb;
00336
00337 return strcmp (a->name, b->name);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346 static bfd_vma *exported_symbol_offsets;
00347 static struct bfd_section **exported_symbol_sections;
00348 static int export_table_size;
00349 static int count_exported;
00350 static int count_exported_byname;
00351 static int count_with_ordinals;
00352 static const char *dll_name;
00353 static int min_ordinal, max_ordinal;
00354 static int *exported_symbols;
00355
00356 typedef struct exclude_list_struct
00357 {
00358 char *string;
00359 struct exclude_list_struct *next;
00360 int type;
00361 }
00362 exclude_list_struct;
00363
00364 static struct exclude_list_struct *excludes = 0;
00365
00366 void
00367 pe_dll_add_excludes (const char *new_excludes, const int type)
00368 {
00369 char *local_copy;
00370 char *exclude_string;
00371
00372 local_copy = xstrdup (new_excludes);
00373
00374 exclude_string = strtok (local_copy, ",:");
00375 for (; exclude_string; exclude_string = strtok (NULL, ",:"))
00376 {
00377 struct exclude_list_struct *new_exclude;
00378
00379 new_exclude = xmalloc (sizeof (struct exclude_list_struct));
00380 new_exclude->string = xmalloc (strlen (exclude_string) + 1);
00381 strcpy (new_exclude->string, exclude_string);
00382 new_exclude->type = type;
00383 new_exclude->next = excludes;
00384 excludes = new_exclude;
00385 }
00386
00387 free (local_copy);
00388 }
00389
00390
00391
00392
00393
00394 static int
00395 auto_export (bfd *abfd, def_file *d, const char *n)
00396 {
00397 int i;
00398 struct exclude_list_struct *ex;
00399 autofilter_entry_type *afptr;
00400 const char * libname = 0;
00401 if (abfd && abfd->my_archive)
00402 libname = lbasename (abfd->my_archive->filename);
00403
00404
00405 if (strncmp (n, "_imp_", 5) == 0)
00406 return 0;
00407
00408 for (i = 0; i < d->num_exports; i++)
00409 if (strcmp (d->exports[i].name, n) == 0)
00410 return 0;
00411
00412 if (pe_dll_do_default_excludes)
00413 {
00414 const char * p;
00415 int len;
00416
00417 if (pe_dll_extra_pe_debug)
00418 printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n",
00419 n, abfd, abfd->my_archive);
00420
00421
00422
00423 if (libname)
00424 {
00425 afptr = autofilter_liblist;
00426
00427 while (afptr->name)
00428 {
00429 if (strncmp (libname, afptr->name, afptr->len) == 0 )
00430 return 0;
00431 afptr++;
00432 }
00433 }
00434
00435
00436
00437 if (abfd && (p = lbasename (abfd->filename)))
00438 {
00439 afptr = autofilter_objlist;
00440 while (afptr->name)
00441 {
00442 if (strcmp (p, afptr->name) == 0)
00443 return 0;
00444 afptr++;
00445 }
00446 }
00447
00448
00449
00450
00451
00452
00453 afptr = autofilter_symbollist;
00454 while (afptr->name)
00455 {
00456 if (strcmp (n, afptr->name) == 0)
00457 return 0;
00458
00459 afptr++;
00460 }
00461
00462
00463 afptr = autofilter_symbolprefixlist;
00464 while (afptr->name)
00465 {
00466 if (strncmp (n, afptr->name, afptr->len) == 0)
00467 return 0;
00468
00469 afptr++;
00470 }
00471
00472
00473 len = strlen (n);
00474 afptr = autofilter_symbolsuffixlist;
00475 while (afptr->name)
00476 {
00477 if ((len >= afptr->len)
00478
00479 && strncmp (n + len - afptr->len, afptr->name,
00480 afptr->len + 1) == 0)
00481 return 0;
00482
00483 afptr++;
00484 }
00485 }
00486
00487 for (ex = excludes; ex; ex = ex->next)
00488 {
00489 if (ex->type == 1)
00490 {
00491 if (libname
00492 && ((strcmp (libname, ex->string) == 0)
00493 || (strcasecmp ("ALL", ex->string) == 0)))
00494 return 0;
00495 }
00496 else if (strcmp (n, ex->string) == 0)
00497 return 0;
00498 }
00499
00500 return 1;
00501 }
00502
00503 static void
00504 process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
00505 {
00506 int i, j;
00507 struct bfd_link_hash_entry *blhe;
00508 bfd *b;
00509 struct bfd_section *s;
00510 def_file_export *e = 0;
00511
00512 if (!pe_def_file)
00513 pe_def_file = def_file_empty ();
00514
00515
00516
00517 for (b = info->input_bfds; b; b = b->link_next)
00518 {
00519 s = bfd_get_section_by_name (b, ".drectve");
00520 if (s)
00521 {
00522 long size = s->size;
00523 char *buf = xmalloc (size);
00524
00525 bfd_get_section_contents (b, s, buf, 0, size);
00526 def_file_add_directive (pe_def_file, buf, size);
00527 free (buf);
00528 }
00529 }
00530
00531
00532
00533 if (!pe_dll_export_everything && pe_def_file->num_exports == 0
00534 && info->executable)
00535 return;
00536
00537
00538 if (pe_dll_export_everything || pe_def_file->num_exports == 0)
00539 {
00540 for (b = info->input_bfds; b; b = b->link_next)
00541 {
00542 asymbol **symbols;
00543 int nsyms, symsize;
00544
00545 symsize = bfd_get_symtab_upper_bound (b);
00546 symbols = xmalloc (symsize);
00547 nsyms = bfd_canonicalize_symtab (b, symbols);
00548
00549 for (j = 0; j < nsyms; j++)
00550 {
00551
00552
00553
00554 if (symbols[j]->section != &bfd_und_section
00555 && ((symbols[j]->flags & BSF_GLOBAL)
00556 || (symbols[j]->flags == BFD_FORT_COMM_DEFAULT_VALUE)))
00557 {
00558 const char *sn = symbols[j]->name;
00559
00560
00561 {
00562 char *name = xmalloc (strlen (sn) + 2 + 6);
00563 sprintf (name, "%s%s", U("_imp_"), sn);
00564
00565 blhe = bfd_link_hash_lookup (info->hash, name,
00566 FALSE, FALSE, FALSE);
00567 free (name);
00568
00569 if (blhe && blhe->type == bfd_link_hash_defined)
00570 continue;
00571 }
00572
00573 if (*sn == '_')
00574 sn++;
00575
00576 if (auto_export (b, pe_def_file, sn))
00577 {
00578 def_file_export *p;
00579 p=def_file_add_export (pe_def_file, sn, 0, -1);
00580
00581 p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
00582 }
00583 }
00584 }
00585 }
00586 }
00587
00588 #undef NE
00589 #define NE pe_def_file->num_exports
00590
00591
00592 if (pe_dll_kill_ats)
00593 {
00594 for (i = 0; i < NE; i++)
00595 {
00596 if (strchr (pe_def_file->exports[i].name, '@'))
00597 {
00598
00599
00600
00601 int lead_at = (*pe_def_file->exports[i].name == '@');
00602 char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
00603
00604 *(strchr (tmp, '@')) = 0;
00605 pe_def_file->exports[i].name = tmp;
00606 }
00607 }
00608 }
00609
00610 if (pe_dll_stdcall_aliases)
00611 {
00612 for (i = 0; i < NE; i++)
00613 {
00614 if (strchr (pe_def_file->exports[i].name, '@'))
00615 {
00616 int lead_at = (*pe_def_file->exports[i].name == '@');
00617 char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
00618
00619 *(strchr (tmp, '@')) = 0;
00620 if (auto_export (NULL, pe_def_file, tmp))
00621 def_file_add_export (pe_def_file, tmp,
00622 pe_def_file->exports[i].internal_name,
00623 -1);
00624 else
00625 free (tmp);
00626 }
00627 }
00628 }
00629
00630
00631 e = pe_def_file->exports;
00632
00633 exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
00634 exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
00635
00636 memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
00637 max_ordinal = 0;
00638 min_ordinal = 65536;
00639 count_exported = 0;
00640 count_exported_byname = 0;
00641 count_with_ordinals = 0;
00642
00643 qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]),
00644 pe_export_sort);
00645 for (i = 0, j = 0; i < NE; i++)
00646 {
00647 if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
00648 {
00649
00650 if (e[j - 1].ordinal != -1
00651 && e[i].ordinal != -1
00652 && e[j - 1].ordinal != e[i].ordinal)
00653 {
00654 if (pe_dll_warn_dup_exports)
00655
00656 einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"),
00657 e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
00658 }
00659 else
00660 {
00661 if (pe_dll_warn_dup_exports)
00662
00663 einfo (_("Warning, duplicate EXPORT: %s\n"),
00664 e[j - 1].name);
00665 }
00666
00667 if (e[i].ordinal != -1)
00668 e[j - 1].ordinal = e[i].ordinal;
00669 e[j - 1].flag_private |= e[i].flag_private;
00670 e[j - 1].flag_constant |= e[i].flag_constant;
00671 e[j - 1].flag_noname |= e[i].flag_noname;
00672 e[j - 1].flag_data |= e[i].flag_data;
00673 }
00674 else
00675 {
00676 if (i != j)
00677 e[j] = e[i];
00678 j++;
00679 }
00680 }
00681 pe_def_file->num_exports = j;
00682
00683 for (i = 0; i < NE; i++)
00684 {
00685 char *name;
00686
00687 name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
00688 if (pe_details->underscored
00689 && (*pe_def_file->exports[i].internal_name != '@'))
00690 {
00691 *name = '_';
00692 strcpy (name + 1, pe_def_file->exports[i].internal_name);
00693 }
00694 else
00695 strcpy (name, pe_def_file->exports[i].internal_name);
00696
00697 blhe = bfd_link_hash_lookup (info->hash,
00698 name,
00699 FALSE, FALSE, TRUE);
00700
00701 if (blhe
00702 && (blhe->type == bfd_link_hash_defined
00703 || (blhe->type == bfd_link_hash_common)))
00704 {
00705 count_exported++;
00706 if (!pe_def_file->exports[i].flag_noname)
00707 count_exported_byname++;
00708
00709
00710
00711
00712 if (blhe->type == bfd_link_hash_defined)
00713 exported_symbol_sections[i] = blhe->u.def.section;
00714 else
00715 exported_symbol_sections[i] = blhe->u.c.p->section;
00716
00717 if (pe_def_file->exports[i].ordinal != -1)
00718 {
00719 if (max_ordinal < pe_def_file->exports[i].ordinal)
00720 max_ordinal = pe_def_file->exports[i].ordinal;
00721 if (min_ordinal > pe_def_file->exports[i].ordinal)
00722 min_ordinal = pe_def_file->exports[i].ordinal;
00723 count_with_ordinals++;
00724 }
00725 }
00726 else if (blhe && blhe->type == bfd_link_hash_undefined)
00727 {
00728
00729 einfo (_("%XCannot export %s: symbol not defined\n"),
00730 pe_def_file->exports[i].internal_name);
00731 }
00732 else if (blhe)
00733 {
00734
00735 einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"),
00736 pe_def_file->exports[i].internal_name,
00737 blhe->type, bfd_link_hash_defined);
00738 }
00739 else
00740 {
00741
00742 einfo (_("%XCannot export %s: symbol not found\n"),
00743 pe_def_file->exports[i].internal_name);
00744 }
00745 free (name);
00746 }
00747 }
00748
00749
00750
00751 static void
00752 build_filler_bfd (int include_edata)
00753 {
00754 lang_input_statement_type *filler_file;
00755 filler_file = lang_add_input_file ("dll stuff",
00756 lang_input_file_is_fake_enum,
00757 NULL);
00758 filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", output_bfd);
00759 if (filler_bfd == NULL
00760 || !bfd_set_arch_mach (filler_bfd,
00761 bfd_get_arch (output_bfd),
00762 bfd_get_mach (output_bfd)))
00763 {
00764 einfo ("%X%P: can not create BFD %E\n");
00765 return;
00766 }
00767
00768 if (include_edata)
00769 {
00770 edata_s = bfd_make_section_old_way (filler_bfd, ".edata");
00771 if (edata_s == NULL
00772 || !bfd_set_section_flags (filler_bfd, edata_s,
00773 (SEC_HAS_CONTENTS
00774 | SEC_ALLOC
00775 | SEC_LOAD
00776 | SEC_KEEP
00777 | SEC_IN_MEMORY)))
00778 {
00779 einfo ("%X%P: can not create .edata section: %E\n");
00780 return;
00781 }
00782 bfd_set_section_size (filler_bfd, edata_s, edata_sz);
00783 }
00784
00785 reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc");
00786 if (reloc_s == NULL
00787 || !bfd_set_section_flags (filler_bfd, reloc_s,
00788 (SEC_HAS_CONTENTS
00789 | SEC_ALLOC
00790 | SEC_LOAD
00791 | SEC_KEEP
00792 | SEC_IN_MEMORY)))
00793 {
00794 einfo ("%X%P: can not create .reloc section: %E\n");
00795 return;
00796 }
00797
00798 bfd_set_section_size (filler_bfd, reloc_s, 0);
00799
00800 ldlang_add_file (filler_file);
00801 }
00802
00803
00804
00805 static void
00806 generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
00807 {
00808 int i, next_ordinal;
00809 int name_table_size = 0;
00810 const char *dlnp;
00811
00812
00813
00814 if (pe_def_file->name)
00815 dll_name = pe_def_file->name;
00816 else
00817 {
00818 dll_name = abfd->filename;
00819
00820 for (dlnp = dll_name; *dlnp; dlnp++)
00821 if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')
00822 dll_name = dlnp + 1;
00823 }
00824
00825 if (count_with_ordinals && max_ordinal > count_exported)
00826 {
00827 if (min_ordinal > max_ordinal - count_exported + 1)
00828 min_ordinal = max_ordinal - count_exported + 1;
00829 }
00830 else
00831 {
00832 min_ordinal = 1;
00833 max_ordinal = count_exported;
00834 }
00835
00836 export_table_size = max_ordinal - min_ordinal + 1;
00837 exported_symbols = xmalloc (export_table_size * sizeof (int));
00838 for (i = 0; i < export_table_size; i++)
00839 exported_symbols[i] = -1;
00840
00841
00842 for (i = 0; i < NE; i++)
00843 {
00844 if (exported_symbol_sections[i])
00845 {
00846 if (pe_def_file->exports[i].ordinal != -1)
00847 {
00848 int ei = pe_def_file->exports[i].ordinal - min_ordinal;
00849 int pi = exported_symbols[ei];
00850
00851 if (pi != -1)
00852 {
00853
00854 einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"),
00855 pe_def_file->exports[i].ordinal,
00856 pe_def_file->exports[i].name,
00857 pe_def_file->exports[pi].name);
00858 }
00859 exported_symbols[ei] = i;
00860 }
00861 name_table_size += strlen (pe_def_file->exports[i].name) + 1;
00862 }
00863 }
00864
00865 next_ordinal = min_ordinal;
00866 for (i = 0; i < NE; i++)
00867 if (exported_symbol_sections[i])
00868 if (pe_def_file->exports[i].ordinal == -1)
00869 {
00870 while (exported_symbols[next_ordinal - min_ordinal] != -1)
00871 next_ordinal++;
00872
00873 exported_symbols[next_ordinal - min_ordinal] = i;
00874 pe_def_file->exports[i].ordinal = next_ordinal;
00875 }
00876
00877
00878 edata_sz = (40
00879 + 4 * export_table_size
00880 + 4 * count_exported_byname
00881 + 2 * count_exported_byname
00882 + name_table_size + strlen (dll_name) + 1);
00883 }
00884
00885
00886
00887
00888 static void
00889 fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
00890 {
00891 int i;
00892 struct bfd_link_hash_entry *blhe;
00893
00894 for (i = 0; i < pe_def_file->num_exports; i++)
00895 {
00896 char *name;
00897
00898 name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
00899 if (pe_details->underscored
00900 && *pe_def_file->exports[i].internal_name != '@')
00901 {
00902 *name = '_';
00903 strcpy (name + 1, pe_def_file->exports[i].internal_name);
00904 }
00905 else
00906 strcpy (name, pe_def_file->exports[i].internal_name);
00907
00908 blhe = bfd_link_hash_lookup (info->hash,
00909 name,
00910 FALSE, FALSE, TRUE);
00911
00912 if (blhe && blhe->type == bfd_link_hash_defined)
00913 exported_symbol_offsets[i] = blhe->u.def.value;
00914
00915 free (name);
00916 }
00917 }
00918
00919 static void
00920 fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
00921 {
00922 int s, hint;
00923 unsigned char *edirectory;
00924 unsigned char *eaddresses;
00925 unsigned char *enameptrs;
00926 unsigned char *eordinals;
00927 char *enamestr;
00928 time_t now;
00929
00930 time (&now);
00931
00932 edata_d = xmalloc (edata_sz);
00933
00934
00935 edirectory = edata_d;
00936 eaddresses = edata_d + 40;
00937 enameptrs = eaddresses + 4 * export_table_size;
00938 eordinals = enameptrs + 4 * count_exported_byname;
00939 enamestr = (char *) eordinals + 2 * count_exported_byname;
00940
00941 #define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \
00942 + edata_s->output_section->vma - image_base)
00943
00944 memset (edata_d, 0, edata_sz);
00945 bfd_put_32 (abfd, now, edata_d + 4);
00946 if (pe_def_file->version_major != -1)
00947 {
00948 bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8);
00949 bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10);
00950 }
00951
00952 bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);
00953 strcpy (enamestr, dll_name);
00954 enamestr += strlen (enamestr) + 1;
00955 bfd_put_32 (abfd, min_ordinal, edata_d + 16);
00956 bfd_put_32 (abfd, export_table_size, edata_d + 20);
00957 bfd_put_32 (abfd, count_exported_byname, edata_d + 24);
00958 bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28);
00959 bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32);
00960 bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36);
00961
00962 fill_exported_offsets (abfd, info);
00963
00964
00965
00966
00967
00968
00969
00970 hint = 0;
00971 for (s = 0; s < NE; s++)
00972 {
00973 struct bfd_section *ssec = exported_symbol_sections[s];
00974 if (ssec && pe_def_file->exports[s].ordinal != -1)
00975 {
00976 unsigned long srva = (exported_symbol_offsets[s]
00977 + ssec->output_section->vma
00978 + ssec->output_offset);
00979 int ord = pe_def_file->exports[s].ordinal;
00980
00981 bfd_put_32 (abfd, srva - image_base,
00982 eaddresses + 4 * (ord - min_ordinal));
00983
00984 if (!pe_def_file->exports[s].flag_noname)
00985 {
00986 char *ename = pe_def_file->exports[s].name;
00987
00988 bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
00989 enameptrs += 4;
00990 strcpy (enamestr, ename);
00991 enamestr += strlen (enamestr) + 1;
00992 bfd_put_16 (abfd, ord - min_ordinal, eordinals);
00993 eordinals += 2;
00994 pe_def_file->exports[s].hint = hint++;
00995 }
00996 }
00997 }
00998 }
00999
01000
01001 static struct bfd_section *current_sec;
01002
01003 void
01004 pe_walk_relocs_of_symbol (struct bfd_link_info *info,
01005 const char *name,
01006 int (*cb) (arelent *, asection *))
01007 {
01008 bfd *b;
01009 asection *s;
01010
01011 for (b = info->input_bfds; b; b = b->link_next)
01012 {
01013 asymbol **symbols;
01014 int nsyms, symsize;
01015
01016 symsize = bfd_get_symtab_upper_bound (b);
01017 symbols = xmalloc (symsize);
01018 nsyms = bfd_canonicalize_symtab (b, symbols);
01019
01020 for (s = b->sections; s; s = s->next)
01021 {
01022 arelent **relocs;
01023 int relsize, nrelocs, i;
01024 int flags = bfd_get_section_flags (b, s);
01025
01026
01027 if (flags & SEC_LINK_ONCE
01028 && s->output_section == bfd_abs_section_ptr)
01029 continue;
01030
01031 current_sec = s;
01032
01033 relsize = bfd_get_reloc_upper_bound (b, s);
01034 relocs = xmalloc (relsize);
01035 nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
01036
01037 for (i = 0; i < nrelocs; i++)
01038 {
01039 struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
01040
01041 if (!strcmp (name, sym->name))
01042 cb (relocs[i], s);
01043 }
01044
01045 free (relocs);
01046
01047
01048
01049
01050 }
01051 }
01052 }
01053
01054
01055
01056 static void
01057 generate_reloc (bfd *abfd, struct bfd_link_info *info)
01058 {
01059
01060
01061 reloc_data_type *reloc_data;
01062 int total_relocs = 0;
01063 int i;
01064 unsigned long sec_page = (unsigned long) -1;
01065 unsigned long page_ptr, page_count;
01066 int bi;
01067 bfd *b;
01068 struct bfd_section *s;
01069
01070 total_relocs = 0;
01071 for (b = info->input_bfds; b; b = b->link_next)
01072 for (s = b->sections; s; s = s->next)
01073 total_relocs += s->reloc_count;
01074
01075 reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type));
01076
01077 total_relocs = 0;
01078 bi = 0;
01079 for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)
01080 {
01081 arelent **relocs;
01082 int relsize, nrelocs, i;
01083
01084 for (s = b->sections; s; s = s->next)
01085 {
01086 unsigned long sec_vma = s->output_section->vma + s->output_offset;
01087 asymbol **symbols;
01088 int nsyms, symsize;
01089
01090
01091 if (!(s->output_section->flags & SEC_LOAD))
01092 continue;
01093
01094
01095
01096 if (s->output_section == &bfd_abs_section)
01097 continue;
01098
01099 if (s->output_section->vma == 0)
01100 {
01101
01102 einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n",
01103 s->output_section->name, s->output_section->index,
01104 s->output_section->flags);
01105 continue;
01106 }
01107
01108 symsize = bfd_get_symtab_upper_bound (b);
01109 symbols = xmalloc (symsize);
01110 nsyms = bfd_canonicalize_symtab (b, symbols);
01111
01112 relsize = bfd_get_reloc_upper_bound (b, s);
01113 relocs = xmalloc (relsize);
01114 nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
01115
01116 for (i = 0; i < nrelocs; i++)
01117 {
01118 if (pe_dll_extra_pe_debug)
01119 {
01120 struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
01121 printf ("rel: %s\n", sym->name);
01122 }
01123 if (!relocs[i]->howto->pc_relative
01124 && relocs[i]->howto->type != pe_details->imagebase_reloc)
01125 {
01126 bfd_vma sym_vma;
01127 struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
01128
01129 sym_vma = (relocs[i]->addend
01130 + sym->value
01131 + sym->section->vma
01132 + sym->section->output_offset
01133 + sym->section->output_section->vma);
01134 reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
01135
01136 #define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
01137
01138 switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
01139 relocs[i]->howto->rightshift)
01140 {
01141 case BITS_AND_SHIFT (32, 0):
01142 reloc_data[total_relocs].type = 3;
01143 total_relocs++;
01144 break;
01145 case BITS_AND_SHIFT (16, 0):
01146 reloc_data[total_relocs].type = 2;
01147 total_relocs++;
01148 break;
01149 case BITS_AND_SHIFT (16, 16):
01150 reloc_data[total_relocs].type = 4;
01151
01152
01153
01154
01155 reloc_data[total_relocs].extra = 0;
01156 total_relocs++;
01157 break;
01158 case BITS_AND_SHIFT (26, 2):
01159 reloc_data[total_relocs].type = 5;
01160 total_relocs++;
01161 break;
01162 case BITS_AND_SHIFT (24, 2):
01163
01164
01165
01166 if (relocs[i]->howto->type == 0
01167
01168 || relocs[i]->howto->type == 5)
01169
01170
01171
01172 break;
01173
01174 default:
01175
01176 einfo (_("%XError: %d-bit reloc in dll\n"),
01177 relocs[i]->howto->bitsize);
01178 break;
01179 }
01180 }
01181 }
01182 free (relocs);
01183
01184
01185 }
01186 }
01187
01188
01189
01190
01191 qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort);
01192
01193 for (i = 0; i < total_relocs; i++)
01194 {
01195 unsigned long this_page = (reloc_data[i].vma >> 12);
01196
01197 if (this_page != sec_page)
01198 {
01199 reloc_sz = (reloc_sz + 3) & ~3;
01200 reloc_sz += 8;
01201 sec_page = this_page;
01202 }
01203
01204 reloc_sz += 2;
01205
01206 if (reloc_data[i].type == 4)
01207 reloc_sz += 2;
01208 }
01209
01210 reloc_sz = (reloc_sz + 3) & ~3;
01211 reloc_d = xmalloc (reloc_sz);
01212 sec_page = (unsigned long) -1;
01213 reloc_sz = 0;
01214 page_ptr = (unsigned long) -1;
01215 page_count = 0;
01216
01217 for (i = 0; i < total_relocs; i++)
01218 {
01219 unsigned long rva = reloc_data[i].vma - image_base;
01220 unsigned long this_page = (rva & ~0xfff);
01221
01222 if (this_page != sec_page)
01223 {
01224 while (reloc_sz & 3)
01225 reloc_d[reloc_sz++] = 0;
01226
01227 if (page_ptr != (unsigned long) -1)
01228 bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
01229
01230 bfd_put_32 (abfd, this_page, reloc_d + reloc_sz);
01231 page_ptr = reloc_sz;
01232 reloc_sz += 8;
01233 sec_page = this_page;
01234 page_count = 0;
01235 }
01236
01237 bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
01238 reloc_d + reloc_sz);
01239 reloc_sz += 2;
01240
01241 if (reloc_data[i].type == 4)
01242 {
01243 bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
01244 reloc_sz += 2;
01245 }
01246
01247 page_count++;
01248 }
01249
01250 while (reloc_sz & 3)
01251 reloc_d[reloc_sz++] = 0;
01252
01253 if (page_ptr != (unsigned long) -1)
01254 bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
01255
01256 while (reloc_sz < reloc_s->size)
01257 reloc_d[reloc_sz++] = 0;
01258 }
01259
01260
01261
01262
01263 static void
01264 quoteput (char *s, FILE *f, int needs_quotes)
01265 {
01266 char *cp;
01267
01268 for (cp = s; *cp; cp++)
01269 if (*cp == '\''
01270 || *cp == '"'
01271 || *cp == '\\'
01272 || ISSPACE (*cp)
01273 || *cp == ','
01274 || *cp == ';')
01275 needs_quotes = 1;
01276
01277 if (needs_quotes)
01278 {
01279 putc ('"', f);
01280
01281 while (*s)
01282 {
01283 if (*s == '"' || *s == '\\')
01284 putc ('\\', f);
01285
01286 putc (*s, f);
01287 s++;
01288 }
01289
01290 putc ('"', f);
01291 }
01292 else
01293 fputs (s, f);
01294 }
01295
01296 void
01297 pe_dll_generate_def_file (const char *pe_out_def_filename)
01298 {
01299 int i;
01300 FILE *out = fopen (pe_out_def_filename, "w");
01301
01302 if (out == NULL)
01303
01304 einfo (_("%s: Can't open output def file %s\n"),
01305 program_name, pe_out_def_filename);
01306
01307 if (pe_def_file)
01308 {
01309 if (pe_def_file->name)
01310 {
01311 if (pe_def_file->is_dll)
01312 fprintf (out, "LIBRARY ");
01313 else
01314 fprintf (out, "NAME ");
01315
01316 quoteput (pe_def_file->name, out, 1);
01317
01318 if (pe_data (output_bfd)->pe_opthdr.ImageBase)
01319 fprintf (out, " BASE=0x%lx",
01320 (unsigned long) pe_data (output_bfd)->pe_opthdr.ImageBase);
01321 fprintf (out, "\n");
01322 }
01323
01324 if (pe_def_file->description)
01325 {
01326 fprintf (out, "DESCRIPTION ");
01327 quoteput (pe_def_file->description, out, 1);
01328 fprintf (out, "\n");
01329 }
01330
01331 if (pe_def_file->version_minor != -1)
01332 fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major,
01333 pe_def_file->version_minor);
01334 else if (pe_def_file->version_major != -1)
01335 fprintf (out, "VERSION %d\n", pe_def_file->version_major);
01336
01337 if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1)
01338 fprintf (out, "\n");
01339
01340 if (pe_def_file->stack_commit != -1)
01341 fprintf (out, "STACKSIZE 0x%x,0x%x\n",
01342 pe_def_file->stack_reserve, pe_def_file->stack_commit);
01343 else if (pe_def_file->stack_reserve != -1)
01344 fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve);
01345
01346 if (pe_def_file->heap_commit != -1)
01347 fprintf (out, "HEAPSIZE 0x%x,0x%x\n",
01348 pe_def_file->heap_reserve, pe_def_file->heap_commit);
01349 else if (pe_def_file->heap_reserve != -1)
01350 fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve);
01351
01352 if (pe_def_file->num_section_defs > 0)
01353 {
01354 fprintf (out, "\nSECTIONS\n\n");
01355
01356 for (i = 0; i < pe_def_file->num_section_defs; i++)
01357 {
01358 fprintf (out, " ");
01359 quoteput (pe_def_file->section_defs[i].name, out, 0);
01360
01361 if (pe_def_file->section_defs[i].class)
01362 {
01363 fprintf (out, " CLASS ");
01364 quoteput (pe_def_file->section_defs[i].class, out, 0);
01365 }
01366
01367 if (pe_def_file->section_defs[i].flag_read)
01368 fprintf (out, " READ");
01369
01370 if (pe_def_file->section_defs[i].flag_write)
01371 fprintf (out, " WRITE");
01372
01373 if (pe_def_file->section_defs[i].flag_execute)
01374 fprintf (out, " EXECUTE");
01375
01376 if (pe_def_file->section_defs[i].flag_shared)
01377 fprintf (out, " SHARED");
01378
01379 fprintf (out, "\n");
01380 }
01381 }
01382
01383 if (pe_def_file->num_exports > 0)
01384 {
01385 fprintf (out, "EXPORTS\n");
01386
01387 for (i = 0; i < pe_def_file->num_exports; i++)
01388 {
01389 def_file_export *e = pe_def_file->exports + i;
01390 fprintf (out, " ");
01391 quoteput (e->name, out, 0);
01392
01393 if (e->internal_name && strcmp (e->internal_name, e->name))
01394 {
01395 fprintf (out, " = ");
01396 quoteput (e->internal_name, out, 0);
01397 }
01398
01399 if (e->ordinal != -1)
01400 fprintf (out, " @%d", e->ordinal);
01401
01402 if (e->flag_private)
01403 fprintf (out, " PRIVATE");
01404
01405 if (e->flag_constant)
01406 fprintf (out, " CONSTANT");
01407
01408 if (e->flag_noname)
01409 fprintf (out, " NONAME");
01410
01411 if (e->flag_data)
01412 fprintf (out, " DATA");
01413
01414 fprintf (out, "\n");
01415 }
01416 }
01417
01418 if (pe_def_file->num_imports > 0)
01419 {
01420 fprintf (out, "\nIMPORTS\n\n");
01421
01422 for (i = 0; i < pe_def_file->num_imports; i++)
01423 {
01424 def_file_import *im = pe_def_file->imports + i;
01425 fprintf (out, " ");
01426
01427 if (im->internal_name
01428 && (!im->name || strcmp (im->internal_name, im->name)))
01429 {
01430 quoteput (im->internal_name, out, 0);
01431 fprintf (out, " = ");
01432 }
01433
01434 quoteput (im->module->name, out, 0);
01435 fprintf (out, ".");
01436
01437 if (im->name)
01438 quoteput (im->name, out, 0);
01439 else
01440 fprintf (out, "%d", im->ordinal);
01441
01442 fprintf (out, "\n");
01443 }
01444 }
01445 }
01446 else
01447 fprintf (out, _("; no contents available\n"));
01448
01449 if (fclose (out) == EOF)
01450
01451 einfo (_("%P: Error closing file `%s'\n"), pe_out_def_filename);
01452 }
01453
01454
01455
01456 static asymbol **symtab;
01457 static int symptr;
01458 static int tmp_seq;
01459 static const char *dll_filename;
01460 static char *dll_symname;
01461
01462 #define UNDSEC (asection *) &bfd_und_section
01463
01464 static asection *
01465 quick_section (bfd *abfd, const char *name, int flags, int align)
01466 {
01467 asection *sec;
01468 asymbol *sym;
01469
01470 sec = bfd_make_section_old_way (abfd, name);
01471 bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
01472 bfd_set_section_alignment (abfd, sec, align);
01473
01474 sec->output_section = sec;
01475
01476 sym = bfd_make_empty_symbol (abfd);
01477 symtab[symptr++] = sym;
01478 sym->name = sec->name;
01479 sym->section = sec;
01480 sym->flags = BSF_LOCAL;
01481 sym->value = 0;
01482
01483 return sec;
01484 }
01485
01486 static void
01487 quick_symbol (bfd *abfd,
01488 const char *n1,
01489 const char *n2,
01490 const char *n3,
01491 asection *sec,
01492 int flags,
01493 int addr)
01494 {
01495 asymbol *sym;
01496 char *name = xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1);
01497
01498 strcpy (name, n1);
01499 strcat (name, n2);
01500 strcat (name, n3);
01501 sym = bfd_make_empty_symbol (abfd);
01502 sym->name = name;
01503 sym->section = sec;
01504 sym->flags = flags;
01505 sym->value = addr;
01506 symtab[symptr++] = sym;
01507 }
01508
01509 static arelent *reltab = 0;
01510 static int relcount = 0, relsize = 0;
01511
01512 static void
01513 quick_reloc (bfd *abfd, int address, int which_howto, int symidx)
01514 {
01515 if (relcount >= relsize - 1)
01516 {
01517 relsize += 10;
01518 if (reltab)
01519 reltab = xrealloc (reltab, relsize * sizeof (arelent));
01520 else
01521 reltab = xmalloc (relsize * sizeof (arelent));
01522 }
01523 reltab[relcount].address = address;
01524 reltab[relcount].addend = 0;
01525 reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto);
01526 reltab[relcount].sym_ptr_ptr = symtab + symidx;
01527 relcount++;
01528 }
01529
01530 static void
01531 save_relocs (asection *sec)
01532 {
01533 int i;
01534
01535 sec->relocation = reltab;
01536 sec->reloc_count = relcount;
01537 sec->orelocation = xmalloc ((relcount + 1) * sizeof (arelent *));
01538 for (i = 0; i < relcount; i++)
01539 sec->orelocation[i] = sec->relocation + i;
01540 sec->orelocation[relcount] = 0;
01541 sec->flags |= SEC_RELOC;
01542 reltab = 0;
01543 relcount = relsize = 0;
01544 }
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563 static bfd *
01564 make_head (bfd *parent)
01565 {
01566 asection *id2, *id5, *id4;
01567 unsigned char *d2, *d5, *d4;
01568 char *oname;
01569 bfd *abfd;
01570
01571 oname = xmalloc (20);
01572 sprintf (oname, "d%06d.o", tmp_seq);
01573 tmp_seq++;
01574
01575 abfd = bfd_create (oname, parent);
01576 bfd_find_target (pe_details->object_target, abfd);
01577 bfd_make_writable (abfd);
01578
01579 bfd_set_format (abfd, bfd_object);
01580 bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
01581
01582 symptr = 0;
01583 symtab = xmalloc (6 * sizeof (asymbol *));
01584 id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
01585 id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
01586 id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
01587 quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0);
01588 quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
01589
01590
01591
01592
01593
01594
01595
01596 bfd_set_section_size (abfd, id2, 20);
01597 d2 = xmalloc (20);
01598 id2->contents = d2;
01599 memset (d2, 0, 20);
01600 d2[0] = d2[16] = 4;
01601 quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
01602 quick_reloc (abfd, 12, BFD_RELOC_RVA, 4);
01603 quick_reloc (abfd, 16, BFD_RELOC_RVA, 1);
01604 save_relocs (id2);
01605
01606 bfd_set_section_size (abfd, id5, 4);
01607 d5 = xmalloc (4);
01608 id5->contents = d5;
01609 memset (d5, 0, 4);
01610
01611 bfd_set_section_size (abfd, id4, 4);
01612 d4 = xmalloc (4);
01613 id4->contents = d4;
01614 memset (d4, 0, 4);
01615
01616 bfd_set_symtab (abfd, symtab, symptr);
01617
01618 bfd_set_section_contents (abfd, id2, d2, 0, 20);
01619 bfd_set_section_contents (abfd, id5, d5, 0, 4);
01620 bfd_set_section_contents (abfd, id4, d4, 0, 4);
01621
01622 bfd_make_readable (abfd);
01623 return abfd;
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635 static bfd *
01636 make_tail (bfd *parent)
01637 {
01638 asection *id4, *id5, *id7;
01639 unsigned char *d4, *d5, *d7;
01640 int len;
01641 char *oname;
01642 bfd *abfd;
01643
01644 oname = xmalloc (20);
01645 sprintf (oname, "d%06d.o", tmp_seq);
01646 tmp_seq++;
01647
01648 abfd = bfd_create (oname, parent);
01649 bfd_find_target (pe_details->object_target, abfd);
01650 bfd_make_writable (abfd);
01651
01652 bfd_set_format (abfd, bfd_object);
01653 bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
01654
01655 symptr = 0;
01656 symtab = xmalloc (5 * sizeof (asymbol *));
01657 id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
01658 id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
01659 id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
01660 quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
01661
01662 bfd_set_section_size (abfd, id4, 4);
01663 d4 = xmalloc (4);
01664 id4->contents = d4;
01665 memset (d4, 0, 4);
01666
01667 bfd_set_section_size (abfd, id5, 4);
01668 d5 = xmalloc (4);
01669 id5->contents = d5;
01670 memset (d5, 0, 4);
01671
01672 len = strlen (dll_filename) + 1;
01673 if (len & 1)
01674 len++;
01675 bfd_set_section_size (abfd, id7, len);
01676 d7 = xmalloc (len);
01677 id7->contents = d7;
01678 strcpy ((char *) d7, dll_filename);
01679
01680 bfd_set_symtab (abfd, symtab, symptr);
01681
01682 bfd_set_section_contents (abfd, id4, d4, 0, 4);
01683 bfd_set_section_contents (abfd, id5, d5, 0, 4);
01684 bfd_set_section_contents (abfd, id7, d7, 0, len);
01685
01686 bfd_make_readable (abfd);
01687 return abfd;
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711 static unsigned char jmp_ix86_bytes[] =
01712 {
01713 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
01714 };
01715
01716
01717
01718
01719
01720
01721
01722
01723 static unsigned char jmp_sh_bytes[] =
01724 {
01725 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00
01726 };
01727
01728
01729
01730
01731
01732
01733
01734 static unsigned char jmp_mips_bytes[] =
01735 {
01736 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
01737 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
01738 };
01739
01740 static bfd *
01741 make_one (def_file_export *exp, bfd *parent)
01742 {
01743 asection *tx, *id7, *id5, *id4, *id6;
01744 unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL;
01745 int len;
01746 char *oname;
01747 bfd *abfd;
01748 unsigned char *jmp_bytes = NULL;
01749 int jmp_byte_count = 0;
01750
01751 switch (pe_details->pe_arch)
01752 {
01753 case PE_ARCH_i386:
01754 jmp_bytes = jmp_ix86_bytes;
01755 jmp_byte_count = sizeof (jmp_ix86_bytes);
01756 break;
01757 case PE_ARCH_sh:
01758 jmp_bytes = jmp_sh_bytes;
01759 jmp_byte_count = sizeof (jmp_sh_bytes);
01760 break;
01761 case PE_ARCH_mips:
01762 jmp_bytes = jmp_mips_bytes;
01763 jmp_byte_count = sizeof (jmp_mips_bytes);
01764 break;
01765 default:
01766 abort ();
01767 }
01768
01769 oname = xmalloc (20);
01770 sprintf (oname, "d%06d.o", tmp_seq);
01771 tmp_seq++;
01772
01773 abfd = bfd_create (oname, parent);
01774 bfd_find_target (pe_details->object_target, abfd);
01775 bfd_make_writable (abfd);
01776
01777 bfd_set_format (abfd, bfd_object);
01778 bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
01779
01780 symptr = 0;
01781 symtab = xmalloc (11 * sizeof (asymbol *));
01782 tx = quick_section (abfd, ".text", SEC_CODE|SEC_HAS_CONTENTS, 2);
01783 id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
01784 id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
01785 id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
01786 id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
01787
01788 if (*exp->internal_name == '@')
01789 {
01790 quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
01791 BSF_GLOBAL, 0);
01792 if (! exp->flag_data)
01793 quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
01794 quick_symbol (abfd, U ("_imp_"), exp->internal_name, "", id5,
01795 BSF_GLOBAL, 0);
01796
01797
01798 }
01799 else
01800 {
01801 quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
01802 BSF_GLOBAL, 0);
01803 if (! exp->flag_data)
01804 quick_symbol (abfd, U (""), exp->internal_name, "", tx,
01805 BSF_GLOBAL, 0);
01806 quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5,
01807 BSF_GLOBAL, 0);
01808
01809
01810 if (exp->flag_data)
01811 quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6,
01812 BSF_GLOBAL,0);
01813 }
01814 if (pe_dll_compat_implib)
01815 quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5,
01816 BSF_GLOBAL, 0);
01817
01818 if (! exp->flag_data)
01819 {
01820 bfd_set_section_size (abfd, tx, jmp_byte_count);
01821 td = xmalloc (jmp_byte_count);
01822 tx->contents = td;
01823 memcpy (td, jmp_bytes, jmp_byte_count);
01824
01825 switch (pe_details->pe_arch)
01826 {
01827 case PE_ARCH_i386:
01828 quick_reloc (abfd, 2, BFD_RELOC_32, 2);
01829 break;
01830 case PE_ARCH_sh:
01831 quick_reloc (abfd, 8, BFD_RELOC_32, 2);
01832 break;
01833 case PE_ARCH_mips:
01834 quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2);
01835 quick_reloc (abfd, 0, BFD_RELOC_LO16, 0);
01836 quick_reloc (abfd, 4, BFD_RELOC_LO16, 2);
01837 break;
01838 default:
01839 abort ();
01840 }
01841 save_relocs (tx);
01842 }
01843
01844 bfd_set_section_size (abfd, id7, 4);
01845 d7 = xmalloc (4);
01846 id7->contents = d7;
01847 memset (d7, 0, 4);
01848 quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
01849 save_relocs (id7);
01850
01851 bfd_set_section_size (abfd, id5, 4);
01852 d5 = xmalloc (4);
01853 id5->contents = d5;
01854 memset (d5, 0, 4);
01855
01856 if (exp->flag_noname)
01857 {
01858 d5[0] = exp->ordinal;
01859 d5[1] = exp->ordinal >> 8;
01860 d5[3] = 0x80;
01861 }
01862 else
01863 {
01864 quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
01865 save_relocs (id5);
01866 }
01867
01868 bfd_set_section_size (abfd, id4, 4);
01869 d4 = xmalloc (4);
01870 id4->contents = d4;
01871 memset (d4, 0, 4);
01872
01873 if (exp->flag_noname)
01874 {
01875 d4[0] = exp->ordinal;
01876 d4[1] = exp->ordinal >> 8;
01877 d4[3] = 0x80;
01878 }
01879 else
01880 {
01881 quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
01882 save_relocs (id4);
01883 }
01884
01885 if (exp->flag_noname)
01886 {
01887 len = 0;
01888 bfd_set_section_size (abfd, id6, 0);
01889 }
01890 else
01891 {
01892 len = strlen (exp->name) + 3;
01893 if (len & 1)
01894 len++;
01895 bfd_set_section_size (abfd, id6, len);
01896 d6 = xmalloc (len);
01897 id6->contents = d6;
01898 memset (d6, 0, len);
01899 d6[0] = exp->hint & 0xff;
01900 d6[1] = exp->hint >> 8;
01901 strcpy ((char *) d6 + 2, exp->name);
01902 }
01903
01904 bfd_set_symtab (abfd, symtab, symptr);
01905
01906 bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count);
01907 bfd_set_section_contents (abfd, id7, d7, 0, 4);
01908 bfd_set_section_contents (abfd, id5, d5, 0, 4);
01909 bfd_set_section_contents (abfd, id4, d4, 0, 4);
01910 if (!exp->flag_noname)
01911 bfd_set_section_contents (abfd, id6, d6, 0, len);
01912
01913 bfd_make_readable (abfd);
01914 return abfd;
01915 }
01916
01917 static bfd *
01918 make_singleton_name_thunk (const char *import, bfd *parent)
01919 {
01920
01921 asection *id4;
01922 unsigned char *d4;
01923 char *oname;
01924 bfd *abfd;
01925
01926 oname = xmalloc (20);
01927 sprintf (oname, "nmth%06d.o", tmp_seq);
01928 tmp_seq++;
01929
01930 abfd = bfd_create (oname, parent);
01931 bfd_find_target (pe_details->object_target, abfd);
01932 bfd_make_writable (abfd);
01933
01934 bfd_set_format (abfd, bfd_object);
01935 bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
01936
01937 symptr = 0;
01938 symtab = xmalloc (3 * sizeof (asymbol *));
01939 id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
01940 quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
01941 quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
01942
01943 bfd_set_section_size (abfd, id4, 8);
01944 d4 = xmalloc (4);
01945 id4->contents = d4;
01946 memset (d4, 0, 8);
01947 quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
01948 save_relocs (id4);
01949
01950 bfd_set_symtab (abfd, symtab, symptr);
01951
01952 bfd_set_section_contents (abfd, id4, d4, 0, 8);
01953
01954 bfd_make_readable (abfd);
01955 return abfd;
01956 }
01957
01958 static char *
01959 make_import_fixup_mark (arelent *rel)
01960 {
01961
01962 static int counter;
01963 static char *fixup_name = NULL;
01964 static size_t buffer_len = 0;
01965
01966 struct bfd_symbol *sym = *rel->sym_ptr_ptr;
01967
01968 bfd *abfd = bfd_asymbol_bfd (sym);
01969 struct bfd_link_hash_entry *bh;
01970
01971 if (!fixup_name)
01972 {
01973 fixup_name = xmalloc (384);
01974 buffer_len = 384;
01975 }
01976
01977 if (strlen (sym->name) + 25 > buffer_len)
01978
01979
01980
01981 {
01982 free (fixup_name);
01983
01984
01985 buffer_len = ((strlen (sym->name) + 25) + 127) & ~127;
01986 fixup_name = xmalloc (buffer_len);
01987 }
01988
01989 sprintf (fixup_name, "__fu%d_%s", counter++, sym->name);
01990
01991 bh = NULL;
01992 bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL,
01993 current_sec,
01994 rel->address, NULL, TRUE, FALSE, &bh);
01995
01996 if (0)
01997 {
01998 struct coff_link_hash_entry *myh;
01999
02000 myh = (struct coff_link_hash_entry *) bh;
02001 printf ("type:%d\n", myh->type);
02002 printf ("%s\n", myh->root.u.def.section->name);
02003 }
02004
02005 return fixup_name;
02006 }
02007
02008
02009
02010
02011
02012
02013
02014
02015 static bfd *
02016 make_import_fixup_entry (const char *name,
02017 const char *fixup_name,
02018 const char *dll_symname,
02019 bfd *parent)
02020 {
02021 asection *id3;
02022 unsigned char *d3;
02023 char *oname;
02024 bfd *abfd;
02025
02026 oname = xmalloc (20);
02027 sprintf (oname, "fu%06d.o", tmp_seq);
02028 tmp_seq++;
02029
02030 abfd = bfd_create (oname, parent);
02031 bfd_find_target (pe_details->object_target, abfd);
02032 bfd_make_writable (abfd);
02033
02034 bfd_set_format (abfd, bfd_object);
02035 bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
02036
02037 symptr = 0;
02038 symtab = xmalloc (6 * sizeof (asymbol *));
02039 id3 = quick_section (abfd, ".idata$3", SEC_HAS_CONTENTS, 2);
02040
02041 quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);
02042 quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
02043 quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
02044
02045 bfd_set_section_size (abfd, id3, 20);
02046 d3 = xmalloc (20);
02047 id3->contents = d3;
02048 memset (d3, 0, 20);
02049
02050 quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
02051 quick_reloc (abfd, 12, BFD_RELOC_RVA, 2);
02052 quick_reloc (abfd, 16, BFD_RELOC_RVA, 3);
02053 save_relocs (id3);
02054
02055 bfd_set_symtab (abfd, symtab, symptr);
02056
02057 bfd_set_section_contents (abfd, id3, d3, 0, 20);
02058
02059 bfd_make_readable (abfd);
02060 return abfd;
02061 }
02062
02063
02064
02065
02066
02067 static bfd *
02068 make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
02069 const char *fixup_name,
02070 int addend,
02071 bfd *parent)
02072 {
02073 asection *rt_rel;
02074 unsigned char *rt_rel_d;
02075 char *oname;
02076 bfd *abfd;
02077
02078 oname = xmalloc (20);
02079 sprintf (oname, "rtr%06d.o", tmp_seq);
02080 tmp_seq++;
02081
02082 abfd = bfd_create (oname, parent);
02083 bfd_find_target (pe_details->object_target, abfd);
02084 bfd_make_writable (abfd);
02085
02086 bfd_set_format (abfd, bfd_object);
02087 bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
02088
02089 symptr = 0;
02090 symtab = xmalloc (2 * sizeof (asymbol *));
02091 rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc",
02092 SEC_HAS_CONTENTS, 2);
02093
02094 quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
02095
02096 bfd_set_section_size (abfd, rt_rel, 8);
02097 rt_rel_d = xmalloc (8);
02098 rt_rel->contents = rt_rel_d;
02099 memset (rt_rel_d, 0, 8);
02100 bfd_put_32 (abfd, addend, rt_rel_d);
02101
02102 quick_reloc (abfd, 4, BFD_RELOC_RVA, 1);
02103 save_relocs (rt_rel);
02104
02105 bfd_set_symtab (abfd, symtab, symptr);
02106
02107 bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8);
02108
02109 bfd_make_readable (abfd);
02110 return abfd;
02111 }
02112
02113
02114
02115
02116 static bfd *
02117 pe_create_runtime_relocator_reference (bfd *parent)
02118 {
02119 asection *extern_rt_rel;
02120 unsigned char *extern_rt_rel_d;
02121 char *oname;
02122 bfd *abfd;
02123
02124 oname = xmalloc (20);
02125 sprintf (oname, "ertr%06d.o", tmp_seq);
02126 tmp_seq++;
02127
02128 abfd = bfd_create (oname, parent);
02129 bfd_find_target (pe_details->object_target, abfd);
02130 bfd_make_writable (abfd);
02131
02132 bfd_set_format (abfd, bfd_object);
02133 bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
02134
02135 symptr = 0;
02136 symtab = xmalloc (2 * sizeof (asymbol *));
02137 extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2);
02138
02139 quick_symbol (abfd, "", "__pei386_runtime_relocator", "", UNDSEC,
02140 BSF_NO_FLAGS, 0);
02141
02142 bfd_set_section_size (abfd, extern_rt_rel, 4);
02143 extern_rt_rel_d = xmalloc (4);
02144 extern_rt_rel->contents = extern_rt_rel_d;
02145
02146 quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
02147 save_relocs (extern_rt_rel);
02148
02149 bfd_set_symtab (abfd, symtab, symptr);
02150
02151 bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, 4);
02152
02153 bfd_make_readable (abfd);
02154 return abfd;
02155 }
02156
02157 void
02158 pe_create_import_fixup (arelent *rel, asection *s, int addend)
02159 {
02160 char buf[300];
02161 struct bfd_symbol *sym = *rel->sym_ptr_ptr;
02162 struct bfd_link_hash_entry *name_thunk_sym;
02163 const char *name = sym->name;
02164 char *fixup_name = make_import_fixup_mark (rel);
02165 bfd *b;
02166
02167 sprintf (buf, U ("_nm_thnk_%s"), name);
02168
02169 name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
02170
02171 if (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined)
02172 {
02173 bfd *b = make_singleton_name_thunk (name, output_bfd);
02174 add_bfd_to_link (b, b->filename, &link_info);
02175
02176
02177 config.text_read_only = FALSE;
02178 output_bfd->flags &= ~WP_TEXT;
02179 }
02180
02181 if (addend == 0 || link_info.pei386_runtime_pseudo_reloc)
02182 {
02183 extern char * pe_data_import_dll;
02184 char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
02185
02186 b = make_import_fixup_entry (name, fixup_name, dll_symname, output_bfd);
02187 add_bfd_to_link (b, b->filename, &link_info);
02188 }
02189
02190 if (addend != 0)
02191 {
02192 if (link_info.pei386_runtime_pseudo_reloc)
02193 {
02194 if (pe_dll_extra_pe_debug)
02195 printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
02196 fixup_name, addend);
02197 b = make_runtime_pseudo_reloc (name, fixup_name, addend, output_bfd);
02198 add_bfd_to_link (b, b->filename, &link_info);
02199
02200 if (runtime_pseudo_relocs_created == 0)
02201 {
02202 b = pe_create_runtime_relocator_reference (output_bfd);
02203 add_bfd_to_link (b, b->filename, &link_info);
02204 }
02205 runtime_pseudo_relocs_created++;
02206 }
02207 else
02208 {
02209 einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
02210 s->owner, s, rel->address, sym->name);
02211 einfo ("%X");
02212 }
02213 }
02214 }
02215
02216
02217 void
02218 pe_dll_generate_implib (def_file *def, const char *impfilename)
02219 {
02220 int i;
02221 bfd *ar_head;
02222 bfd *ar_tail;
02223 bfd *outarch;
02224 bfd *head = 0;
02225
02226 dll_filename = (def->name) ? def->name : dll_name;
02227 dll_symname = xstrdup (dll_filename);
02228 for (i = 0; dll_symname[i]; i++)
02229 if (!ISALNUM (dll_symname[i]))
02230 dll_symname[i] = '_';
02231
02232 unlink_if_ordinary (impfilename);
02233
02234 outarch = bfd_openw (impfilename, 0);
02235
02236 if (!outarch)
02237 {
02238
02239 einfo (_("%XCan't open .lib file: %s\n"), impfilename);
02240 return;
02241 }
02242
02243
02244 einfo (_("Creating library file: %s\n"), impfilename);
02245
02246 bfd_set_format (outarch, bfd_archive);
02247 outarch->has_armap = 1;
02248
02249
02250 ar_head = make_head (outarch);
02251
02252 for (i = 0; i < def->num_exports; i++)
02253 {
02254
02255 char *internal = def->exports[i].internal_name;
02256 bfd *n;
02257
02258
02259 if (pe_def_file->exports[i].flag_private)
02260 continue;
02261 def->exports[i].internal_name = def->exports[i].name;
02262 n = make_one (def->exports + i, outarch);
02263 n->next = head;
02264 head = n;
02265 def->exports[i].internal_name = internal;
02266 }
02267
02268 ar_tail = make_tail (outarch);
02269
02270 if (ar_head == NULL || ar_tail == NULL)
02271 return;
02272
02273
02274 ar_head->next = head;
02275 ar_tail->next = ar_head;
02276 head = ar_tail;
02277
02278 if (! bfd_set_archive_head (outarch, head))
02279 einfo ("%Xbfd_set_archive_head: %s\n", bfd_errmsg (bfd_get_error ()));
02280
02281 if (! bfd_close (outarch))
02282 einfo ("%Xbfd_close %s: %s\n", impfilename, bfd_errmsg (bfd_get_error ()));
02283
02284 while (head != NULL)
02285 {
02286 bfd *n = head->next;
02287 bfd_close (head);
02288 head = n;
02289 }
02290 }
02291
02292 static void
02293 add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
02294 {
02295 lang_input_statement_type *fake_file;
02296
02297 fake_file = lang_add_input_file (name,
02298 lang_input_file_is_fake_enum,
02299 NULL);
02300 fake_file->the_bfd = abfd;
02301 ldlang_add_file (fake_file);
02302
02303 if (!bfd_link_add_symbols (abfd, link_info))
02304 einfo ("%Xaddsym %s: %s\n", name, bfd_errmsg (bfd_get_error ()));
02305 }
02306
02307 void
02308 pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
02309 {
02310 def_file_module *module;
02311
02312 pe_dll_id_target (bfd_get_target (output_bfd));
02313
02314 if (!pe_def_file)
02315 return;
02316
02317 for (module = pe_def_file->modules; module; module = module->next)
02318 {
02319 int i, do_this_dll;
02320
02321 dll_filename = module->name;
02322 dll_symname = xstrdup (module->name);
02323 for (i = 0; dll_symname[i]; i++)
02324 if (!ISALNUM (dll_symname[i]))
02325 dll_symname[i] = '_';
02326
02327 do_this_dll = 0;
02328
02329 for (i = 0; i < pe_def_file->num_imports; i++)
02330 if (pe_def_file->imports[i].module == module)
02331 {
02332 def_file_export exp;
02333 struct bfd_link_hash_entry *blhe;
02334 int lead_at = (*pe_def_file->imports[i].internal_name == '@');
02335
02336 size_t len = strlen (pe_def_file->imports[i].internal_name);
02337 char *name = xmalloc (len + 2 + 6);
02338
02339 if (lead_at)
02340 sprintf (name, "%s%s", "",
02341 pe_def_file->imports[i].internal_name);
02342 else
02343 sprintf (name, "%s%s",U (""),
02344 pe_def_file->imports[i].internal_name);
02345
02346 blhe = bfd_link_hash_lookup (link_info->hash, name,
02347 FALSE, FALSE, FALSE);
02348
02349 if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
02350 {
02351 if (lead_at)
02352 sprintf (name, "%s%s", U ("_imp_"),
02353 pe_def_file->imports[i].internal_name);
02354 else
02355 sprintf (name, "%s%s", U ("_imp__"),
02356 pe_def_file->imports[i].internal_name);
02357
02358 blhe = bfd_link_hash_lookup (link_info->hash, name,
02359 FALSE, FALSE, FALSE);
02360 }
02361 free (name);
02362
02363 if (blhe && blhe->type == bfd_link_hash_undefined)
02364 {
02365 bfd *one;
02366
02367 if (!do_this_dll)
02368 {
02369 bfd *ar_head = make_head (output_bfd);
02370 add_bfd_to_link (ar_head, ar_head->filename, link_info);
02371 do_this_dll = 1;
02372 }
02373 exp.internal_name = pe_def_file->imports[i].internal_name;
02374 exp.name = pe_def_file->imports[i].name;
02375 exp.ordinal = pe_def_file->imports[i].ordinal;
02376 exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
02377 exp.flag_private = 0;
02378 exp.flag_constant = 0;
02379 exp.flag_data = pe_def_file->imports[i].data;
02380 exp.flag_noname = exp.name ? 0 : 1;
02381 one = make_one (&exp, output_bfd);
02382 add_bfd_to_link (one, one->filename, link_info);
02383 }
02384 }
02385 if (do_this_dll)
02386 {
02387 bfd *ar_tail = make_tail (output_bfd);
02388 add_bfd_to_link (ar_tail, ar_tail->filename, link_info);
02389 }
02390
02391 free (dll_symname);
02392 }
02393 }
02394
02395
02396
02397
02398
02399 static unsigned int
02400 pe_get16 (bfd *abfd, int where)
02401 {
02402 unsigned char b[2];
02403
02404 bfd_seek (abfd, (file_ptr) where, SEEK_SET);
02405 bfd_bread (b, (bfd_size_type) 2, abfd);
02406 return b[0] + (b[1] << 8);
02407 }
02408
02409 static unsigned int
02410 pe_get32 (bfd *abfd, int where)
02411 {
02412 unsigned char b[4];
02413
02414 bfd_seek (abfd, (file_ptr) where, SEEK_SET);
02415 bfd_bread (b, (bfd_size_type) 4, abfd);
02416 return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
02417 }
02418
02419 static unsigned int
02420 pe_as32 (void *ptr)
02421 {
02422 unsigned char *b = ptr;
02423
02424 return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
02425 }
02426
02427 bfd_boolean
02428 pe_implied_import_dll (const char *filename)
02429 {
02430 bfd *dll;
02431 unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
02432 unsigned long export_rva, export_size, nsections, secptr, expptr;
02433 unsigned long exp_funcbase;
02434 unsigned char *expdata;
02435 char *erva;
02436 unsigned long name_rvas, ordinals, nexp, ordbase;
02437 const char *dll_name;
02438
02439
02440 unsigned long data_start = 1;
02441 unsigned long data_end = 0;
02442 unsigned long rdata_start = 1;
02443 unsigned long rdata_end = 0;
02444 unsigned long bss_start = 1;
02445 unsigned long bss_end = 0;
02446
02447
02448
02449 dll = bfd_openr (filename, pe_details->target_name);
02450 if (!dll)
02451 {
02452 einfo ("%Xopen %s: %s\n", filename, bfd_errmsg (bfd_get_error ()));
02453 return FALSE;
02454 }
02455
02456
02457 if (!bfd_check_format (dll, bfd_object))
02458 {
02459 einfo ("%X%s: this doesn't appear to be a DLL\n", filename);
02460 return FALSE;
02461 }
02462
02463
02464 pe_header_offset = pe_get32 (dll, 0x3c);
02465 opthdr_ofs = pe_header_offset + 4 + 20;
02466 num_entries = pe_get32 (dll, opthdr_ofs + 92);
02467
02468 if (num_entries < 1)
02469 return FALSE;
02470
02471 export_rva = pe_get32 (dll, opthdr_ofs + 96);
02472 export_size = pe_get32 (dll, opthdr_ofs + 100);
02473 nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
02474 secptr = (pe_header_offset + 4 + 20 +
02475 pe_get16 (dll, pe_header_offset + 4 + 16));
02476 expptr = 0;
02477
02478
02479 for (i = 0; i < nsections; i++)
02480 {
02481 char sname[8];
02482 unsigned long secptr1 = secptr + 40 * i;
02483 unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
02484 unsigned long vsize = pe_get32 (dll, secptr1 + 16);
02485 unsigned long fptr = pe_get32 (dll, secptr1 + 20);
02486
02487 bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
02488 bfd_bread (sname, (bfd_size_type) 8, dll);
02489
02490 if (vaddr <= export_rva && vaddr + vsize > export_rva)
02491 {
02492 expptr = fptr + (export_rva - vaddr);
02493 if (export_rva + export_size > vaddr + vsize)
02494 export_size = vsize - (export_rva - vaddr);
02495 break;
02496 }
02497 }
02498
02499
02500
02501 for (i = 0; i < nsections; i++)
02502 {
02503 unsigned long secptr1 = secptr + 40 * i;
02504 unsigned long vsize = pe_get32 (dll, secptr1 + 8);
02505 unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
02506 unsigned long flags = pe_get32 (dll, secptr1 + 36);
02507 char sec_name[9];
02508
02509 sec_name[8] = '\0';
02510 bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
02511 bfd_bread (sec_name, (bfd_size_type) 8, dll);
02512
02513 if (strcmp(sec_name,".data") == 0)
02514 {
02515 data_start = vaddr;
02516 data_end = vaddr + vsize;
02517
02518 if (pe_dll_extra_pe_debug)
02519 printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
02520 __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
02521 }
02522 else if (strcmp(sec_name,".rdata") == 0)
02523 {
02524 rdata_start = vaddr;
02525 rdata_end = vaddr + vsize;
02526
02527 if (pe_dll_extra_pe_debug)
02528 printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
02529 __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
02530 }
02531 else if (strcmp (sec_name,".bss") == 0)
02532 {
02533 bss_start = vaddr;
02534 bss_end = vaddr + vsize;
02535
02536 if (pe_dll_extra_pe_debug)
02537 printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
02538 __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
02539 }
02540 }
02541
02542 expdata = xmalloc (export_size);
02543 bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
02544 bfd_bread (expdata, (bfd_size_type) export_size, dll);
02545 erva = (char *) expdata - export_rva;
02546
02547 if (pe_def_file == 0)
02548 pe_def_file = def_file_empty ();
02549
02550 nexp = pe_as32 (expdata + 24);
02551 name_rvas = pe_as32 (expdata + 32);
02552 ordinals = pe_as32 (expdata + 36);
02553 ordbase = pe_as32 (expdata + 16);
02554 exp_funcbase = pe_as32 (expdata + 28);
02555
02556
02557
02558 dll_name = erva + pe_as32 (expdata + 12);
02559
02560
02561
02562
02563 if (def_get_module (pe_def_file, dll_name))
02564 {
02565 if (pe_dll_extra_pe_debug)
02566 printf ("%s is already loaded\n", dll_name);
02567 return TRUE;
02568 }
02569
02570
02571 for (i = 0; i < nexp; i++)
02572 {
02573
02574 unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
02575 def_file_import *imp;
02576
02577 unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);
02578 int is_data = 0;
02579
02580
02581
02582 if (strncmp (erva + name_rva, "_nm_", 4) != 0)
02583 {
02584
02585
02586 is_data =
02587 (func_rva >= data_start && func_rva < data_end)
02588 || (func_rva >= rdata_start && func_rva < rdata_end)
02589 || (func_rva >= bss_start && func_rva < bss_end);
02590
02591 imp = def_file_add_import (pe_def_file, erva + name_rva,
02592 dll_name, i, 0);
02593
02594 imp->data = is_data;
02595
02596 if (pe_dll_extra_pe_debug)
02597 printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
02598 __FUNCTION__, dll_name, erva + name_rva,
02599 func_rva, is_data ? "(data)" : "");
02600 }
02601 }
02602
02603 return TRUE;
02604 }
02605
02606
02607
02608
02609
02610
02611 void
02612 pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
02613 {
02614 pe_dll_id_target (bfd_get_target (abfd));
02615 process_def_file (abfd, info);
02616
02617 if (pe_def_file->num_exports == 0 && !info->shared)
02618 return;
02619
02620 generate_edata (abfd, info);
02621 build_filler_bfd (1);
02622 }
02623
02624 void
02625 pe_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
02626 {
02627 pe_dll_id_target (bfd_get_target (abfd));
02628 build_filler_bfd (0);
02629 }
02630
02631 void
02632 pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
02633 {
02634 pe_dll_id_target (bfd_get_target (abfd));
02635 image_base = pe_data (abfd)->pe_opthdr.ImageBase;
02636
02637 generate_reloc (abfd, info);
02638 if (reloc_sz > 0)
02639 {
02640 bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
02641
02642
02643 lang_size_sections (stat_ptr->head, abs_output_section,
02644 &stat_ptr->head, 0, 0, NULL, TRUE);
02645
02646
02647 ldemul_after_allocation ();
02648
02649
02650 lang_do_assignments (stat_ptr->head, abs_output_section, NULL, 0);
02651 }
02652
02653 fill_edata (abfd, info);
02654
02655 if (info->shared && !info->pie)
02656 pe_data (abfd)->dll = 1;
02657
02658 edata_s->contents = edata_d;
02659 reloc_s->contents = reloc_d;
02660 }
02661
02662 void
02663 pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
02664 {
02665 pe_dll_id_target (bfd_get_target (abfd));
02666 image_base = pe_data (abfd)->pe_opthdr.ImageBase;
02667
02668 generate_reloc (abfd, info);
02669 if (reloc_sz > 0)
02670 {
02671 bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
02672
02673
02674 lang_size_sections (stat_ptr->head, abs_output_section,
02675 &stat_ptr->head, 0, 0, NULL, TRUE);
02676
02677
02678 ldemul_after_allocation ();
02679
02680
02681 lang_do_assignments (stat_ptr->head, abs_output_section, NULL, 0);
02682 }
02683 reloc_s->contents = reloc_d;
02684 }