X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Femultempl%2Fpep.em;h=a0a7023e7067ae0c358130d843266cc613958de4;hb=a435742a7fb32f6320ce0e6074e2500e28378104;hp=bcc959e95d4954e02e5e269ed858e27642ae9a78;hpb=b5f14a6dffb53245e454ebeb1a353a42d02dfc04;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index bcc959e95d..a0a7023e70 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -5,10 +5,20 @@ if [ -z "$MACHINE" ]; then else OUTPUT_ARCH=${ARCH}:${MACHINE} fi + +case ${target} in + *-*-cygwin*) + move_default_addr_high=1 + ;; + *) + move_default_addr_high=0; + ;; +esac + rm -f e${EMULATION_NAME}.c (echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) fragment < Set size of the initial stack\n")); fprintf (file, _(" --subsystem [:] Set required OS subsystem [& version]\n")); fprintf (file, _(" --support-old-code Support interworking with old code\n")); + fprintf (file, _(" --[no-]leading-underscore Set explicit symbol underscore prefix mode\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")); @@ -335,44 +419,47 @@ gld_${EMULATION_NAME}_list_options (FILE *file) fprintf (file, _(" --exclude-libs lib,lib,... Exclude libraries from automatic export\n")); fprintf (file, _(" --exclude-modules-for-implib mod,mod,...\n")); fprintf (file, _(" Exclude objects, archive members from auto\n")); - fprintf (file, _(" export, place into import library instead.\n")); + 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")); + 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, _(" --disable-auto-image-base Do not auto-choose image base. (default)\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\ adding pseudo-relocations resolved at\n\ - runtime.\n")); + runtime\n")); fprintf (file, _(" --disable-runtime-pseudo-reloc Do not add runtime pseudo-relocations for\n\ - auto-imported DATA.\n")); + auto-imported DATA\n")); fprintf (file, _(" --enable-extra-pep-debug Enable verbose debug output when building\n\ or linking to DLLs (esp. auto-import)\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, _(" --tsaware Image is Terminal Server aware\n")); + fprintf (file, _(" --high-entropy-va Image is compatible with 64-bit address space\n\ + layout randomization (ASLR)\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")); #endif } @@ -381,16 +468,16 @@ static void set_pep_name (char *name, bfd_vma val) { int i; - + is_underscoring (); /* Find the name and set it. */ for (i = 0; init[i].ptr; i++) { - if (strcmp (name, init[i].symbol) == 0) + if (strcmp (name, GET_INIT_SYMBOL_NAME (i)) == 0) { init[i].value = val; init[i].inited = 1; if (strcmp (name,"__image_base__") == 0) - set_pep_name ("___ImageBase", val); + set_pep_name (U ("__ImageBase"), val); return; } } @@ -405,10 +492,10 @@ set_entry_point (void) int i; static const struct - { - const int value; - const char *entry; - } + { + const int value; + const char *entry; + } v[] = { { 1, "NtProcessStartup" }, @@ -423,24 +510,26 @@ 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) { entry = "DllMainCRTStartup"; } else { for (i = 0; v[i].entry; i++) - if (v[i].value == pep_subsystem) - break; + if (v[i].value == pep_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; } - initial_symbol_char = ${INITIAL_SYMBOL_CHAR}; + /* Now we check target's default for getting proper symbol_char. */ + initial_symbol_char = (is_underscoring () != 0 ? "_" : ""); + if (*initial_symbol_char != '\0') { char *alc_entry; @@ -520,7 +609,7 @@ set_pep_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; } @@ -541,7 +630,7 @@ set_pep_value (char *name) set_pep_name (name, (bfd_vma) strtoull (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; } @@ -558,13 +647,15 @@ set_pep_stack_heap (char *resname, char *comname) set_pep_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) { + is_underscoring (); switch (optc) { default: @@ -573,12 +664,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. */ @@ -627,6 +713,18 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_USE_NUL_PREFIXED_IMPORT_TABLES: pep_use_nul_prefixed_import_tables = TRUE; break; + case OPTION_NO_LEADING_UNDERSCORE: + pep_leading_underscore = 0; + break; + case OPTION_LEADING_UNDERSCORE: + pep_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: pep_out_def_filename = xstrdup (optarg); @@ -658,9 +756,6 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_DISABLE_STDCALL_FIXUP: pep_enable_stdcall_fixup = 0; break; - case OPTION_IMPLIB_FILENAME: - pep_implib_filename = xstrdup (optarg); - break; case OPTION_WARN_DUPLICATE_EXPORTS: pep_dll_warn_dup_exports = 1; break; @@ -691,9 +786,6 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC: link_info.pei386_runtime_pseudo_reloc = 0; break; - case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1: - link_info.pei386_runtime_pseudo_reloc = 1; - break; case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2: link_info.pei386_runtime_pseudo_reloc = 2; break; @@ -708,8 +800,14 @@ gld${EMULATION_NAME}_handle_option (int optc) pep_use_coff_long_section_names = 0; break; /* Get DLLCharacteristics bits */ + case OPTION_HIGH_ENTROPY_VA: + pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA; + /* fall through */ case OPTION_DYNAMIC_BASE: pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; + /* fall through */ + case OPTION_ENABLE_RELOC_SECTION: + pep_dll_enable_reloc_section = 1; break; case OPTION_FORCE_INTEGRITY: pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; @@ -732,11 +830,19 @@ 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: + 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 */ set_pep_name ("__dll_characteristics__", pe_dll_characteristics); - + return TRUE; } @@ -771,7 +877,7 @@ static bfd_vma compute_dll_image_base (const char *ofile) { bfd_vma hash = (bfd_vma) strhash (ofile); - return 0x61300000 + ((hash << 16) & 0x0FFC0000); + return NT_DLL_AUTO_IMAGE_BASE + ((hash << 16) & NT_DLL_AUTO_IMAGE_MASK); } #endif @@ -785,11 +891,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 = (pep_enable_auto_image_base @@ -805,7 +913,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. */ @@ -815,8 +923,9 @@ gld_${EMULATION_NAME}_set_symbols (void) { bfd_vma val = init[j].value; lang_assignment_statement_type *rv; - rv = lang_add_assignment (exp_assop ('=', init[j].symbol, - 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 = (short) val; else if (init[j].size == sizeof (int)) @@ -835,7 +944,7 @@ gld_${EMULATION_NAME}_set_symbols (void) if (pep.FileAlignment > pep.SectionAlignment) { - einfo (_("%P: warning, file alignment > section alignment.\n")); + einfo (_("%P: warning, file alignment > section alignment\n")); } } @@ -852,17 +961,10 @@ gld_${EMULATION_NAME}_after_parse (void) "targets, did you mean --export-all-symbols?\n")); set_entry_point (); - + after_parse_default (); } -/* pep-dll.c directly accesses pep_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 * pep_data_import_dll; - #ifdef DLL_SUPPORT static struct bfd_link_hash_entry *pep_undef_found_sym; @@ -923,7 +1025,7 @@ pep_fixup_stdcalls (void) if (pep_enable_stdcall_fixup == -1) { - einfo (_("Warning: resolving %s by linking to %s\n"), + einfo (_("warning: resolving %s by linking to %s\n"), undef->root.string, cname); if (! gave_warning_message) { @@ -950,7 +1052,7 @@ pep_fixup_stdcalls (void) if (pep_enable_stdcall_fixup == -1) { - einfo (_("Warning: resolving %s by linking to %s\n"), + einfo (_("warning: resolving %s by linking to %s\n"), undef->root.string, sym->root.string); if (! gave_warning_message) { @@ -964,8 +1066,8 @@ pep_fixup_stdcalls (void) } } -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[8]; @@ -979,151 +1081,236 @@ make_import_fixup (arelent *rel, asection *s) memset (addend, 0, sizeof (addend)); switch ((rel->howto->bitsize)) { - case 8: - suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 1); - if (suc && rel->howto->pc_relative) - _addend = (bfd_vma) ((bfd_signed_vma) ((char) bfd_get_8 (s->owner, addend))); - else if (suc) - _addend = ((bfd_vma) bfd_get_8 (s->owner, addend)) & 0xff; - break; - case 16: - suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 2); - if (suc && rel->howto->pc_relative) - _addend = (bfd_vma) ((bfd_signed_vma) ((short) bfd_get_16 (s->owner, addend))); - else if (suc) - _addend = ((bfd_vma) bfd_get_16 (s->owner, addend)) & 0xffff; - break; - case 32: - suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4); - if (suc && rel->howto->pc_relative) - _addend = (bfd_vma) ((bfd_signed_vma) ((int) bfd_get_32 (s->owner, addend))); - else if (suc) - _addend = ((bfd_vma) bfd_get_32 (s->owner, addend)) & 0xffffffff; - break; - case 64: - suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 8); - if (suc) - _addend = ((bfd_vma) bfd_get_64 (s->owner, addend)); - break; + case 8: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 1); + if (suc && rel->howto->pc_relative) + _addend = bfd_get_signed_8 (s->owner, addend); + else if (suc) + _addend = bfd_get_8 (s->owner, addend); + break; + case 16: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 2); + if (suc && rel->howto->pc_relative) + _addend = bfd_get_signed_16 (s->owner, addend); + else if (suc) + _addend = bfd_get_16 (s->owner, addend); + break; + case 32: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4); + if (suc && rel->howto->pc_relative) + _addend = bfd_get_signed_32 (s->owner, addend); + else if (suc) + _addend = bfd_get_32 (s->owner, addend); + break; + case 64: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 8); + if (suc) + _addend = bfd_get_64 (s->owner, addend); + break; } if (! suc) - 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); if (pep_dll_extra_pe_debug) { - printf ("import of 0x%lx(0x%lx) sec_addr=0x%lx", (long) _addend, (long) rel->addend, (long) rel->address); - if (rel->howto->pc_relative) printf (" pcrel"); - printf (" %d bit rel.\n",(int) rel->howto->bitsize); - } - pep_create_import_fixup (rel, s, _addend); + printf ("import of 0x%lx(0x%lx) sec_addr=0x%lx", + (long) _addend, (long) rel->addend, (long) rel->address); + if (rel->howto->pc_relative) + printf (" pcrel"); + printf (" %d bit rel.\n", (int) rel->howto->bitsize); + } - return 1; + pep_create_import_fixup (rel, s, _addend, name, symname); } -static void -pep_find_data_imports (void) +static bfd_boolean +pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED) { - struct bfd_link_hash_entry *undef, *sym; + printf ("+%s\n", h->string); - if (link_info.pei386_auto_import == 0) - return; + return TRUE; +} +#endif /* DLL_SUPPORT */ - for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next) - { - if (undef->type == bfd_link_hash_undefined) - { - /* C++ symbols are *long*. */ - char buf[4096]; +static void +debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj) +{ + int *found = (int *) obj; - if (pep_dll_extra_pe_debug) - printf ("%s:%s\n", __FUNCTION__, undef->root.string); + if (strncmp (".debug_", sect->name, sizeof (".debug_") - 1) == 0) + *found = 1; +} - sprintf (buf, "__imp_%s", undef->root.string); +static bfd_boolean +pecoff_checksum_contents (bfd *abfd, + void (*process) (const void *, size_t, void *), + void *arg) +{ + file_ptr filepos = (file_ptr) 0; - sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); + while (1) + { + unsigned char b; + int status; - if (sym && sym->type == bfd_link_hash_defined) - { - bfd *b = sym->u.def.section->owner; - asymbol **symbols; - int nsyms, i; + if (bfd_seek (abfd, filepos, SEEK_SET) != 0) + return 0; - 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, "__head_")) - continue; - - if (pep_dll_extra_pe_debug) - printf ("->%s\n", symbols[i]->name); - - pep_data_import_dll = (char*) (symbols[i]->name + - sizeof ("__head_") - 1); + link_order = l; break; } - - pep_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 (pep_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 enttry */ + 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 (); + + is_underscoring (); #ifdef DLL_SUPPORT if (pep_dll_extra_pe_debug) { @@ -1136,23 +1323,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 = pep; 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 @@ -1162,39 +1374,44 @@ gld_${EMULATION_NAME}_after_open (void) find it, so enable it in that case. */ if (pep_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)) + pep_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) - { - pep_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) + { + pep_use_coff_long_section_names = 1; + break; + } + } } } pep_output_file_set_long_section_names (link_info.output_bfd); #ifdef DLL_SUPPORT - if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */ - pep_fixup_stdcalls (); - pep_process_import_defs (link_info.output_bfd, &link_info); - pep_find_data_imports (); + if (link_info.pei386_auto_import) /* -1=warn or 1=enable */ + pep_find_data_imports (U ("_head_"), make_import_fixup); - /* As possibly new symbols are added by imports, we rerun - stdcall/fastcall fixup here. */ - if (pep_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 (pep_enable_stdcall_fixup) /* -1=warn or 1=enable */ pep_fixup_stdcalls (); #ifndef TARGET_IS_i386pep - if (link_info.shared) + if (bfd_link_pic (&link_info)) #else - if (!link_info.relocatable) + if (!bfd_link_relocatable (&link_info)) #endif pep_dll_build_sections (link_info.output_bfd, &link_info); @@ -1250,7 +1467,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; } @@ -1262,7 +1479,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; } @@ -1270,8 +1487,7 @@ gld_${EMULATION_NAME}_after_open (void) { struct bfd_symbol *s; struct bfd_link_hash_entry * blhe; - char *other_bfd_filename; - char *n; + const char *other_bfd_filename; s = (relocs[i]->sym_ptr_ptr)[0]; @@ -1292,14 +1508,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; + if (!bfd_set_filename (is->the_bfd->my_archive, + other_bfd_filename)) + einfo ("%F%P: %pB: %E\n", is->the_bfd); } free (relocs); @@ -1346,8 +1563,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; } @@ -1363,12 +1580,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; @@ -1380,9 +1597,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; @@ -1402,13 +1619,14 @@ 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; + new_name + = xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3); + sprintf (new_name, "%s.%c", + bfd_get_filename (is->the_bfd), seq); + is->filename = bfd_set_filename (is->the_bfd, new_name); + free (new_name); + if (!is->filename) + einfo ("%F%P: %pB: %E\n", is->the_bfd); } } } @@ -1418,6 +1636,7 @@ gld_${EMULATION_NAME}_after_open (void) static void gld_${EMULATION_NAME}_before_allocation (void) { + is_underscoring (); before_allocation_default (); } @@ -1430,8 +1649,10 @@ saw_option (char *option) { int i; + is_underscoring (); + for (i = 0; init[i].ptr; i++) - if (strcmp (init[i].symbol, option) == 0) + if (strcmp (GET_INIT_SYMBOL_NAME (i), option) == 0) return init[i].inited; return 0; } @@ -1443,7 +1664,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) { pep_def_file = def_file_parse (entry->filename, pep_def_file); @@ -1465,11 +1686,12 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB { struct bfd_link_hash_entry *h; - sprintf (buf, "_%s", pep_def_file->exports[i].internal_name); + sprintf (buf, "%s%s", U (""), + pep_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; @@ -1481,7 +1703,7 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB /* def_file_print (stdout, pep_def_file); */ if (pep_def_file->is_dll == 1) - link_info.shared = 1; + link_info.type = type_dll; if (pep_def_file->base_address != (bfd_vma)(-1)) { @@ -1491,8 +1713,9 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB = pep_def_file->base_address; init[IMAGEBASEOFF].inited = 1; if (image_base_statement) - image_base_statement->exp = exp_assop ('=', "__image_base__", - exp_intop (pep.ImageBase)); + image_base_statement->exp + = exp_assign ("__image_base__", exp_intop (pep.ImageBase), + FALSE); } if (pep_def_file->stack_reserve != -1 @@ -1519,6 +1742,7 @@ gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIB static bfd_boolean gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED) { + is_underscoring (); #ifdef DLL_SUPPORT #ifdef TARGET_IS_i386pep pep_dll_id_target ("pei-x86-64"); @@ -1532,15 +1756,19 @@ gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUT static void gld_${EMULATION_NAME}_finish (void) { + is_underscoring (); finish_default (); #ifdef DLL_SUPPORT - if (link_info.shared - || (!link_info.relocatable && pep_def_file->num_exports != 0)) + if (bfd_link_pic (&link_info) + || pep_dll_enable_reloc_section + || (!bfd_link_relocatable (&link_info) + && pep_def_file->num_exports != 0)) { pep_dll_fill_sections (link_info.output_bfd, &link_info); - if (pep_implib_filename) - pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info); + if (command_line.out_implib_filename) + pep_dll_generate_implib (pep_def_file, + command_line.out_implib_filename, &link_info); } if (pep_out_def_filename) @@ -1586,7 +1814,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; @@ -1618,7 +1846,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; } @@ -1632,7 +1860,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; } @@ -1643,6 +1871,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 }, @@ -1656,6 +1887,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, enum orphan_save_index { orphan_text = 0, + orphan_idata, orphan_rodata, orphan_data, orphan_bss @@ -1664,6 +1896,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) { @@ -1678,18 +1912,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]; @@ -1700,17 +1953,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 '\$' @@ -1725,7 +1985,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; @@ -1758,11 +2018,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 }, @@ -1783,7 +2045,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; @@ -1862,18 +2124,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 && 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 @@ -1890,6 +2152,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, @@ -1909,6 +2173,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