X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=ld%2Femultempl%2Fpe.em;h=fe65d2b266e5c49ad521a5a49078061e81fef146;hb=607b483327fdfc75fb193870b3c4e7445ce3f64d;hp=ec893b9e5e4836674aeb396cdde8d1d9115ccac3;hpb=522f09cd4c88911ec7e2c6a8a9a8375af605be21;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index ec893b9e5e..fe65d2b266 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -8,8 +8,7 @@ fi rm -f e${EMULATION_NAME}.c (echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) fragment < Set the entry point to be Thumb \n")); + fprintf (file, _(" --[no-]insert-timestamp Use a real timestamp rather than zero (default).\n")); + fprintf (file, _(" This makes binaries non-deterministic\n")); #ifdef DLL_SUPPORT fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n")); @@ -419,18 +453,18 @@ gld_${EMULATION_NAME}_list_options (FILE *file) fprintf (file, _(" export, place into import library instead.\n")); fprintf (file, _(" --export-all-symbols Automatically export all globals to DLL\n")); fprintf (file, _(" --kill-at Remove @nn from exported symbols\n")); - fprintf (file, _(" --out-implib Generate import library\n")); fprintf (file, _(" --output-def Generate a .DEF file for the built DLL\n")); - fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n")); + fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports\n")); fprintf (file, _(" --compat-implib Create backward compatible import libs;\n\ create __imp_ as well.\n")); - fprintf (file, _(" --enable-auto-image-base Automatically choose image base for DLLs\n\ - unless user specifies one\n")); + fprintf (file, _(" --enable-auto-image-base[=
] Automatically choose image base for DLLs\n\ + (optionally starting with address) unless\n\ + specifically set with --image-base\n")); fprintf (file, _(" --disable-auto-image-base Do not auto-choose image base. (default)\n")); fprintf (file, _(" --dll-search-prefix= When linking dynamically to a dll without\n\ an importlib, use .dll\n\ in preference to lib.dll \n")); - fprintf (file, _(" --enable-auto-import Do sophistcated linking of _sym to\n\ + fprintf (file, _(" --enable-auto-import Do sophisticated linking of _sym to\n\ __imp_sym for DATA references\n")); fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n")); fprintf (file, _(" --enable-runtime-pseudo-reloc Work around auto-import limitations by\n\ @@ -443,20 +477,24 @@ gld_${EMULATION_NAME}_list_options (FILE *file) #endif fprintf (file, _(" --large-address-aware Executable supports virtual addresses\n\ greater than 2 gigabytes\n")); + fprintf (file, _(" --disable-large-address-aware Executable does not support virtual\n\ + addresses greater than 2 gigabytes\n")); fprintf (file, _(" --enable-long-section-names Use long COFF section names even in\n\ executable image files\n")); fprintf (file, _(" --disable-long-section-names Never use long COFF section names, even\n\ in object files\n")); - fprintf (file, _(" --dynamicbase Image base address may be relocated using\n\ - address space layout randomization (ASLR)\n")); - fprintf (file, _(" --forceinteg Code integrity checks are enforced\n")); - fprintf (file, _(" --nxcompat Image is compatible with data execution prevention\n")); - fprintf (file, _(" --no-isolation Image understands isolation but do not isolate the image\n")); - fprintf (file, _(" --no-seh Image does not use SEH. No SE handler may\n\ - be called in this image\n")); - fprintf (file, _(" --no-bind Do not bind this image\n")); - fprintf (file, _(" --wdmdriver Driver uses the WDM model\n")); + fprintf (file, _(" --dynamicbase Image base address may be relocated using\n\ + address space layout randomization (ASLR)\n")); + fprintf (file, _(" --enable-reloc-section Create the base relocation table\n")); + fprintf (file, _(" --forceinteg Code integrity checks are enforced\n")); + fprintf (file, _(" --nxcompat Image is compatible with data execution prevention\n")); + fprintf (file, _(" --no-isolation Image understands isolation but do not isolate the image\n")); + fprintf (file, _(" --no-seh Image does not use SEH. No SE handler may\n\ + be called in this image\n")); + fprintf (file, _(" --no-bind Do not bind this image\n")); + fprintf (file, _(" --wdmdriver Driver uses the WDM model\n")); fprintf (file, _(" --tsaware Image is Terminal Server aware\n")); + fprintf (file, _(" --build-id[=STYLE] Generate build ID\n")); } @@ -464,6 +502,7 @@ static void set_pe_name (char *name, long val) { int i; + is_underscoring (); /* Find the name and set it. */ for (i = 0; init[i].ptr; i++) @@ -485,13 +524,13 @@ set_entry_point (void) { const char *entry; const char *initial_symbol_char; - int i, u = -1; + int i; static const struct - { - const int value; - const char *entry; - } + { + const int value; + const char *entry; + } v[] = { { 1, "NtProcessStartup" }, @@ -506,7 +545,7 @@ set_entry_point (void) /* Entry point name for arbitrary subsystem numbers. */ static const char default_entry[] = "mainCRTStartup"; - if (link_info.shared || dll) + if (bfd_link_pic (&link_info) || dll) { #if defined (TARGET_IS_i386pe) entry = "DllMainCRTStartup@12"; @@ -516,30 +555,18 @@ set_entry_point (void) } else { - for (i = 0; v[i].entry; i++) - if (v[i].value == pe_subsystem) - break; + if (v[i].value == pe_subsystem) + break; /* If no match, use the default. */ if (v[i].entry != NULL) - entry = v[i].entry; + entry = v[i].entry; else - entry = default_entry; + entry = default_entry; } - /* Now we check target's default for getting proper symbol_char. */ - u = pe_leading_underscore; - if (u == -1 && !bfd_get_target_info ("${OUTPUT_FORMAT}", NULL, NULL, &u, NULL)) - bfd_get_target_info ("${RELOCATEABLE_OUTPUT_FORMAT}", NULL, NULL, &u, NULL); - - if (u == 0) - initial_symbol_char = ""; - else if (u != -1) - initial_symbol_char = "_"; - else - abort (); - pe_leading_underscore = u; + initial_symbol_char = (is_underscoring () != 0 ? "_" : ""); if (*initial_symbol_char != '\0') { @@ -620,7 +647,7 @@ set_pe_subsystem (void) if (v[i].name == NULL) { - einfo (_("%P%F: invalid subsystem type %s\n"), optarg); + einfo (_("%F%P: invalid subsystem type %s\n"), optarg); return; } @@ -641,7 +668,7 @@ set_pe_value (char *name) set_pe_name (name, strtoul (optarg, &end, 0)); if (end == optarg) - einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg); + einfo (_("%F%P: invalid hex number for PE parameter '%s'\n"), optarg); optarg = end; } @@ -658,9 +685,10 @@ set_pe_stack_heap (char *resname, char *comname) set_pe_value (comname); } else if (*optarg) - einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg); + einfo (_("%F%P: strange hex info for PE parameter '%s'\n"), optarg); } +#define DEFAULT_BUILD_ID_STYLE "md5" static bfd_boolean gld${EMULATION_NAME}_handle_option (int optc) @@ -673,12 +701,7 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_BASE_FILE: link_info.base_file = fopen (optarg, FOPEN_WB); if (link_info.base_file == NULL) - { - /* xgettext:c-format */ - fprintf (stderr, _("%s: Can't open base file %s\n"), - program_name, optarg); - xexit (1); - } + einfo (_("%F%P: cannot open base file %s\n"), optarg); break; /* PE options. */ @@ -736,6 +759,12 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_LEADING_UNDERSCORE: pe_leading_underscore = 1; break; + case OPTION_INSERT_TIMESTAMP: + insert_timestamp = TRUE; + break; + case OPTION_NO_INSERT_TIMESTAMP: + insert_timestamp = FALSE; + break; #ifdef DLL_SUPPORT case OPTION_OUT_DEF: pe_out_def_filename = xstrdup (optarg); @@ -767,9 +796,6 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_DISABLE_STDCALL_FIXUP: pe_enable_stdcall_fixup = 0; break; - case OPTION_IMPLIB_FILENAME: - pe_implib_filename = xstrdup (optarg); - break; case OPTION_WARN_DUPLICATE_EXPORTS: pe_dll_warn_dup_exports = 1; break; @@ -778,6 +804,12 @@ gld${EMULATION_NAME}_handle_option (int optc) break; case OPTION_ENABLE_AUTO_IMAGE_BASE: pe_enable_auto_image_base = 1; + if (optarg && *optarg) + { + char *end; + pe_auto_image_base = strtoul (optarg, &end, 0); + /* XXX should check that we actually parsed something */ + } break; case OPTION_DISABLE_AUTO_IMAGE_BASE: pe_enable_auto_image_base = 0; @@ -814,6 +846,9 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_LARGE_ADDRESS_AWARE: real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE; break; + case OPTION_DISABLE_LARGE_ADDRESS_AWARE: + real_flags &= ~ IMAGE_FILE_LARGE_ADDRESS_AWARE; + break; case OPTION_ENABLE_LONG_SECTION_NAMES: pe_use_coff_long_section_names = 1; break; @@ -823,6 +858,9 @@ gld${EMULATION_NAME}_handle_option (int optc) /* Get DLLCharacteristics bits */ case OPTION_DYNAMIC_BASE: pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; + /* fall through */ + case OPTION_ENABLE_RELOC_SECTION: + pe_dll_enable_reloc_section = 1; break; case OPTION_FORCE_INTEGRITY: pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; @@ -845,6 +883,17 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_TERMINAL_SERVER_AWARE: pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE; break; + case OPTION_BUILD_ID: + if (emit_build_id != NULL) + { + free ((char *) emit_build_id); + emit_build_id = NULL; + } + if (optarg == NULL) + optarg = DEFAULT_BUILD_ID_STYLE; + if (strcmp (optarg, "none")) + emit_build_id = xstrdup (optarg); + break; } /* Set DLLCharacteristics bits */ @@ -884,7 +933,7 @@ static unsigned long compute_dll_image_base (const char *ofile) { unsigned long hash = strhash (ofile); - return 0x61300000 + ((hash << 16) & 0x0FFC0000); + return pe_auto_image_base + ((hash << 16) & 0x0FFC0000); } #endif @@ -898,11 +947,13 @@ gld_${EMULATION_NAME}_set_symbols (void) names and insert the defaults. */ int j; + is_underscoring (); + if (!init[IMAGEBASEOFF].inited) { - if (link_info.relocatable) + if (bfd_link_relocatable (&link_info)) init[IMAGEBASEOFF].value = 0; - else if (init[DLLOFF].value || (link_info.shared && !link_info.pie)) + else if (init[DLLOFF].value || bfd_link_dll (&link_info)) { #ifdef DLL_SUPPORT init[IMAGEBASEOFF].value = (pe_enable_auto_image_base @@ -918,7 +969,7 @@ gld_${EMULATION_NAME}_set_symbols (void) } /* Don't do any symbol assignments if this is a relocatable link. */ - if (link_info.relocatable) + if (bfd_link_relocatable (&link_info)) return; /* Glue the assignments into the abs section. */ @@ -929,8 +980,8 @@ gld_${EMULATION_NAME}_set_symbols (void) long val = init[j].value; lang_assignment_statement_type *rv; - rv = lang_add_assignment (exp_assop ('=', GET_INIT_SYMBOL_NAME (j), - exp_intop (val))); + rv = lang_add_assignment (exp_assign (GET_INIT_SYMBOL_NAME (j), + exp_intop (val), FALSE)); if (init[j].size == sizeof (short)) *(short *) init[j].ptr = val; else if (init[j].size == sizeof (int)) @@ -949,7 +1000,7 @@ gld_${EMULATION_NAME}_set_symbols (void) if (pe.FileAlignment > pe.SectionAlignment) { - einfo (_("%P: warning, file alignment > section alignment.\n")); + einfo (_("%P: warning, file alignment > section alignment\n")); } } @@ -970,13 +1021,6 @@ gld_${EMULATION_NAME}_after_parse (void) after_parse_default (); } -/* pe-dll.c directly accesses pe_data_import_dll, - so it must be defined outside of #ifdef DLL_SUPPORT. - Note - this variable is deliberately not initialised. - This allows it to be treated as a common varaible, and only - exist in one incarnation in a multiple target enabled linker. */ -char * pe_data_import_dll; - #ifdef DLL_SUPPORT static struct bfd_link_hash_entry *pe_undef_found_sym; @@ -1000,10 +1044,38 @@ pe_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf) return TRUE; } +/* Change UNDEF to a defined symbol, taking data from SYM. */ + +static void +change_undef (struct bfd_link_hash_entry * undef, + struct bfd_link_hash_entry * sym) +{ + static bfd_boolean gave_warning_message = FALSE; + + undef->type = bfd_link_hash_defined; + undef->u.def.value = sym->u.def.value; + undef->u.def.section = sym->u.def.section; + + if (pe_enable_stdcall_fixup == -1) + { + einfo (_("%P: warning: resolving %s by linking to %s\n"), + undef->root.string, sym->root.string); + + if (! gave_warning_message) + { + einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); + einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); + gave_warning_message = TRUE; + } + } + + /* PR 19803: Make sure that the linked symbol is not garbage collected. */ + lang_add_gc_name (sym->root.string); +} + static void pe_fixup_stdcalls (void) { - static int gave_warning_message = 0; struct bfd_link_hash_entry *undef, *sym; if (pe_dll_extra_pe_debug) @@ -1012,196 +1084,247 @@ pe_fixup_stdcalls (void) for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next) if (undef->type == bfd_link_hash_undefined) { - char* at = strchr (undef->root.string, '@'); - int lead_at = (*undef->root.string == '@'); + const char * name = undef->root.string; + char * at; + int lead_at = (*name == '@'); + if (lead_at) - at = strchr (undef->root.string + 1, '@'); + at = strchr (name + 1, '@'); + else + at = strchr (name, '@'); if (at || lead_at) { /* The symbol is a stdcall symbol, so let's look for a cdecl symbol with the same name and resolve to that. */ - char *cname = xstrdup (undef->root.string); + char *cname = xstrdup (name); if (lead_at) *cname = '_'; - at = strchr (cname, '@'); if (at) - *at = 0; - sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); + * strchr (cname, '@') = 0; + sym = bfd_link_hash_lookup (link_info.hash, cname, FALSE, FALSE, TRUE); if (sym && sym->type == bfd_link_hash_defined) - { - undef->type = bfd_link_hash_defined; - undef->u.def.value = sym->u.def.value; - undef->u.def.section = sym->u.def.section; - - if (pe_enable_stdcall_fixup == -1) - { - einfo (_("Warning: resolving %s by linking to %s\n"), - undef->root.string, cname); - if (! gave_warning_message) - { - gave_warning_message = 1; - einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); - einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); - } - } - } + change_undef (undef, sym); } else { /* The symbol is a cdecl symbol, so we look for stdcall symbols - which means scanning the whole symbol table. */ - pe_undef_found_sym = 0; + pe_undef_found_sym = NULL; bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match, - (char *) undef->root.string); - sym = pe_undef_found_sym; - if (sym) - { - undef->type = bfd_link_hash_defined; - undef->u.def.value = sym->u.def.value; - undef->u.def.section = sym->u.def.section; - - if (pe_enable_stdcall_fixup == -1) - { - einfo (_("Warning: resolving %s by linking to %s\n"), - undef->root.string, sym->root.string); - if (! gave_warning_message) - { - gave_warning_message = 1; - einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); - einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); - } - } - } + (char *) name); + if (pe_undef_found_sym) + change_undef (undef, pe_undef_found_sym); } } } -static int -make_import_fixup (arelent *rel, asection *s) +static void +make_import_fixup (arelent *rel, asection *s, char *name, const char *symname) { struct bfd_symbol *sym = *rel->sym_ptr_ptr; char addend[4]; + bfd_vma _addend; if (pe_dll_extra_pe_debug) printf ("arelent: %s@%#lx: add=%li\n", sym->name, (unsigned long) rel->address, (long) rel->addend); if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend))) - einfo (_("%C: Cannot get section contents - auto-import exception\n"), + einfo (_("%P: %C: cannot get section contents - auto-import exception\n"), s->owner, s, rel->address); - pe_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend)); + _addend = bfd_get_32 (s->owner, addend); + pe_create_import_fixup (rel, s, _addend, name, symname); +} + +static bfd_boolean +pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED) +{ + printf ("+%s\n", h->string); - return 1; + return TRUE; } +#endif /* DLL_SUPPORT */ static void -pe_find_data_imports (void) +debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj) { - struct bfd_link_hash_entry *undef, *sym; + int *found = (int *) obj; + if (strncmp (".debug_", sect->name, sizeof (".debug_") - 1) == 0) + *found = 1; +} - if (link_info.pei386_auto_import == 0) - return; +static bfd_boolean +pecoff_checksum_contents (bfd *abfd, + void (*process) (const void *, size_t, void *), + void *arg) +{ + file_ptr filepos = (file_ptr) 0; - for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next) + while (1) { - if (undef->type == bfd_link_hash_undefined) - { - /* C++ symbols are *long*. */ - char buf[4096]; + unsigned char b; + int status; - if (pe_dll_extra_pe_debug) - printf ("%s:%s\n", __FUNCTION__, undef->root.string); + if (bfd_seek (abfd, filepos, SEEK_SET) != 0) + return 0; - 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) - { - bfd *b = sym->u.def.section->owner; - asymbol **symbols; - int nsyms, i; - - if (link_info.pei386_auto_import == -1) - { - static bfd_boolean warned = FALSE; - - info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"), - undef->root.string, buf); - - /* PR linker/4844. */ - if (! warned) - { - warned = TRUE; - einfo (_("%P: warning: auto-importing has been activated without --enable-auto-import specified on the command line.\n\ -This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.\n")); - } - } + status = bfd_bread (&b, (bfd_size_type) 1, abfd); + if (status < 1) + { + break; + } - if (!bfd_generic_link_read_symbols (b)) - { - einfo (_("%B%F: could not read symbols: %E\n"), b); - return; - } + (*process) (&b, 1, arg); + filepos += 1; + } - symbols = bfd_get_outsymbols (b); - nsyms = bfd_get_symcount (b); + return TRUE; +} - for (i = 0; i < nsyms; i++) +static bfd_boolean +write_build_id (bfd *abfd) +{ + struct pe_tdata *t = pe_data (abfd); + asection *asec; + struct bfd_link_order *link_order = NULL; + unsigned char *contents; + bfd_size_type size; + bfd_size_type build_id_size; + unsigned char *build_id; + + /* Find the section the .buildid output section has been merged info. */ + for (asec = abfd->sections; asec != NULL; asec = asec->next) + { + struct bfd_link_order *l = NULL; + for (l = asec->map_head.link_order; l != NULL; l = l->next) + { + if (l->type == bfd_indirect_link_order) + { + if (l->u.indirect.section == t->build_id.sec) { - if (! CONST_STRNEQ (symbols[i]->name, - U ("_head_"))) - continue; - - if (pe_dll_extra_pe_debug) - printf ("->%s\n", symbols[i]->name); - - pe_data_import_dll = (char *) (symbols[i]->name - + U_SIZE ("_head_") - 1); + link_order = l; 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; } } + + if (link_order) + break; } -} -static bfd_boolean -pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED) -{ - if (pe_dll_extra_pe_debug) - printf ("+%s\n", h->string); + if (!link_order) + { + einfo (_("%P: warning: .buildid section discarded," + " --build-id ignored\n")); + return TRUE; + } + + if (t->build_id.sec->contents == NULL) + t->build_id.sec->contents = (unsigned char *) xmalloc (t->build_id.sec->size); + contents = t->build_id.sec->contents; + size = t->build_id.sec->size; + + build_id_size = compute_build_id_size (t->build_id.style); + build_id = xmalloc (build_id_size); + generate_build_id (abfd, t->build_id.style, pecoff_checksum_contents, build_id, build_id_size); + + bfd_vma ib = pe_data (link_info.output_bfd)->pe_opthdr.ImageBase; + + /* Construct a debug directory entry which points to an immediately following CodeView record. */ + struct internal_IMAGE_DEBUG_DIRECTORY idd; + idd.Characteristics = 0; + idd.TimeDateStamp = 0; + idd.MajorVersion = 0; + idd.MinorVersion = 0; + idd.Type = PE_IMAGE_DEBUG_TYPE_CODEVIEW; + idd.SizeOfData = sizeof (CV_INFO_PDB70) + 1; + idd.AddressOfRawData = asec->vma - ib + link_order->offset + + sizeof (struct external_IMAGE_DEBUG_DIRECTORY); + idd.PointerToRawData = asec->filepos + link_order->offset + + sizeof (struct external_IMAGE_DEBUG_DIRECTORY); + + struct external_IMAGE_DEBUG_DIRECTORY *ext = (struct external_IMAGE_DEBUG_DIRECTORY *)contents; + _bfd_XXi_swap_debugdir_out (abfd, &idd, ext); + + /* Write the debug directory entry. */ + if (bfd_seek (abfd, asec->filepos + link_order->offset, SEEK_SET) != 0) + return 0; + + if (bfd_bwrite (contents, size, abfd) != size) + return 0; + + /* Construct the CodeView record. */ + CODEVIEW_INFO cvinfo; + cvinfo.CVSignature = CVINFO_PDB70_CVSIGNATURE; + cvinfo.Age = 1; + + /* Zero pad or truncate the generated build_id to fit in the CodeView record. */ + memset (&(cvinfo.Signature), 0, CV_INFO_SIGNATURE_LENGTH); + memcpy (&(cvinfo.Signature), build_id, (build_id_size > CV_INFO_SIGNATURE_LENGTH) + ? CV_INFO_SIGNATURE_LENGTH : build_id_size); + + free (build_id); + + /* Write the codeview record. */ + if (_bfd_XXi_write_codeview_record (abfd, idd.PointerToRawData, &cvinfo) == 0) + return 0; + + /* Record the location of the debug directory in the data directory. */ + pe_data (link_info.output_bfd)->pe_opthdr.DataDirectory[PE_DEBUG_DATA].VirtualAddress + = asec->vma - ib + link_order->offset; + pe_data (link_info.output_bfd)->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size + = sizeof (struct external_IMAGE_DEBUG_DIRECTORY); return TRUE; } -#endif /* DLL_SUPPORT */ -static void -debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj) +/* Make .buildid section, and set up coff_tdata->build_id. */ +static bfd_boolean +setup_build_id (bfd *ibfd) { - int *found = (int *) obj; - if (strncmp (".debug_", sect->name, sizeof (".debug_") - 1) == 0) - *found = 1; + asection *s; + flagword flags; + + if (!validate_build_id_style (emit_build_id)) + { + einfo (_("%P: warning: unrecognized --build-id style ignored\n")); + return FALSE; + } + + flags = (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY + | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA); + s = bfd_make_section_anyway_with_flags (ibfd, ".buildid", flags); + if (s != NULL) + { + struct pe_tdata *t = pe_data (link_info.output_bfd); + t->build_id.after_write_object_contents = &write_build_id; + t->build_id.style = emit_build_id; + t->build_id.sec = s; + + /* Section is a fixed size: + One IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW, + pointing at a CV_INFO_PDB70 record containing the build-id, with a + null byte for PdbFileName. */ + s->size = sizeof (struct external_IMAGE_DEBUG_DIRECTORY) + + sizeof (CV_INFO_PDB70) + 1; + + return TRUE; + } + + einfo (_("%P: warning: cannot create .buildid section," + " --build-id ignored\n")); + return FALSE; } static void gld_${EMULATION_NAME}_after_open (void) { + after_open_default (); + #ifdef DLL_SUPPORT if (pe_dll_extra_pe_debug) { @@ -1214,23 +1337,48 @@ gld_${EMULATION_NAME}_after_open (void) 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); + for (a = link_info.input_bfds; a; a = a->link.next) + printf ("*%s\n", bfd_get_filename (a)); } #endif + if (emit_build_id != NULL) + { + bfd *abfd; + + /* Find a COFF input. */ + for (abfd = link_info.input_bfds; + abfd != (bfd *) NULL; abfd = abfd->link.next) + if (bfd_get_flavour (abfd) == bfd_target_coff_flavour) + break; + + /* If there are no COFF input files do not try to + add a build-id section. */ + if (abfd == NULL + || !setup_build_id (abfd)) + { + free ((char *) emit_build_id); + emit_build_id = NULL; + } + } + /* 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 (link_info.output_bfd) == NULL + if (bfd_get_flavour (link_info.output_bfd) != bfd_target_coff_flavour + || coff_data (link_info.output_bfd) == NULL || coff_data (link_info.output_bfd)->pe == 0) - einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"), + einfo (_("%F%P: cannot perform PE operations on non PE output file '%pB'\n"), link_info.output_bfd); pe_data (link_info.output_bfd)->pe_opthdr = pe; pe_data (link_info.output_bfd)->dll = init[DLLOFF].value; pe_data (link_info.output_bfd)->real_flags |= real_flags; + if (insert_timestamp) + pe_data (link_info.output_bfd)->timestamp = -1; + else + pe_data (link_info.output_bfd)->timestamp = 0; /* At this point we must decide whether to use long section names in the output or not. If the user hasn't explicitly specified @@ -1240,57 +1388,62 @@ gld_${EMULATION_NAME}_after_open (void) find it, so enable it in that case. */ if (pe_use_coff_long_section_names < 0 && link_info.strip == strip_none) { - /* Iterate over all sections of all input BFDs, checking - for any that begin 'debug_' and are long names. */ - LANG_FOR_EACH_INPUT_STATEMENT (is) + if (bfd_link_relocatable (&link_info)) + pe_use_coff_long_section_names = 1; + else { - int found_debug = 0; - bfd_map_over_sections (is->the_bfd, debug_section_p, &found_debug); - if (found_debug) - { - pe_use_coff_long_section_names = 1; - break; - } + /* Iterate over all sections of all input BFDs, checking + for any that begin 'debug_' and are long names. */ + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + int found_debug = 0; + + bfd_map_over_sections (is->the_bfd, debug_section_p, &found_debug); + if (found_debug) + { + pe_use_coff_long_section_names = 1; + break; + } + } } } pe_output_file_set_long_section_names (link_info.output_bfd); #ifdef DLL_SUPPORT - if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ - pe_fixup_stdcalls (); - pe_process_import_defs (link_info.output_bfd, &link_info); - pe_find_data_imports (); + if (link_info.pei386_auto_import) /* -1=warn or 1=enable */ + pe_find_data_imports (U ("_head_"), make_import_fixup); - /* As possibly new symbols are added by imports, we rerun - stdcall/fastcall fixup here. */ - if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ + /* The implementation of the feature is rather dumb and would cause the + compilation time to go through the roof if there are many undefined + symbols in the link, so it needs to be run after auto-import. */ + if (pe_enable_stdcall_fixup) /* -1=warn or 1=enable */ pe_fixup_stdcalls (); #if defined (TARGET_IS_i386pe) \ || defined (TARGET_IS_armpe) \ - || defined (TARGET_IS_arm_epoc_pe) \ || defined (TARGET_IS_arm_wince_pe) - if (!link_info.relocatable) + if (!bfd_link_relocatable (&link_info)) pe_dll_build_sections (link_info.output_bfd, &link_info); #else - if (link_info.shared) + if (bfd_link_pic (&link_info)) pe_dll_build_sections (link_info.output_bfd, &link_info); else pe_exe_build_sections (link_info.output_bfd, &link_info); #endif #endif /* DLL_SUPPORT */ -#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) +#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe) if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL) { /* The arm backend needs special fields in the output hash structure. These will only be created if the output format is an arm format, hence we do not support linking and changing output formats at the same time. Use a link followed by objcopy to change output formats. */ - einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n"); + einfo (_("%F%P: error: cannot change output format " + "whilst linking %s binaries\n"), "ARM"); return; } { @@ -1349,7 +1502,7 @@ gld_${EMULATION_NAME}_after_open (void) if (!bfd_generic_link_read_symbols (is->the_bfd)) { - einfo (_("%B%F: could not read symbols: %E\n"), + einfo (_("%F%P: %pB: could not read symbols: %E\n"), is->the_bfd); return; } @@ -1361,7 +1514,7 @@ gld_${EMULATION_NAME}_after_open (void) if (nrelocs < 0) { free (relocs); - einfo ("%X%P: unable to process relocs: %E\n"); + einfo (_("%X%P: unable to process relocs: %E\n")); return; } @@ -1369,7 +1522,7 @@ gld_${EMULATION_NAME}_after_open (void) { struct bfd_symbol *s; struct bfd_link_hash_entry * blhe; - char *other_bfd_filename; + const char *other_bfd_filename; char *n; s = (relocs[i]->sym_ptr_ptr)[0]; @@ -1391,14 +1544,15 @@ gld_${EMULATION_NAME}_after_open (void) ? bfd_get_filename (blhe->u.def.section->owner->my_archive) : bfd_get_filename (blhe->u.def.section->owner); - if (strcmp (bfd_get_filename (is->the_bfd->my_archive), - other_bfd_filename) == 0) + if (filename_cmp (bfd_get_filename + (is->the_bfd->my_archive), + other_bfd_filename) == 0) continue; /* Rename this implib to match the other one. */ n = xmalloc (strlen (other_bfd_filename) + 1); strcpy (n, other_bfd_filename); - is->the_bfd->my_archive->filename = n; + bfd_set_filename (is->the_bfd->my_archive, n); } free (relocs); @@ -1445,8 +1599,8 @@ gld_${EMULATION_NAME}_after_open (void) members, so look for the first element with a .dll extension, and use that for the remainder of the comparisons. */ - pnt = strrchr (is3->the_bfd->filename, '.'); - if (pnt != NULL && strcmp (pnt, ".dll") == 0) + pnt = strrchr (bfd_get_filename (is3->the_bfd), '.'); + if (pnt != NULL && filename_cmp (pnt, ".dll") == 0) break; } @@ -1462,12 +1616,12 @@ gld_${EMULATION_NAME}_after_open (void) { /* Skip static members, ie anything with a .obj extension. */ - pnt = strrchr (is2->the_bfd->filename, '.'); - if (pnt != NULL && strcmp (pnt, ".obj") == 0) + pnt = strrchr (bfd_get_filename (is2->the_bfd), '.'); + if (pnt != NULL && filename_cmp (pnt, ".obj") == 0) continue; - if (strcmp (is3->the_bfd->filename, - is2->the_bfd->filename)) + if (filename_cmp (bfd_get_filename (is3->the_bfd), + bfd_get_filename (is2->the_bfd))) { is_ms_arch = 0; break; @@ -1479,9 +1633,9 @@ gld_${EMULATION_NAME}_after_open (void) /* This fragment might have come from an .obj file in a Microsoft import, and not an actual import record. If this is the case, then leave the filename alone. */ - pnt = strrchr (is->the_bfd->filename, '.'); + pnt = strrchr (bfd_get_filename (is->the_bfd), '.'); - if (is_ms_arch && (strcmp (pnt, ".dll") == 0)) + if (is_ms_arch && (filename_cmp (pnt, ".dll") == 0)) { int idata2 = 0, reloc_count=0; asection *sec; @@ -1501,13 +1655,28 @@ gld_${EMULATION_NAME}_after_open (void) else /* sentinel */ seq = 'c'; - new_name = xmalloc (strlen (is->the_bfd->filename) + 3); - sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); - is->the_bfd->filename = new_name; - - new_name = xmalloc (strlen (is->filename) + 3); - sprintf (new_name, "%s.%c", is->filename, seq); - is->filename = new_name; + /* PR 25993: It is possible that is->the_bfd-filename == is->filename. + In which case calling bfd_set_filename on one will free the memory + pointed to by the other. */ + if (is->filename == bfd_get_filename (is->the_bfd)) + { + new_name = xmalloc (strlen (is->filename) + 3); + sprintf (new_name, "%s.%c", is->filename, seq); + bfd_set_filename (is->the_bfd, new_name); + is->filename = new_name; + } + else + { + new_name + = xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3); + sprintf (new_name, "%s.%c", + bfd_get_filename (is->the_bfd), seq); + bfd_set_filename (is->the_bfd, new_name); + + new_name = xmalloc (strlen (is->filename) + 3); + sprintf (new_name, "%s.%c", is->filename, seq); + is->filename = new_name; + } } } } @@ -1555,7 +1724,7 @@ gld_${EMULATION_NAME}_after_open (void) if (!bfd_generic_link_read_symbols (is->the_bfd)) { - einfo (_("%B%F: could not read symbols: %E\n"), + einfo (_("%F%P: %pB: could not read symbols: %E\n"), is->the_bfd); return; } @@ -1574,8 +1743,10 @@ gld_${EMULATION_NAME}_after_open (void) /* If the symbol in the stub section has no other undefined references, exclude the stub section from the final link. */ - if (blhe && (blhe->type == bfd_link_hash_defined) - && (blhe->u.undef.next == NULL)) + if (blhe != NULL + && blhe->type == bfd_link_hash_defined + && blhe->u.undef.next == NULL + && blhe != link_info.hash->undefs_tail) stub_sec->flags |= SEC_EXCLUDE; } } @@ -1596,7 +1767,7 @@ gld_${EMULATION_NAME}_before_allocation (void) if (!ppc_process_before_allocation (is->the_bfd, &link_info)) { /* xgettext:c-format */ - einfo (_("Errors encountered processing file %s\n"), is->filename); + einfo (_("%P: errors encountered processing file %s\n"), is->filename); } } } @@ -1605,7 +1776,7 @@ gld_${EMULATION_NAME}_before_allocation (void) ppc_allocate_toc_section (&link_info); #endif /* TARGET_IS_ppcpe */ -#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) +#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe) /* FIXME: we should be able to set the size of the interworking stub section. @@ -1619,7 +1790,7 @@ gld_${EMULATION_NAME}_before_allocation (void) (is->the_bfd, & link_info, support_old_code)) { /* xgettext:c-format */ - einfo (_("Errors encountered processing file %s for interworking\n"), + einfo (_("%P: errors encountered processing file %s for interworking\n"), is->filename); } } @@ -1627,7 +1798,7 @@ gld_${EMULATION_NAME}_before_allocation (void) /* We have seen it all. Allocate it, and carry on. */ bfd_arm_allocate_interworking_sections (& link_info); -#endif /* TARGET_IS_armpe || TARGET_IS_arm_epoc_pe || TARGET_IS_arm_wince_pe */ +#endif /* TARGET_IS_armpe || TARGET_IS_arm_wince_pe */ before_allocation_default (); } @@ -1654,7 +1825,7 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB #ifdef DLL_SUPPORT const char *ext = entry->filename + strlen (entry->filename) - 4; - if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0) + if (filename_cmp (ext, ".def") == 0 || filename_cmp (ext, ".DEF") == 0) { pe_def_file = def_file_parse (entry->filename, pe_def_file); @@ -1677,11 +1848,11 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB struct bfd_link_hash_entry *h; sprintf (buf, "%s%s", U (""), - pe_def_file->exports[i].internal_name); + pe_def_file->exports[i].internal_name); h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE); if (h == (struct bfd_link_hash_entry *) NULL) - einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); + einfo (_("%F%P: bfd_link_hash_lookup failed: %E\n")); if (h->type == bfd_link_hash_new) { h->type = bfd_link_hash_undefined; @@ -1693,7 +1864,7 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB /* def_file_print (stdout, pe_def_file); */ if (pe_def_file->is_dll == 1) - link_info.shared = 1; + link_info.type = type_dll; if (pe_def_file->base_address != (bfd_vma)(-1)) { @@ -1703,8 +1874,9 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB = pe_def_file->base_address; init[IMAGEBASEOFF].inited = 1; if (image_base_statement) - image_base_statement->exp = exp_assop ('=', "__image_base__", - exp_intop (pe.ImageBase)); + image_base_statement->exp + = exp_assign ("__image_base__", exp_intop (pe.ImageBase), + FALSE); } if (pe_def_file->stack_reserve != -1 @@ -1738,15 +1910,9 @@ gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUT #ifdef TARGET_IS_shpe pe_dll_id_target ("pei-shl"); #endif -#ifdef TARGET_IS_mipspe - pe_dll_id_target ("pei-mips"); -#endif #ifdef TARGET_IS_armpe pe_dll_id_target ("pei-arm-little"); #endif -#ifdef TARGET_IS_arm_epoc_pe - pe_dll_id_target ("epoc-pei-arm-little"); -#endif #ifdef TARGET_IS_arm_wince_pe pe_dll_id_target ("pei-arm-wince-little"); #endif @@ -1759,7 +1925,7 @@ gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUT static void gld_${EMULATION_NAME}_finish (void) { -#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) +#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe) struct bfd_link_hash_entry * h; if (thumb_entry_symbol != NULL) @@ -1778,8 +1944,7 @@ gld_${EMULATION_NAME}_finish (void) /* Special procesing is required for a Thumb entry symbol. The bottom bit of its address must be set. */ val = (h->u.def.value - + bfd_get_section_vma (link_info.output_bfd, - h->u.def.section->output_section) + + bfd_section_vma (h->u.def.section->output_section) + h->u.def.section->output_offset); val |= 1; @@ -1799,22 +1964,25 @@ gld_${EMULATION_NAME}_finish (void) else einfo (_("%P: warning: cannot find thumb start symbol %s\n"), thumb_entry_symbol); } -#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) */ +#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe) */ finish_default (); #ifdef DLL_SUPPORT - if (link_info.shared -#if !defined(TARGET_IS_shpe) && !defined(TARGET_IS_mipspe) - || (!link_info.relocatable && pe_def_file->num_exports != 0) + if (bfd_link_pic (&link_info) +#if !defined(TARGET_IS_shpe) + || pe_dll_enable_reloc_section + || (!bfd_link_relocatable (&link_info) + && pe_def_file->num_exports != 0) #endif ) { pe_dll_fill_sections (link_info.output_bfd, &link_info); - if (pe_implib_filename) - pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info); + if (command_line.out_implib_filename) + pe_dll_generate_implib (pe_def_file, command_line.out_implib_filename, + &link_info); } -#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) +#if defined(TARGET_IS_shpe) /* ARM doesn't need relocs. */ else { @@ -1865,7 +2033,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, lang_statement_union_type **pl; /* Look through the script to see where to place this section. */ - if (!link_info.relocatable + if (!bfd_link_relocatable (&link_info) && (dollar = strchr (secname, '\$')) != NULL) { size_t len = dollar - secname; @@ -1897,7 +2065,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, If the section already exists but does not have any flags set, then it has been created by the linker, probably as a result of a --section-start command line switch. */ - lang_add_section (&add_child, s, os); + lang_add_section (&add_child, s, NULL, os); break; } @@ -1911,7 +2079,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, unused one and use that. */ if (os == NULL && match_by_name) { - lang_add_section (&match_by_name->children, s, match_by_name); + lang_add_section (&match_by_name->children, s, NULL, match_by_name); return match_by_name; } @@ -1922,6 +2090,9 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, { ".text", SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE, 0, 0, 0, 0 }, + { ".idata", + SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, + 0, 0, 0, 0 }, { ".rdata", SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, 0, 0, 0, 0 }, @@ -1935,6 +2106,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, enum orphan_save_index { orphan_text = 0, + orphan_idata, orphan_rodata, orphan_data, orphan_bss @@ -1943,6 +2115,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, struct orphan_save *place; lang_output_section_statement_type *after; etree_type *address; + flagword flags; + asection *nexts; if (!orphan_init_done) { @@ -1957,18 +2131,37 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, orphan_init_done = 1; } + flags = s->flags; + if (!bfd_link_relocatable (&link_info)) + { + nexts = s; + while ((nexts = bfd_get_next_section_by_name (nexts->owner, + nexts))) + if (nexts->output_section == NULL + && (nexts->flags & SEC_EXCLUDE) == 0 + && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0 + && (nexts->owner->flags & DYNAMIC) == 0 + && !bfd_input_just_syms (nexts->owner)) + flags = (((flags ^ SEC_READONLY) + | (nexts->flags ^ SEC_READONLY)) + ^ SEC_READONLY); + } + /* Try to put the new output section in a reasonable place based on the section name and section flags. */ place = NULL; - if ((s->flags & SEC_ALLOC) == 0) + if ((flags & SEC_ALLOC) == 0) ; - else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) + else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) place = &hold[orphan_bss]; - else if ((s->flags & SEC_READONLY) == 0) + else if ((flags & SEC_READONLY) == 0) place = &hold[orphan_data]; - else if ((s->flags & SEC_CODE) == 0) - place = &hold[orphan_rodata]; + else if ((flags & SEC_CODE) == 0) + { + place = (!strncmp (secname, ".idata\$", 7) ? &hold[orphan_idata] + : &hold[orphan_rodata]); + } else place = &hold[orphan_text]; @@ -1979,17 +2172,24 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, place->os = lang_output_section_find (place->name); after = place->os; if (after == NULL) - after = lang_output_section_find_by_flags (s, &place->os, NULL); + after = lang_output_section_find_by_flags (s, flags, &place->os, + NULL); if (after == NULL) /* *ABS* is always the first output section statement. */ - after = (&lang_output_section_statement.head - ->output_section_statement); + after = (void *) lang_os_list.head; } - /* All sections in an executable must be aligned to a page boundary. */ + /* All sections in an executable must be aligned to a page boundary. + In a relocatable link, just preserve the incoming alignment; the + address is discarded by lang_insert_orphan in that case, anyway. */ address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__")); os = lang_insert_orphan (s, secname, constraint, after, place, address, &add_child); + if (bfd_link_relocatable (&link_info)) + { + os->section_alignment = exp_intop (1U << s->alignment_power); + os->bfd_section->alignment_power = s->alignment_power; + } } /* If the section name has a '\$', sort it with the other '\$' @@ -2004,7 +2204,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, ls = &(*pl)->input_section; - lname = bfd_get_section_name (ls->section->owner, ls->section); + lname = bfd_section_name (ls->section); if (strchr (lname, '\$') != NULL && (dollar == NULL || strcmp (orig_secname, lname) < 0)) break; @@ -2037,11 +2237,13 @@ gld_${EMULATION_NAME}_open_dynamic_archive /* Alternate explicit import library for dll's. */ { "%s.dll.a", FALSE }, /* "libfoo.a" could be either an import lib or a static lib. - For backwards compatibility, libfoo.a needs to precede - libfoo.dll and foo.dll in the search. */ + For backwards compatibility, libfoo.a needs to precede + libfoo.dll and foo.dll in the search. */ { "lib%s.a", FALSE }, /* The 'native' spelling of an import lib name is "foo.lib". */ { "%s.lib", FALSE }, + /* PR 22948 - Check for an import library. */ + { "lib%s.lib", FALSE }, #ifdef DLL_SUPPORT /* Try "foo.dll" (preferred dll name, if specified). */ { "%s%s.dll", TRUE }, @@ -2062,7 +2264,7 @@ gld_${EMULATION_NAME}_open_dynamic_archive unsigned int i; - if (! entry->is_archive) + if (! entry->flags.maybe_archive || entry->flags.full_name_provided) return FALSE; filename = entry->filename; @@ -2141,18 +2343,18 @@ fragment <> e${EMULATION_NAME}.c -echo ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c +echo ' ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c if test -n "$GENERATE_AUTO_IMPORT_SCRIPT" ; then -echo ' ; else if (link_info.pei386_auto_import == 1) return' >> e${EMULATION_NAME}.c +echo ' ; else if (link_info.pei386_auto_import == 1 && (MERGE_RDATA_V2 || link_info.pei386_runtime_pseudo_reloc != 2)) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xa >> e${EMULATION_NAME}.c fi echo ' ; else return' >> e${EMULATION_NAME}.c @@ -2169,6 +2371,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = hll_default, gld_${EMULATION_NAME}_after_parse, gld_${EMULATION_NAME}_after_open, + after_check_relocs_default, + before_place_orphans_default, after_allocation_default, set_output_arch_default, ldemul_default_target, @@ -2188,6 +2392,10 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = gld_${EMULATION_NAME}_list_options, gld_${EMULATION_NAME}_recognized_file, gld_${EMULATION_NAME}_find_potential_libraries, - NULL /* new_vers_pattern. */ + NULL, /* new_vers_pattern. */ + NULL, /* extra_map_file_text. */ + ${LDEMUL_EMIT_CTF_EARLY-NULL}, + ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF