X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Femultempl%2Fpe.em;h=6519eae6d30642cd91f1f9483649e2608fcb2b65;hb=415b1b13876006c4704a85e6dfc8bdda38a5056e;hp=99829a20371b62eebd64c40db084ac73ba7cb542;hpb=b9a6918857531f9d3f41befcadc08929617b38de;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 99829a2037..6519eae6d3 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -1,10 +1,16 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. +if [ -z "$MACHINE" ]; then + OUTPUT_ARCH=${ARCH} +else + OUTPUT_ARCH=${ARCH}:${MACHINE} +fi rm -f e${EMULATION_NAME}.c (echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) cat >>e${EMULATION_NAME}.c < + #define TARGET_IS_${EMULATION_NAME} /* Permit the emulation parameters to override the default section @@ -127,10 +135,20 @@ extern const char *output_filename; static void gld_${EMULATION_NAME}_before_parse() { + const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}"); + if (arch) + { + ldfile_output_architecture = arch->arch; + ldfile_output_machine = arch->mach; + ldfile_output_machine_name = arch->printable_name; + } + else + ldfile_output_architecture = bfd_arch_${ARCH}; output_filename = "${EXECUTABLE_NAME:-a.exe}"; - ldfile_output_architecture = bfd_arch_${ARCH}; #ifdef DLL_SUPPORT + config.dynamic_link = true; config.has_shared = 1; +/* link_info.pei386_auto_import = true; */ #if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2) #if defined TARGET_IS_mipspe || defined TARGET_IS_armpe @@ -173,10 +191,13 @@ gld_${EMULATION_NAME}_before_parse() #define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1) #define OPTION_ENABLE_AUTO_IMAGE_BASE (OPTION_IMP_COMPAT + 1) #define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + 1) -#define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1) +#define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1) +#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_DLL_SEARCH_PREFIX + 1) +#define OPTION_DLL_ENABLE_AUTO_IMPORT (OPTION_NO_DEFAULT_EXCLUDES + 1) +#define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_DLL_ENABLE_AUTO_IMPORT + 1) +#define OPTION_ENABLE_EXTRA_PE_DEBUG (OPTION_DLL_DISABLE_AUTO_IMPORT + 1) -static struct option longopts[] = -{ +static struct option longopts[] = { /* PE options */ {"base-file", required_argument, NULL, OPTION_BASE_FILE}, {"dll", no_argument, NULL, OPTION_DLL}, @@ -211,6 +232,10 @@ static struct option longopts[] = {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE}, {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE}, {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX}, + {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, + {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT}, + {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT}, + {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG}, #endif {NULL, no_argument, NULL, 0} }; @@ -250,7 +275,7 @@ static definfo init[] = #endif D(MinorSubsystemVersion,"__minor_subsystem_version__", 0), D(Subsystem,"__subsystem__", ${SUBSYSTEM}), - D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x2000000), + D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000), D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000), D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000), D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000), @@ -296,6 +321,11 @@ gld_${EMULATION_NAME}_list_options (file) fprintf (file, _(" --dll-search-prefix= When linking dynamically to a dll witout an\n")); fprintf (file, _(" importlib, use .dll \n")); fprintf (file, _(" in preference to lib.dll \n")); + fprintf (file, _(" --enable-auto-import Do sophistcated linking of _sym to \n")); + fprintf (file, _(" __imp_sym for DATA references\n")); + fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n")); + fprintf (file, _(" --enable-extra-pe-debug Enable verbose debug output when building\n")); + fprintf (file, _(" or linking to DLLs (esp. auto-import)\n")); #endif } @@ -563,6 +593,18 @@ gld_${EMULATION_NAME}_parse_args(argc, argv) case OPTION_DLL_SEARCH_PREFIX: pe_dll_search_prefix = xstrdup( optarg ); break; + case OPTION_NO_DEFAULT_EXCLUDES: + pe_dll_do_default_excludes = 0; + break; + case OPTION_DLL_ENABLE_AUTO_IMPORT: + link_info.pei386_auto_import = true; + break; + case OPTION_DLL_DISABLE_AUTO_IMPORT: + link_info.pei386_auto_import = false; + break; + case OPTION_ENABLE_EXTRA_PE_DEBUG: + pe_dll_extra_pe_debug = 1; + break; #endif } return 1; @@ -696,14 +738,15 @@ pe_undef_cdecl_match (h, string) struct bfd_link_hash_entry *h; PTR string; { - int sl = strlen (string); + int sl; + sl = strlen (string); /* silence compiler warning */ if (h->type == bfd_link_hash_defined && strncmp (h->root.string, string, sl) == 0 && h->root.string[sl] == '@') - { - pe_undef_found_sym = h; - return false; - } + { + pe_undef_found_sym = h; + return false; + } return true; } @@ -713,6 +756,11 @@ pe_fixup_stdcalls () static int gave_warning_message = 0; struct bfd_link_hash_entry *undef, *sym; char *at; + if (pe_dll_extra_pe_debug) + { + printf ("%s\n", __FUNCTION__); + } + for (undef = link_info.hash->undefs; undef; undef=undef->next) if (undef->type == bfd_link_hash_undefined) { @@ -771,16 +819,127 @@ pe_fixup_stdcalls () } } } + +static int +make_import_fixup (rel) + arelent *rel; +{ + struct symbol_cache_entry *sym = *rel->sym_ptr_ptr; +/* + bfd *b; +*/ + + if (pe_dll_extra_pe_debug) + { + printf ("arelent: %s@%#x: add=%li\n", sym->name, + (int) rel->address, rel->addend); + } + pe_create_import_fixup (rel); + return 1; +} + +char *pe_data_import_dll; + +static void +pe_find_data_imports () +{ + struct bfd_link_hash_entry *undef, *sym; + for (undef = link_info.hash->undefs; undef; undef=undef->next) + { + if (undef->type == bfd_link_hash_undefined) + { + /* C++ symbols are *long* */ + char buf[4096]; + if (pe_dll_extra_pe_debug) + { + printf ("%s:%s\n", __FUNCTION__, undef->root.string); + } + sprintf (buf, "__imp_%s", undef->root.string); + + sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); + if (sym && sym->type == bfd_link_hash_defined) + { + einfo (_("Warning: resolving %s by linking to %s (auto-import)\n"), + undef->root.string, buf); + { + bfd *b = sym->u.def.section->owner; + asymbol **symbols; + int nsyms, symsize, i; + + symsize = bfd_get_symtab_upper_bound (b); + symbols = (asymbol **) xmalloc (symsize); + nsyms = bfd_canonicalize_symtab (b, symbols); + + for (i = 0; i < nsyms; i++) + { + if (memcmp(symbols[i]->name, "__head_", + sizeof ("__head_") - 1)) + continue; + if (pe_dll_extra_pe_debug) + { + printf ("->%s\n", symbols[i]->name); + } + pe_data_import_dll = (char*) (symbols[i]->name + + sizeof ("__head_") - 1); + break; + } + } + + pe_walk_relocs_of_symbol (&link_info, undef->root.string, + make_import_fixup); + + /* let's differentiate it somehow from defined */ + undef->type = bfd_link_hash_defweak; + /* we replace original name with __imp_ prefixed, this + 1) may trash memory 2) leads to duplicate symbol generation. + Still, IMHO it's better than having name poluted. */ + undef->root.string = sym->root.string; + undef->u.def.value = sym->u.def.value; + undef->u.def.section = sym->u.def.section; + } + } + } +} #endif /* DLL_SUPPORT */ +static boolean +pr_sym (h, string) + struct bfd_hash_entry *h; + PTR string; +{ + if (pe_dll_extra_pe_debug) + { + printf("+%s\n",h->string); + } + return true; +} + + static void gld_${EMULATION_NAME}_after_open () { + + if (pe_dll_extra_pe_debug) + { + bfd *a; + struct bfd_link_hash_entry *sym; + printf ("%s()\n", __FUNCTION__); + + for (sym = link_info.hash->undefs; sym; sym=sym->next) + printf ("-%s\n", sym->root.string); + bfd_hash_traverse (&link_info.hash->table, pr_sym,NULL); + + for (a = link_info.input_bfds; a; a = a->link_next) + { + printf("*%s\n",a->filename); + } + } + /* Pass the wacky PE command line options into the output bfd. FIXME: This should be done via a function, rather than by including an internal BFD header. */ - if (!coff_data (output_bfd)->pe) + if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == NULL) einfo (_("%F%P: PE operations on non PE file.\n")); pe_data (output_bfd)->pe_opthdr = pe; @@ -790,6 +949,8 @@ gld_${EMULATION_NAME}_after_open () if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ pe_fixup_stdcalls (); + pe_find_data_imports (output_bfd, &link_info); + pe_process_import_defs(output_bfd, &link_info); if (link_info.shared) pe_dll_build_sections (output_bfd, &link_info); @@ -839,7 +1000,8 @@ gld_${EMULATION_NAME}_after_open () { int idata2 = 0, reloc_count=0, is_imp = 0; asection *sec; - /* See if this is an import library thunk */ + + /* See if this is an import library thunk. */ for (sec = is->the_bfd->sections; sec; sec = sec->next) { if (strcmp (sec->name, ".idata\$2") == 0) @@ -848,46 +1010,83 @@ gld_${EMULATION_NAME}_after_open () is_imp = 1; reloc_count += sec->reloc_count; } + if (is_imp && !idata2 && reloc_count) { - /* it is, look for the reference to head and see if it's - from our own library */ + /* It is, look for the reference to head and see if it's + from our own library. */ for (sec = is->the_bfd->sections; sec; sec = sec->next) { int i; - int symsize = bfd_get_symtab_upper_bound (is->the_bfd); - asymbol **symbols = (asymbol **) xmalloc (symsize); - int relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec); - arelent **relocs = (arelent **) xmalloc ((size_t) relsize); - int nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec, + long symsize; + long relsize; + asymbol **symbols; + arelent **relocs; + int nrelocs; + + symsize = bfd_get_symtab_upper_bound (is->the_bfd); + if (symsize < 1) + break; + relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec); + if (relsize < 1) + break; + + symbols = (asymbol **) xmalloc (symsize); + symsize = bfd_canonicalize_symtab (is->the_bfd, symbols); + if (symsize < 0) + { + einfo ("%X%P: unable to process symbols: %E"); + return; + } + + relocs = (arelent **) xmalloc ((size_t) relsize); + nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec, relocs, symbols); - for (i=0; isym_ptr_ptr)[0]; - if (!s->flags & BSF_LOCAL) - { - /* thunk section with reloc to another bfd... */ - struct bfd_link_hash_entry *blhe; - blhe = bfd_link_hash_lookup (link_info.hash, - s->name, - false, false, true); - if (blhe && blhe->type == bfd_link_hash_defined) - { - bfd *other_bfd = blhe->u.def.section->owner; - if (strcmp (is->the_bfd->my_archive->filename, - other_bfd->my_archive->filename)) - { - /* Rename this implib to match the other */ - char *n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1); - strcpy (n, other_bfd->my_archive->filename); - is->the_bfd->my_archive->filename = n; - } - } - } + + if (s->flags & BSF_LOCAL) + continue; + + /* Thunk section with reloc to another bfd. */ + blhe = bfd_link_hash_lookup (link_info.hash, + s->name, + false, false, true); + + if (blhe == NULL + || blhe->type != bfd_link_hash_defined) + continue; + + other_bfd = blhe->u.def.section->owner; + + if (strcmp (is->the_bfd->my_archive->filename, + other_bfd->my_archive->filename) == 0) + continue; + + /* Rename this implib to match the other. */ + n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1); + + strcpy (n, other_bfd->my_archive->filename); + + is->the_bfd->my_archive->filename = n; } free (relocs); + /* Note - we do not free the symbols, + they are now cached in the BFD. */ } } } @@ -1193,6 +1392,16 @@ gld_${EMULATION_NAME}_finish () if (pe_out_def_filename) pe_dll_generate_def_file (pe_out_def_filename); #endif /* DLL_SUPPORT */ + + /* I don't know where .idata gets set as code, but it shouldn't be */ + { + asection *asec = bfd_get_section_by_name (output_bfd, ".idata"); + if (asec) + { + asec->flags &= ~SEC_CODE; + asec->flags |= SEC_DATA; + } + } } @@ -1225,6 +1434,7 @@ gld_${EMULATION_NAME}_place_orphan (file, s) const char *secname; char *hold_section_name; char *dollar = NULL; + const char *ps = NULL; lang_output_section_statement_type *os; lang_statement_list_type add_child; @@ -1248,7 +1458,7 @@ gld_${EMULATION_NAME}_place_orphan (file, s) && os->bfd_section != NULL && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) { - wild_doit (&add_child, s, os, file); + lang_add_section (&add_child, s, os, file); } else { @@ -1316,6 +1526,26 @@ gld_${EMULATION_NAME}_place_orphan (file, s) stat_ptr = &add; lang_list_init (stat_ptr); + if (config.build_constructors) + { + /* If the name of the section is representable in C, then create + symbols to mark the start and the end of the section. */ + for (ps = outsecname; *ps != '\0'; ps++) + if (! isalnum ((unsigned char) *ps) && *ps != '_') + break; + if (*ps == '\0') + { + char *symname; + etree_type *e_align; + + symname = (char *) xmalloc (ps - outsecname + sizeof "___start_"); + sprintf (symname, "___start_%s", outsecname); + e_align = exp_unop (ALIGN_K, + exp_intop ((bfd_vma) 1 << s->alignment_power)); + lang_add_assignment (exp_assop ('=', symname, e_align)); + } + } + if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) address = exp_intop ((bfd_vma) 0); else @@ -1332,12 +1562,27 @@ gld_${EMULATION_NAME}_place_orphan (file, s) (etree_type *) NULL, (etree_type *) NULL); - wild_doit (&add_child, s, os, file); + lang_add_section (&add_child, s, os, file); lang_leave_output_section_statement ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL, "*default*"); + if (config.build_constructors && *ps == '\0') + { + char *symname; + + /* lang_leave_ouput_section_statement resets stat_ptr. Put + stat_ptr back where we want it. */ + if (place != NULL) + stat_ptr = &add; + + symname = (char *) xmalloc (ps - outsecname + sizeof "___stop_"); + sprintf (symname, "___stop_%s", outsecname); + lang_add_assignment (exp_assop ('=', symname, + exp_nameop (NAME, "."))); + } + stat_ptr = old; if (place != NULL)