diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 68190dbaa27..3413eaca5b3 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2020,6 +2020,14 @@ struct output_elf_obj_tdata asection *sec; } package_metadata; + /* Data for .nx-module-name. */ + struct + { + bool (*after_write_object_contents) (bfd *); + const char *name; + asection *sec; + } nx_module_name; + /* Records the result of `get_program_header_size'. */ bfd_size_type program_header_size; diff --git a/bfd/elf.c b/bfd/elf.c index dfa04c9268d..12b76d3ffb8 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -7223,6 +7223,14 @@ _bfd_elf_write_object_contents (bfd *abfd) if (!bed->s->write_shdrs_and_ehdr (abfd)) return false; + /* Write out the NX module name. */ + if (t->o->nx_module_name.after_write_object_contents != NULL) + { + failed = !(*t->o->nx_module_name.after_write_object_contents) (abfd); + if (failed) + return false; + } + /* This is last since write_shdrs_and_ehdr can touch i_shdrp[0]. */ if (t->o->build_id.after_write_object_contents != NULL && !(*t->o->build_id.after_write_object_contents) (abfd)) diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index e86f0280c2a..debb627a00f 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -2444,6 +2444,12 @@ enum elf_aarch64_stub_type aarch64_stub_erratum_843419_veneer, }; +/* Is an undefined weak symbol resolved to 0 ? */ +#define UNDEFINED_WEAK_RESOLVED_TO_ZERO(INFO, EH) \ + ((EH)->root.root.type == bfd_link_hash_undefweak \ + && bfd_link_executable (INFO) \ + && !(INFO)->dynamic_undefined_weak) + struct elf_aarch64_stub_hash_entry { /* Base hash table entry structure. */ @@ -6986,11 +6992,13 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, Elf_Internal_Sym *sym; asection *sec; struct elf_link_hash_entry *h; + struct elf_aarch64_link_hash_entry *eh; bfd_vma relocation; bfd_reloc_status_type r; arelent bfd_reloc; char sym_type; bool unresolved_reloc = false; + bool resolved_to_zero = false; char *error_message = NULL; r_symndx = ELFNN_R_SYM (rel->r_info); @@ -7130,6 +7138,10 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, h, &unresolved_reloc, save_addend, &addend, sym); + eh = (struct elf_aarch64_link_hash_entry *) h; + resolved_to_zero = (eh != NULL + && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh)); + switch (elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type)) { case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: @@ -7153,7 +7165,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, need_relocs = (!bfd_link_executable (info) || indx != 0) && (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak); BFD_ASSERT (globals->root.srelgot != NULL); @@ -7248,7 +7260,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, need_relocs = (!bfd_link_executable (info) || indx != 0) && (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak); BFD_ASSERT (globals->root.srelgot != NULL); @@ -7297,7 +7309,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, bfd_vma off = symbol_tlsdesc_got_offset (input_bfd, h, r_symndx); need_relocs = (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak); BFD_ASSERT (globals->root.srelgot != NULL); @@ -7623,6 +7635,23 @@ need_copy_relocation_p (struct elf_aarch64_link_hash_entry *eh) return false; } +/* Remove undefined weak symbol from the dynamic symbol table if it + is resolved to 0. */ + +static bool +elfNN_aarch64_elf_fixup_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + if (h->dynindx != -1 + && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, elf_aarch64_hash_entry (h))) + { + h->dynindx = -1; + _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, + h->dynstr_index); + } + return true; +} + /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to @@ -8728,6 +8757,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) struct elf_aarch64_link_hash_table *htab; struct elf_aarch64_link_hash_entry *eh; struct elf_dyn_relocs *p; + bool resolved_to_zero; /* An example of a bfd_link_hash_indirect symbol is versioned symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect) @@ -8747,6 +8777,10 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) info = (struct bfd_link_info *) inf; htab = elf_aarch64_hash_table (info); + eh = (struct elf_aarch64_link_hash_entry *) h; + eh->tlsdesc_got_jump_table_offset = (bfd_vma) - 1; + resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh); + /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined and referenced in a non-shared object. */ if (h->type == STT_GNU_IFUNC @@ -8756,7 +8790,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ - if (h->dynindx == -1 && !h->forced_local + if (h->dynindx == -1 && !h->forced_local && !resolved_to_zero && h->root.type == bfd_link_hash_undefweak) { if (!bfd_elf_link_record_dynamic_symbol (info, h)) @@ -8790,6 +8824,11 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) of relaxing into these from the large model PLT entries. */ s->size += htab->plt_entry_size; + /* There should be no PLT relocations against resolved undefined + weak symbols in the executable. */ + if (!resolved_to_zero) + { + /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ htab->root.sgotplt->size += GOT_ENTRY_SIZE; @@ -8818,6 +8857,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) htab->variant_pcs = 1; } + } else { h->plt.offset = (bfd_vma) - 1; @@ -8830,9 +8870,6 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) h->needs_plt = 0; } - eh = (struct elf_aarch64_link_hash_entry *) h; - eh->tlsdesc_got_jump_table_offset = (bfd_vma) - 1; - if (h->got.refcount > 0) { bool dyn; @@ -8844,7 +8881,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ - if (dyn && h->dynindx == -1 && !h->forced_local + if (dyn && h->dynindx == -1 && !h->forced_local && !resolved_to_zero && h->root.type == bfd_link_hash_undefweak) { if (!bfd_elf_link_record_dynamic_symbol (info, h)) @@ -8858,7 +8895,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { h->got.offset = htab->root.sgot->size; htab->root.sgot->size += GOT_ENTRY_SIZE; - if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + if (((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak) && (bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) @@ -8894,7 +8931,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } indx = h && h->dynindx != -1 ? h->dynindx : 0; - if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + if (((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak) && (!bfd_link_executable (info) || indx != 0 @@ -8976,7 +9013,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) visibility. */ if (h->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) { - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT || resolved_to_zero || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) h->dyn_relocs = NULL; @@ -8996,7 +9033,9 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) symbols which turn out to need copy relocs or are not dynamic. */ - if (!h->non_got_ref + if (!(h->non_got_ref + || (h->root.type == bfd_link_hash_undefweak + && !resolved_to_zero)) && ((h->def_dynamic && !h->def_regular) || (htab->root.dynamic_sections_created @@ -9007,6 +9046,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 && !h->forced_local + && !resolved_to_zero && h->root.type == bfd_link_hash_undefweak && !bfd_elf_link_record_dynamic_symbol (info, h)) return false; @@ -9978,8 +10018,17 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Sym *sym) { struct elf_aarch64_link_hash_table *htab; + struct elf_aarch64_link_hash_entry *eh; + bool local_undefweak; htab = elf_aarch64_hash_table (info); + eh = (struct elf_aarch64_link_hash_entry *) h; + + /* We keep PLT/GOT entries without dynamic PLT/GOT relocations for + resolved undefined weak symbols in executable so that their + references have value 0 at run-time. */ + local_undefweak = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh); + if (h->plt.offset != (bfd_vma) - 1) { asection *plt, *gotplt, *relplt; @@ -10014,7 +10063,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, abort (); elfNN_aarch64_create_small_pltn_entry (h, htab, output_bfd, info); - if (!h->def_regular) + if (!local_undefweak && !h->def_regular) { /* Mark the symbol as undefined, rather than as defined in the .plt section. */ @@ -10036,7 +10085,8 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, && elf_aarch64_hash_entry (h)->got_type == GOT_NORMAL /* Undefined weak symbol in static PIE resolves to 0 without any dynamic relocations. */ - && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) + && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h) + && !local_undefweak) { Elf_Internal_Rela rela; bfd_byte *loc; @@ -10704,6 +10754,9 @@ const struct elf_size_info elfNN_aarch64_size_info = #define elf_backend_init_index_section \ _bfd_elf_init_2_index_sections +#define elf_backend_fixup_symbol \ + elfNN_aarch64_elf_fixup_symbol + #define elf_backend_finish_dynamic_sections \ elfNN_aarch64_finish_dynamic_sections diff --git a/ld/emulparams/aarch64elf.sh b/ld/emulparams/aarch64elf.sh index aa051c76a7a..073d3a47b65 100644 --- a/ld/emulparams/aarch64elf.sh +++ b/ld/emulparams/aarch64elf.sh @@ -1,4 +1,5 @@ source_sh ${srcdir}/emulparams/dt-relr.sh +source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh ARCH=aarch64 MACHINE= diff --git a/ld/emulparams/aarch64elf32.sh b/ld/emulparams/aarch64elf32.sh index 0565b7a066c..64821b1fc31 100644 --- a/ld/emulparams/aarch64elf32.sh +++ b/ld/emulparams/aarch64elf32.sh @@ -1,4 +1,5 @@ source_sh ${srcdir}/emulparams/dt-relr.sh +source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh ARCH="aarch64:ilp32" MACHINE= diff --git a/ld/emulparams/elf32ppccommon.sh b/ld/emulparams/elf32ppccommon.sh index da892988f5d..6b8efb9bbdb 100644 --- a/ld/emulparams/elf32ppccommon.sh +++ b/ld/emulparams/elf32ppccommon.sh @@ -23,7 +23,7 @@ else unset SBSS_START_SYMBOLS unset SBSS_END_SYMBOLS fi -OTHER_END_SYMBOLS="${CREATE_SHLIB+PROVIDE (}__end = .${CREATE_SHLIB+)};" +OTHER_END_SYMBOLS="${CREATE_SHLIB+PROVIDE (}__end = .${CREATE_SHLIB+)};${CREATE_SHLIB+PROVIDE (}__end__ = .${CREATE_SHLIB+)};" OTHER_RELRO_SECTIONS=" .fixup ${RELOCATING-0} : { *(.fixup) } .got1 ${RELOCATING-0} : { *(.got1) } diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em index 91d58d8fe5a..e1ac4a6b139 100644 --- a/ld/emultempl/aarch64elf.em +++ b/ld/emultempl/aarch64elf.em @@ -489,7 +489,7 @@ PARSE_AND_LIST_LONGOPTS=' { "no-apply-dynamic-relocs", no_argument, NULL, OPTION_NO_APPLY_DYNAMIC_RELOCS}, ' -PARSE_AND_LIST_OPTIONS=' +PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' fprintf (file, _(" --no-enum-size-warning Don'\''t warn about objects with incompatible\n" " enum sizes\n")); fprintf (file, _(" --no-wchar-size-warning Don'\''t warn about objects with incompatible\n" diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em index 431205fe644..ce288649513 100644 --- a/ld/emultempl/elf.em +++ b/ld/emultempl/elf.em @@ -814,6 +814,7 @@ EOF fi fragment <o->nx_module_name.name; + asec = t->o->nx_module_name.sec; + if (bfd_is_abs_section (asec->output_section)) + { + einfo (_("%P: warning: .nx-module-name section discarded," + " --build-id ignored\n")); + return true; + } + i_shdr = &elf_section_data (asec->output_section)->this_hdr; + + if (i_shdr->contents == NULL) + { + if (asec->contents == NULL) + asec->contents = (unsigned char *) xmalloc (asec->size); + contents = asec->contents; + } + else + contents = i_shdr->contents + asec->output_offset; + + size = asec->size; + bfd_h_put_32 (abfd, 0, &contents[0]); + bfd_h_put_32 (abfd, size - 9, &contents[4]); + memcpy (&contents[8], name, size - 9); + contents[size - 1] = 0; /* ensure null termination for AMS */ + + position = i_shdr->sh_offset + asec->output_offset; + + return (bfd_seek (abfd, position, SEEK_SET) == 0 + && bfd_write (contents, size, abfd) == size); +} +/* Make .nx-module-name section, and set up elf_tdata->nx_module_name. */ + +static bool +setup_nx_module_name (bfd *ibfd, bfd *obfd) +{ + asection *s; + bfd_size_type size; + flagword flags; + + if (ldelf_emit_nx_module_name[0] == '\0') + { + /* Extract the basename of the output bfd and use it as the module name. */ + char *dot_pos; + free ((char *) ldelf_emit_nx_module_name); + ldelf_emit_nx_module_name = (char *) lbasename (bfd_get_filename (obfd)); + ldelf_emit_nx_module_name = xstrdup (ldelf_emit_nx_module_name); + dot_pos = strrchr (ldelf_emit_nx_module_name, '.'); + if (dot_pos != NULL) + { + /* Remove extension. */ + *dot_pos = 0; + } + } + + size = 8 + strlen(ldelf_emit_nx_module_name) + 1; /* extra null terminator for AMS */ + flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY + | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA); + s = bfd_make_section_with_flags (ibfd, ".nx-module-name", flags); + if (s != NULL && bfd_set_section_alignment (s, 4)) + { + struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd); + t->o->nx_module_name.after_write_object_contents = &write_nx_module_name; + t->o->nx_module_name.name = ldelf_emit_nx_module_name; + t->o->nx_module_name.sec = s; + elf_section_type (s) = SHT_PROGBITS; + s->size = size; + return true; + } + + einfo (_("%P: warning: cannot create .nx-module-name section," + " --nx-module-name ignored\n")); + return false; +} + +/* This is called before calling plugin 'all symbols read' hook. */ void ldelf_before_plugin_all_symbols_read (int use_libpath, int native, int is_linux, int is_freebsd, @@ -1291,6 +1379,24 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, } } + if (ldelf_emit_nx_module_name != NULL) + { + /* Find an ELF input. */ + for (abfd = link_info.input_bfds; + abfd != (bfd *) NULL; abfd = abfd->link.next) + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour + && bfd_count_sections (abfd) != 0 + && !((lang_input_statement_type *) abfd->usrdata)->flags.just_syms) + break; + + /* If there are no ELF input files do not try to create a .nx-module-name section. */ + if (abfd == NULL || !setup_nx_module_name (abfd, link_info.output_bfd)) + { + free ((char *) ldelf_emit_nx_module_name); + ldelf_emit_nx_module_name = NULL; + } + } + get_elf_backend_data (link_info.output_bfd)->setup_gnu_properties (&link_info); /* Do not allow executable files to be used as inputs to the link. */ diff --git a/ld/ldelf.h b/ld/ldelf.h index e8b7c8c7eb8..0b76923d834 100644 --- a/ld/ldelf.h +++ b/ld/ldelf.h @@ -20,6 +20,7 @@ extern const char *ldelf_emit_note_gnu_build_id; extern const char *ldelf_emit_note_fdo_package_metadata; +extern const char *ldelf_emit_nx_module_name; extern void ldelf_finish (void); extern void ldelf_after_parse (void); diff --git a/ld/ldlex.h b/ld/ldlex.h index c8d61478c60..a5bb71b1dc5 100644 --- a/ld/ldlex.h +++ b/ld/ldlex.h @@ -188,6 +188,7 @@ enum option_values /* Used by emultempl/elf.em, emultempl/pe.em and emultempl/pep.em. */ OPTION_BUILD_ID, OPTION_EXCLUDE_LIBS, + OPTION_NX_MODULE_NAME, /* Used by emulparams/elf32mcore.sh, emultempl/beos.em, emultempl/pe.em and emultempl/pep.em. */ OPTION_BASE_FILE, diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c index 712cd31d19e..5d6dbb3b48d 100644 --- a/opcodes/ppc-opc.c +++ b/opcodes/ppc-opc.c @@ -5107,7 +5107,7 @@ const unsigned int num_powerpc_operands = ARRAY_SIZE (powerpc_operands); #define MFDEC2 (PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE \ | PPC_OPCODE_TITAN) #define BOOKE PPC_OPCODE_BOOKE -#define NO371 PPC_OPCODE_BOOKE | PPC_OPCODE_PPCPS | PPC_OPCODE_EFS +#define NO371 PPC_OPCODE_BOOKE | PPC_OPCODE_EFS #define PPCE300 PPC_OPCODE_E300 #define PPCSPE PPC_OPCODE_SPE #define PPCSPE2 PPC_OPCODE_SPE2