From 05748d33155caa12e51b2a39a3b1470bba156c0a Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 26 Nov 2017 09:26:34 -0800 Subject: [PATCH] Add STB_SECONDARY support STB_SECONDARY is similar to STB_WEAK. But a STB_SECONDARY definition can be overridden by STB_GLOBAL or STB_WEAK definition at link-time as well as run-time. Linker also search archive library and extract archive members to resolve defined and undefined STB_SECONDARY symbol. bfd/ * archive.c (_bfd_compute_and_write_armap): Treat BSF_SECONDARY symbol as global. * elf32-mips.c (mips_elf_sym_is_global): Likewise. * elfn32-mips.c (mips_elf_sym_is_global): Likewise. * elf.c (sym_is_global): Likewise. (swap_out_syms): Output undefined secondary symbols as weak. Output defined secondary symbols. * elf64-ia64-vms.c (elf64_vms_link_add_object_symbols): Handle secondary symbols. * elfcode.h (elf_slurp_symbol_table): Likewise. * elflink.c (_bfd_elf_merge_symbol): Add a boolean argument to indicate if the old definition is secondary. Set OLDSECONADRY if it isn't TRUE. Treat old secondary symbol as weak. Allow overriding secondary symbols. (_bfd_elf_add_default_symbol): Add a boolean argument to if the old definition is secondary. Handle the unversioned STB_SECONDARY symbol with the versioned definition. * elflink.c (is_global_data_symbol_definition): Renamed to ... (is_global_symbol_definition): This. Add an argument to ignore secondary symbols. If secondary symbols are ignored, count function and common symbols as global definition. (elf_link_is_defined_archive_symbol): Add an argument to ignore secondary symbols. Updated. (elf_link_add_object_symbols): Treat secondary symbols as weak symbols. Allow overriding secondary symbols. Pass oldsecondary to _bfd_elf_merge_symbol and _bfd_elf_add_default_symbol. (elf_link_add_archive_symbols): Keep searching if a definition is secondary. Ignore another secondary definition. Updated. (elf_link_output_extsym): Generate STB_SECONDARY symbols if needed. * linker.c (_bfd_generic_link_add_one_symbol): Treat secondary symbol as weak symbol. Mark secondary symbol. * syms.c (BSF_SECONDARY): New. (bfd_print_symbol_vandf): Handle SECONDARY symbol. (bfd_decode_symclass): Likewise. * bfd-in2.h: Regenerated. binutils/ * nm.c (filter_symbols): Treat BSF_SECONDARY symbol as global. * readelf.c (get_symbol_binding): Handle STB_SECONDARY. gas/ * symbols.c (S_IS_SECONDARY): New. (S_SET_SECONDARY): Likewise. (S_FORCE_RELOC): Handle BSF_SECONDARY like BSF_WEAK. (S_SET_EXTERNAL): Likewise. (S_CLEAR_EXTERNAL): Likewise. (S_CLEAR_WEAKREFD): Likewise. (S_SET_WEAK): Also clear BSF_SECONDARY. * symbols.h (S_IS_SECONDARY): New. (S_SET_SECONDARY): Likewise. * config/obj-elf.c (obj_elf_secondary): New. (elf_pseudo_table): Add "secondary". (obj_elf_weak): Don't set symbol weak on secondary symbol. (elf_frob_symbol): Check secondary symbol. Handle secondary symbol for .symver. Also remove the unused secondary symbol. (elf_frob_file_before_adjust): Treat secondary symbols as weak. * doc/as.texinfo: Document .secondary directive. gas/testsuite/ * gas/elf/common5.d: New file. * gas/elf/common5.l: Likewise. * gas/elf/common5.s: Likewise. * gas/elf/common6.d: Likewise. * gas/elf/common6.l: Likewise. * gas/elf/common6.s: Likewise. * gas/elf/secondary1.e: Likewise. * gas/elf/secondary1.s: Likewise. * gas/elf/secondary2.e: Likewise. * gas/elf/secondary2.s: Likewise. * gas/elf/elf.exp: Run common5, common6, secondary1 and secondary2. * gas/elf/type.s: Add .secondary tests. * gas/elf/type.e: Updated. include/ * bfdlink.h (bfd_link_hash_entry): Add secondary. (bfd_link_info): Add emit_secondary. include/elf/ * common.h (STB_SECONDARY): New. ld/ * ld.texinfo: Document "-z nosecondary". * ldmain.c (main): Initialize link_info.emit_secondary to TRUE. * lexsup.c (elf_shlib_list_options): Add "-z nosecondary". * emultempl/elf.em (gld${EMULATION_NAME}_handle_option): Set to link_info.emit_secondary to FALSE for "-z nosecondary". ld/testsuite/ * ld-elf/library1.c: New file. * ld-elf/library1.out: Likewise. * ld-elf/library2.c: Likewise. * ld-elf/library2.out: Likewise. * ld-elf/library3.out: Likewise. * ld-elf/library4.out: Likewise. * ld-elf/library5a.c: Likewise. * ld-elf/library5b.c: Likewise. * ld-elf/library6a.c: Likewise. * ld-elf/library6b.c: Likewise. * ld-elf/library6c.c: Likewise. * ld-elf/library7a.c: Likewise. * ld-elf/library7b.c: Likewise. * ld-elf/library7c.c: Likewise. * ld-elf/library8.map: Likewise. * ld-elf/library8a.c: Likewise. * ld-elf/library8a.rd: Likewise. * ld-elf/library8b.c: Likewise. * ld-elf/library8b.rd: Likewise. * ld-elf/library8c.c: Likewise. * ld-elf/library8c.rd: Likewise. * ld-elf/secondary-foo.c: Likewise. * ld-elf/secondary-main.c: Likewise. * ld-elf/secondary.c: Likewise. * ld-elf/secondary.exp: Likewise. * ld-elf/secondary.rd: Likewise. * ld-elf/secondary1.out: Likewise. * ld-elf/secondary1.rd: Likewise. * ld-elf/secondary2.rd: Likewise. * ld-elf/secondary3.rd: Likewise. * ld-elf/secondary3a.s: Likewise. * ld-elf/secondary3b.s: Likewise. * ld-elf/secondary4.rd: Likewise. * ld-elf/secondary4.s: Likewise. * ld-elf/secondary5.c: Likewise. * ld-elf/secondary5.out: Likewise. * ld-elf/secondary6.c: Likewise. * ld-elf/secondary6.out: Likewise. * ld-elf/secondary7.c: Likewise. * ld-elf/secondary7.out: Likewise. * ld-elf/secondary8a.c: Likewise. * ld-elf/secondary8a.map: Likewise. * ld-elf/secondary8a.rd: Likewise. * ld-elf/secondary8b.c: Likewise. * ld-elf/secondary8b.rd: Likewise. --- bfd/archive.c | 1 + bfd/bfd-in2.h | 4 + bfd/elf.c | 10 +- bfd/elf32-mips.c | 5 +- bfd/elf64-ia64-vms.c | 4 + bfd/elfcode.h | 3 + bfd/elflink.c | 177 ++++++++++++++++++------- bfd/elfn32-mips.c | 5 +- bfd/linker.c | 40 ++++++ bfd/syms.c | 14 ++ binutils/nm.c | 1 + binutils/readelf.c | 1 + gas/config/obj-elf.c | 44 ++++++- gas/doc/as.texi | 9 ++ gas/symbols.c | 39 ++++-- gas/symbols.h | 2 + gas/testsuite/gas/elf/common6.d | 2 + gas/testsuite/gas/elf/common6.l | 2 + gas/testsuite/gas/elf/common6.s | 2 + gas/testsuite/gas/elf/common7.d | 2 + gas/testsuite/gas/elf/common7.l | 2 + gas/testsuite/gas/elf/common7.s | 2 + gas/testsuite/gas/elf/elf.exp | 5 + gas/testsuite/gas/elf/secondary1.e | 4 + gas/testsuite/gas/elf/secondary1.s | 33 +++++ gas/testsuite/gas/elf/secondary2.e | 1 + gas/testsuite/gas/elf/secondary2.s | 5 + gas/testsuite/gas/elf/type.e | 2 + gas/testsuite/gas/elf/type.s | 13 +- include/bfdlink.h | 6 + include/elf/common.h | 1 + ld/emultempl/elf.em | 2 + ld/ld.texi | 4 + ld/ldmain.c | 1 + ld/lexsup.c | 2 + ld/testsuite/ld-elf/library1.c | 11 ++ ld/testsuite/ld-elf/library1.out | 1 + ld/testsuite/ld-elf/library2.c | 12 ++ ld/testsuite/ld-elf/library2.out | 1 + ld/testsuite/ld-elf/library3.out | 1 + ld/testsuite/ld-elf/library4.out | 1 + ld/testsuite/ld-elf/library5a.c | 16 +++ ld/testsuite/ld-elf/library5b.c | 10 ++ ld/testsuite/ld-elf/library6a.c | 4 + ld/testsuite/ld-elf/library6b.c | 7 + ld/testsuite/ld-elf/library6c.c | 9 ++ ld/testsuite/ld-elf/library7a.c | 1 + ld/testsuite/ld-elf/library7b.c | 7 + ld/testsuite/ld-elf/library7c.c | 3 + ld/testsuite/ld-elf/library8.map | 4 + ld/testsuite/ld-elf/library8a.c | 10 ++ ld/testsuite/ld-elf/library8a.rd | 5 + ld/testsuite/ld-elf/library8b.c | 4 + ld/testsuite/ld-elf/library8b.rd | 5 + ld/testsuite/ld-elf/library8c.c | 7 + ld/testsuite/ld-elf/library8c.rd | 5 + ld/testsuite/ld-elf/secondary-foo.c | 7 + ld/testsuite/ld-elf/secondary-main.c | 8 ++ ld/testsuite/ld-elf/secondary.c | 9 ++ ld/testsuite/ld-elf/secondary.exp | 186 +++++++++++++++++++++++++++ ld/testsuite/ld-elf/secondary.rd | 5 + ld/testsuite/ld-elf/secondary1.out | 1 + ld/testsuite/ld-elf/secondary1.rd | 5 + ld/testsuite/ld-elf/secondary2.rd | 5 + ld/testsuite/ld-elf/secondary3.rd | 6 + ld/testsuite/ld-elf/secondary3a.s | 4 + ld/testsuite/ld-elf/secondary3b.s | 20 +++ ld/testsuite/ld-elf/secondary4.rd | 5 + ld/testsuite/ld-elf/secondary4.s | 9 ++ ld/testsuite/ld-elf/secondary5.c | 10 ++ ld/testsuite/ld-elf/secondary5.out | 3 + ld/testsuite/ld-elf/secondary6.c | 11 ++ ld/testsuite/ld-elf/secondary6.out | 1 + ld/testsuite/ld-elf/secondary7.c | 13 ++ ld/testsuite/ld-elf/secondary7.out | 1 + ld/testsuite/ld-elf/secondary8a.c | 13 ++ ld/testsuite/ld-elf/secondary8a.map | 4 + ld/testsuite/ld-elf/secondary8a.rd | 5 + ld/testsuite/ld-elf/secondary8b.c | 13 ++ ld/testsuite/ld-elf/secondary8b.rd | 5 + 80 files changed, 861 insertions(+), 62 deletions(-) create mode 100644 gas/testsuite/gas/elf/common6.d create mode 100644 gas/testsuite/gas/elf/common6.l create mode 100644 gas/testsuite/gas/elf/common6.s create mode 100644 gas/testsuite/gas/elf/common7.d create mode 100644 gas/testsuite/gas/elf/common7.l create mode 100644 gas/testsuite/gas/elf/common7.s create mode 100644 gas/testsuite/gas/elf/secondary1.e create mode 100644 gas/testsuite/gas/elf/secondary1.s create mode 100644 gas/testsuite/gas/elf/secondary2.e create mode 100644 gas/testsuite/gas/elf/secondary2.s create mode 100644 ld/testsuite/ld-elf/library1.c create mode 100644 ld/testsuite/ld-elf/library1.out create mode 100644 ld/testsuite/ld-elf/library2.c create mode 100644 ld/testsuite/ld-elf/library2.out create mode 100644 ld/testsuite/ld-elf/library3.out create mode 100644 ld/testsuite/ld-elf/library4.out create mode 100644 ld/testsuite/ld-elf/library5a.c create mode 100644 ld/testsuite/ld-elf/library5b.c create mode 100644 ld/testsuite/ld-elf/library6a.c create mode 100644 ld/testsuite/ld-elf/library6b.c create mode 100644 ld/testsuite/ld-elf/library6c.c create mode 100644 ld/testsuite/ld-elf/library7a.c create mode 100644 ld/testsuite/ld-elf/library7b.c create mode 100644 ld/testsuite/ld-elf/library7c.c create mode 100644 ld/testsuite/ld-elf/library8.map create mode 100644 ld/testsuite/ld-elf/library8a.c create mode 100644 ld/testsuite/ld-elf/library8a.rd create mode 100644 ld/testsuite/ld-elf/library8b.c create mode 100644 ld/testsuite/ld-elf/library8b.rd create mode 100644 ld/testsuite/ld-elf/library8c.c create mode 100644 ld/testsuite/ld-elf/library8c.rd create mode 100644 ld/testsuite/ld-elf/secondary-foo.c create mode 100644 ld/testsuite/ld-elf/secondary-main.c create mode 100644 ld/testsuite/ld-elf/secondary.c create mode 100644 ld/testsuite/ld-elf/secondary.exp create mode 100644 ld/testsuite/ld-elf/secondary.rd create mode 100644 ld/testsuite/ld-elf/secondary1.out create mode 100644 ld/testsuite/ld-elf/secondary1.rd create mode 100644 ld/testsuite/ld-elf/secondary2.rd create mode 100644 ld/testsuite/ld-elf/secondary3.rd create mode 100644 ld/testsuite/ld-elf/secondary3a.s create mode 100644 ld/testsuite/ld-elf/secondary3b.s create mode 100644 ld/testsuite/ld-elf/secondary4.rd create mode 100644 ld/testsuite/ld-elf/secondary4.s create mode 100644 ld/testsuite/ld-elf/secondary5.c create mode 100644 ld/testsuite/ld-elf/secondary5.out create mode 100644 ld/testsuite/ld-elf/secondary6.c create mode 100644 ld/testsuite/ld-elf/secondary6.out create mode 100644 ld/testsuite/ld-elf/secondary7.c create mode 100644 ld/testsuite/ld-elf/secondary7.out create mode 100644 ld/testsuite/ld-elf/secondary8a.c create mode 100644 ld/testsuite/ld-elf/secondary8a.map create mode 100644 ld/testsuite/ld-elf/secondary8a.rd create mode 100644 ld/testsuite/ld-elf/secondary8b.c create mode 100644 ld/testsuite/ld-elf/secondary8b.rd diff --git a/bfd/archive.c b/bfd/archive.c index 3423a336956..1a142ec1b13 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -2345,6 +2345,7 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) if (((flags & (BSF_GLOBAL | BSF_WEAK + | BSF_SECONDARY | BSF_INDIRECT | BSF_GNU_UNIQUE)) != 0 || bfd_is_com_section (sec)) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 7aa64556b84..bba1c131fed 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6390,6 +6390,10 @@ typedef struct bfd_symbol with this name and type in use. BSF_OBJECT must also be set. */ #define BSF_GNU_UNIQUE (1 << 23) + /* A secondary global symbol, overridable without warnings by + a regular or weak global symbol of the same name. */ +#define BSF_SECONDARY (1 << 24) + flagword flags; /* A pointer to the section to which this symbol is diff --git a/bfd/elf.c b/bfd/elf.c index 1780074f5ab..6def11ee77a 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4057,7 +4057,10 @@ sym_is_global (bfd *abfd, asymbol *sym) if (bed->elf_backend_sym_is_global) return (*bed->elf_backend_sym_is_global) (abfd, sym); - return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0 + return ((sym->flags & (BSF_GLOBAL + | BSF_WEAK + | BSF_SECONDARY + | BSF_GNU_UNIQUE)) != 0 || bfd_is_und_section (bfd_asymbol_section (sym)) || bfd_is_com_section (bfd_asymbol_section (sym))); } @@ -8368,8 +8371,9 @@ Unable to handle section index %x in ELF symbol. Using ABS instead."), } sym.st_info = ELF_ST_INFO (STB_GLOBAL, type); } + /* Output undefined secondary symbols as weak. */ else if (bfd_is_und_section (syms[idx]->section)) - sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK) + sym.st_info = ELF_ST_INFO (((flags & (BSF_WEAK | BSF_SECONDARY)) ? STB_WEAK : STB_GLOBAL), type); @@ -8383,6 +8387,8 @@ Unable to handle section index %x in ELF symbol. Using ABS instead."), bind = STB_LOCAL; else if (flags & BSF_GNU_UNIQUE) bind = STB_GNU_UNIQUE; + else if (flags & BSF_SECONDARY) + bind = STB_SECONDARY; else if (flags & BSF_WEAK) bind = STB_WEAK; else if (flags & BSF_GLOBAL) diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index e3c4f5594ff..5e1a6a48a5b 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -2280,7 +2280,10 @@ mips_elf_sym_is_global (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym) if (SGI_COMPAT (abfd)) return (sym->flags & BSF_SECTION_SYM) == 0; else - return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0 + return ((sym->flags & (BSF_GLOBAL + | BSF_WEAK + | BSF_SECONDARY + | BSF_GNU_UNIQUE)) != 0 || bfd_is_und_section (bfd_asymbol_section (sym)) || bfd_is_com_section (bfd_asymbol_section (sym))); } diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c index d40fa4277a2..35a6150f721 100644 --- a/bfd/elf64-ia64-vms.c +++ b/bfd/elf64-ia64-vms.c @@ -4954,6 +4954,10 @@ elf64_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) flags = BSF_WEAK; break; + case STB_SECONDARY: + flags = BSF_SECONDARY; + break; + case STB_GNU_UNIQUE: flags = BSF_GNU_UNIQUE; break; diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 68db3e9ee3d..e92818f67eb 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1324,6 +1324,9 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) case STB_WEAK: sym->symbol.flags |= BSF_WEAK; break; + case STB_SECONDARY: + sym->symbol.flags |= BSF_SECONDARY; + break; case STB_GNU_UNIQUE: sym->symbol.flags |= BSF_GNU_UNIQUE; break; diff --git a/bfd/elflink.c b/bfd/elflink.c index 7c0849423a3..9b076744762 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1027,7 +1027,8 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h, overriding a new definition. We set TYPE_CHANGE_OK if it is OK for the type to change. We set SIZE_CHANGE_OK if it is OK for the size to change. By OK to change, we mean that we shouldn't warn if the - type or size does change. */ + type or size does change. If OLDSECONARY is TRUE, the old definion + is a secondary symbol. */ static bfd_boolean _bfd_elf_merge_symbol (bfd *abfd, @@ -1037,6 +1038,7 @@ _bfd_elf_merge_symbol (bfd *abfd, asection **psec, bfd_vma *pvalue, struct elf_link_hash_entry **sym_hash, + bfd_boolean oldsecondary, bfd **poldbfd, bfd_boolean *pold_weak, unsigned int *pold_alignment, @@ -1053,7 +1055,7 @@ _bfd_elf_merge_symbol (bfd *abfd, int bind; bfd *oldbfd; bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon; - bfd_boolean newweak, oldweak, newfunc, oldfunc; + bfd_boolean newweak, oldweak, newfunc, oldfunc, weakbind; const struct elf_backend_data *bed; char *new_version; bfd_boolean default_sym = *matched; @@ -1175,9 +1177,17 @@ _bfd_elf_merge_symbol (bfd *abfd, if (poldbfd && *poldbfd == NULL) *poldbfd = oldbfd; + /* Set OLDSECONADRY if it isn't TRUE. */ + if (!oldsecondary) + oldsecondary = h->root.secondary != 0; + + /* Treat secondary symbols as weak symbols. */ + weakbind = bind == STB_WEAK || bind == STB_SECONDARY; + /* Differentiate strong and weak symbols. */ - newweak = bind == STB_WEAK; - oldweak = (h->root.type == bfd_link_hash_defweak + newweak = weakbind; + oldweak = (oldsecondary + || h->root.type == bfd_link_hash_defweak || h->root.type == bfd_link_hash_undefweak); if (pold_weak) *pold_weak = oldweak; @@ -1203,7 +1213,7 @@ _bfd_elf_merge_symbol (bfd *abfd, { if (bfd_is_und_section (sec)) { - if (bind != STB_WEAK) + if (!weakbind) { h->ref_dynamic_nonweak = 1; hi->ref_dynamic_nonweak = 1; @@ -1499,7 +1509,7 @@ _bfd_elf_merge_symbol (bfd *abfd, if (newdef && !newdyn && (olddyn || h->root.ldscript_def)) newweak = FALSE; - if (olddef && newdyn) + if (olddef && newdyn && !oldsecondary) oldweak = FALSE; /* Allow changes between different types of function symbol. */ @@ -1627,10 +1637,14 @@ _bfd_elf_merge_symbol (bfd *abfd, represent variables; this can cause confusion in principle, but any such confusion would seem to indicate an erroneous program or shared library. We also permit a common symbol in a regular - object to override a weak symbol in a shared object. */ + object to override a weak symbol in a shared object. + + We let a definition in a dynamic object override the old secondary + symbol. */ if (newdyn && newdef + && !oldsecondary && (olddef || (h->root.type == bfd_link_hash_common && (newweak || newfunc)))) @@ -1669,8 +1683,9 @@ _bfd_elf_merge_symbol (bfd *abfd, *size_change_ok = TRUE; } - /* Skip weak definitions of symbols that are already defined. */ - if (newdef && olddef && newweak) + /* Skip weak definitions of symbols that are already defined unless + the old definition is secondary. */ + if (newdef && olddef && newweak && !oldsecondary) { /* Don't skip new non-IR weak syms. */ if (!(oldbfd != NULL @@ -1701,18 +1716,20 @@ _bfd_elf_merge_symbol (bfd *abfd, always take precedence over symbols from dynamic objects, even if they are defined after the dynamic object in the link. + The new non-secondary definition overrides the old secondary + definition. + As above, we again permit a common symbol in a regular object to override a definition in a shared object if the shared object symbol is a function or is weak. */ flip = NULL; - if (!newdyn + if (((!newdyn && olddyn && h->def_dynamic) || oldsecondary) + && bind != STB_SECONDARY && (newdef || (bfd_is_com_section (sec) && (oldweak || oldfunc))) - && olddyn - && olddef - && h->def_dynamic) + && olddef) { /* Change the hash table entry to undefined, and let _bfd_generic_link_add_one_symbol do the right thing with the @@ -1814,8 +1831,8 @@ _bfd_elf_merge_symbol (bfd *abfd, /* This function is called to create an indirect symbol from the default for the symbol with the default version if needed. The - symbol is described by H, NAME, SYM, SEC, and VALUE. We - set DYNSYM if the new indirect symbol is dynamic. */ + symbol is described by H, NAME, SYM, SEC, VALUE, and OLDSECONDARY. + We set DYNSYM if the new indirect symbol is dynamic. */ static bfd_boolean _bfd_elf_add_default_symbol (bfd *abfd, @@ -1825,6 +1842,7 @@ _bfd_elf_add_default_symbol (bfd *abfd, Elf_Internal_Sym *sym, asection *sec, bfd_vma value, + bfd_boolean oldsecondary, bfd **poldbfd, bfd_boolean *dynsym) { @@ -1877,6 +1895,11 @@ _bfd_elf_add_default_symbol (bfd *abfd, return TRUE; } + /* Handle the unversioned STB_SECONDARY symbol with the versioned + definition. */ + if (p == NULL) + return TRUE; + bed = get_elf_backend_data (abfd); collect = bed->collect; dynamic = (abfd->flags & DYNAMIC) != 0; @@ -1897,8 +1920,9 @@ _bfd_elf_add_default_symbol (bfd *abfd, matched = TRUE; tmp_sec = sec; if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value, - &hi, poldbfd, NULL, NULL, &skip, &override, - &type_change_ok, &size_change_ok, &matched)) + &hi, oldsecondary, poldbfd, NULL, NULL, + &skip, &override, &type_change_ok, + &size_change_ok, &matched)) return FALSE; if (skip) @@ -2052,8 +2076,9 @@ _bfd_elf_add_default_symbol (bfd *abfd, size_change_ok = FALSE; tmp_sec = sec; if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value, - &hi, poldbfd, NULL, NULL, &skip, &override, - &type_change_ok, &size_change_ok, &matched)) + &hi, oldsecondary, poldbfd, NULL, NULL, &skip, + &override, &type_change_ok, &size_change_ok, + &matched)) return FALSE; if (skip) @@ -3331,31 +3356,41 @@ _bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) return tls; } -/* Return TRUE iff this is a non-common, definition of a non-function symbol. */ +/* Return TRUE iff this is a non-common, definition of a + non-function symbol, unless IGNORE_SECONDARY is TRUE. */ + static bfd_boolean -is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED, - Elf_Internal_Sym *sym) +is_global_symbol_definition (bfd *abfd, Elf_Internal_Sym *sym, + bfd_boolean ignore_secondary) { - const struct elf_backend_data *bed; + /* Ignore secondary symbols. */ + if (ignore_secondary && ELF_ST_BIND (sym->st_info) == STB_SECONDARY) + return FALSE; /* Local symbols do not count, but target specific ones might. */ if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL && ELF_ST_BIND (sym->st_info) < STB_LOOS) return FALSE; - bed = get_elf_backend_data (abfd); - /* Function symbols do not count. */ - if (bed->is_function_type (ELF_ST_TYPE (sym->st_info))) - return FALSE; - /* If the section is undefined, then so is the symbol. */ if (sym->st_shndx == SHN_UNDEF) return FALSE; - /* If the symbol is defined in the common section, then - it is a common definition and so does not count. */ - if (bed->common_definition (sym)) - return FALSE; + /* If secondary symbols are ignored, count function and common + symbols as global definition. */ + if (!ignore_secondary) + { + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + + /* Function symbols do not count. */ + if (bed->is_function_type (ELF_ST_TYPE (sym->st_info))) + return FALSE; + + /* If the symbol is defined in the common section, then + it is a common definition and so does not count. */ + if (bed->common_definition (sym)) + return FALSE; + } /* If the symbol is in a target specific section then we must rely upon the backend to tell us what it is. */ @@ -3374,9 +3409,12 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED, /* Search the symbol table of the archive element of the archive ABFD whose archive map contains a mention of SYMDEF, and determine if - the symbol is defined in this element. */ + the symbol is defined in this element. Igore seconday defintion, + it IGNORE_SECONDARY is TRUE. */ + static bfd_boolean -elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) +elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef, + bfd_boolean ignore_secondary) { Elf_Internal_Shdr * hdr; size_t symcount; @@ -3451,7 +3489,8 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) if (strcmp (name, symdef->name) == 0) { - result = is_global_data_symbol_definition (abfd, isym); + result = is_global_symbol_definition (abfd, isym, + ignore_secondary); break; } } @@ -4464,6 +4503,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) unsigned int shindex; bfd *old_bfd; bfd_boolean matched; + bfd_boolean oldsecondary; override = FALSE; @@ -4516,6 +4556,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) flags = BSF_WEAK; break; + case STB_SECONDARY: + flags = BSF_SECONDARY; + break; + case STB_GNU_UNIQUE: flags = BSF_GNU_UNIQUE; break; @@ -4759,7 +4803,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) | (isym->st_other & ~ELF_ST_VISIBILITY (-1))); if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value, - sym_hash, &old_bfd, &old_weak, + sym_hash, FALSE, &old_bfd, &old_weak, &old_alignment, &skip, &override, &type_change_ok, &size_change_ok, &matched)) @@ -4782,7 +4826,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) && vernum > 1 && definition) h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1]; + + /* Remember if the old definition is secondary. */ + oldsecondary = h->root.secondary != 0; } + else + oldsecondary = FALSE; if (! (_bfd_generic_link_add_one_symbol (info, abfd, name, flags, sec, value, NULL, FALSE, bed->collect, @@ -4865,10 +4914,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) if (! definition) { h->ref_regular = 1; - if (bind != STB_WEAK) + /* Treat secondary symbols as weak symbols. */ + if (bind != STB_WEAK && bind != STB_SECONDARY) h->ref_regular_nonweak = 1; } - else + /* Mark it defined in a regular object if it is a + non-secondary definition or it hasn't been defined + in a dynamic object. */ + else if (!h->def_dynamic || bind != STB_SECONDARY) { h->def_regular = 1; if (h->def_dynamic) @@ -4897,6 +4950,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) { h->def_dynamic = 1; hi->def_dynamic = 1; + /* Dynamic definition overrides regular old secondary + definition. */ + if (oldsecondary) + { + h->def_regular = 0; + hi->def_regular = 0; + } } /* If the indirect symbol has been forced local, don't @@ -4914,7 +4974,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) if (definition || (!override && h->root.type == bfd_link_hash_common)) if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym, - sec, value, &old_bfd, &dynsym)) + sec, value, oldsecondary, + &old_bfd, &dynsym)) goto error_free_vers; /* Check the alignment when a common symbol is involved. This @@ -5736,16 +5797,27 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) map alone. Instead we must read in the element's symbol table and check that to see what kind of symbol definition this is. */ - if (! elf_link_is_defined_archive_symbol (abfd, symdef)) + if (! elf_link_is_defined_archive_symbol (abfd, symdef, + FALSE)) continue; } - else if (h->root.type != bfd_link_hash_undefined) + /* Keep searching if a definition is secondary. */ + else if (h->root.type != bfd_link_hash_undefined + && !h->root.secondary) { if (h->root.type != bfd_link_hash_undefweak) /* Symbol must be defined. Don't check it again. */ included[i] = TRUE; continue; } + else if (h->root.secondary + && h->root.type == bfd_link_hash_defweak) + { + /* Ignore another secondary definition. */ + if (! elf_link_is_defined_archive_symbol (abfd, symdef, + TRUE)) + continue; + } /* We need to include this archive member. */ element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset); @@ -10088,7 +10160,21 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, type); else if (h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_defweak) - sym.st_info = ELF_ST_INFO (STB_WEAK, type); + { + /* Generate defined secondary symbols for "ld -shared -z secondary" + and "ld -r". For undefined secondary symbols, we convert them + to weak symbols. We also convert defined secondary symbols in + executables to weak symbols since their bindings in executables + are final and can't be changed. */ + if ((bfd_link_relocatable (flinfo->info) + || (!bfd_link_executable (flinfo->info) + && flinfo->info->emit_secondary)) + && h->root.type == bfd_link_hash_defweak + && h->root.secondary) + sym.st_info = ELF_ST_INFO (STB_SECONDARY, type); + else + sym.st_info = ELF_ST_INFO (STB_WEAK, type); + } else sym.st_info = ELF_ST_INFO (STB_GLOBAL, type); sym.st_target_internal = h->target_internal; @@ -10126,7 +10212,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) if (sym.st_shndx == SHN_UNDEF && h->ref_regular && (ELF_ST_BIND (sym.st_info) == STB_GLOBAL - || ELF_ST_BIND (sym.st_info) == STB_WEAK)) + || ELF_ST_BIND (sym.st_info) == STB_WEAK + || ELF_ST_BIND (sym.st_info) == STB_SECONDARY)) { int bindtype; type = ELF_ST_TYPE (sym.st_info); @@ -10152,10 +10239,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) sym.st_size = 0; /* If a non-weak symbol with non-default visibility is not defined - locally, it is a fatal error. */ + locally, it is a fatal error. Treat secondary symbols as weak + symbols. */ if (!bfd_link_relocatable (flinfo->info) && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT && ELF_ST_BIND (sym.st_info) != STB_WEAK + && ELF_ST_BIND (sym.st_info) != STB_SECONDARY && h->root.type == bfd_link_hash_undefined && !h->def_regular) { diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index 71242a55404..fd2d8ad0dfc 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -3840,7 +3840,10 @@ mips_elf_sym_is_global (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym) if (SGI_COMPAT (abfd)) return (sym->flags & BSF_SECTION_SYM) == 0; else - return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0 + return ((sym->flags & (BSF_GLOBAL + | BSF_WEAK + | BSF_SECONDARY + | BSF_GNU_UNIQUE)) != 0 || bfd_is_und_section (bfd_asymbol_section (sym)) || bfd_is_com_section (bfd_asymbol_section (sym))); } diff --git a/bfd/linker.c b/bfd/linker.c index c523f8b5c64..141fcbec813 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1389,6 +1389,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, struct bfd_link_hash_entry *h; struct bfd_link_hash_entry *inh = NULL; bfd_boolean cycle; + unsigned int secondary; BFD_ASSERT (section != NULL); @@ -1455,6 +1456,24 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, return FALSE; } + /* Since secondary symbols have lower precedence than weak symbols, + we treat them as weak symbols here. */ + secondary = (flags & BSF_SECONDARY) != 0; + if (secondary) + switch (row) + { + default: + break; + + case UNDEF_ROW: + row = UNDEFW_ROW; + break; + + case DEF_ROW: + row = DEFW_ROW; + break; + } + if (hashp != NULL) *hashp = h; @@ -1467,6 +1486,24 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, /* Treat symbols defined by early linker script pass as undefined. */ if (h->ldscript_def) prev = bfd_link_hash_undefined; + /* Convert a secondary symbol to a weak symbol. Backend is + responsible to let a weak symbol override a secondary + symbol. */ + else if (h->secondary) + switch (prev) + { + default: + break; + + case bfd_link_hash_undefined: + prev = bfd_link_hash_undefweak; + break; + + case bfd_link_hash_defined: + prev = bfd_link_hash_defweak; + break; + } + cycle = FALSE; action = link_action[(int) row][prev]; switch (action) @@ -1514,6 +1551,9 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, h->linker_def = 0; h->ldscript_def = 0; + /* Mark if this is a secondary symbol. */ + h->secondary = secondary; + /* If we have been asked to, we act like collect2 and identify all functions that might be global constructors and destructors and pass them up in a diff --git a/bfd/syms.c b/bfd/syms.c index 76c212344eb..f4d8a47d291 100644 --- a/bfd/syms.c +++ b/bfd/syms.c @@ -307,6 +307,10 @@ CODE_FRAGMENT . with this name and type in use. BSF_OBJECT must also be set. *} .#define BSF_GNU_UNIQUE (1 << 23) . +. {* A secondary global symbol, overridable without warnings by +. a regular or weak global symbol of the same name. *} +.#define BSF_SECONDARY (1 << 24) +. . flagword flags; . . {* A pointer to the section to which this symbol is @@ -490,6 +494,7 @@ bfd_print_symbol_vandf (bfd *abfd, void *arg, asymbol *symbol) ((type & BSF_LOCAL) ? (type & BSF_GLOBAL) ? '!' : 'l' : (type & BSF_GLOBAL) ? 'g' + : (type & BSF_SECONDARY) ? 's' : (type & BSF_GNU_UNIQUE) ? 'u' : ' '), (type & BSF_WEAK) ? 'w' : ' ', (type & BSF_CONSTRUCTOR) ? 'C' : ' ', @@ -687,6 +692,15 @@ bfd_decode_symclass (asymbol *symbol) } if (symbol->flags & BSF_GNU_UNIQUE) return 'u'; + if (symbol->flags & BSF_SECONDARY) + { + /* If secondary, determine if it's specifically an object + or non-object weak. */ + if (symbol->flags & BSF_OBJECT) + return 'Y'; + else + return 'S'; + } if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL))) return '?'; diff --git a/binutils/nm.c b/binutils/nm.c index 1b5122d56ab..6bfaa2ac9a3 100644 --- a/binutils/nm.c +++ b/binutils/nm.c @@ -502,6 +502,7 @@ filter_symbols (bfd *abfd, bfd_boolean is_dynamic, void *minisyms, /* PR binutls/12753: Unique symbols are global too. */ keep = ((sym->flags & (BSF_GLOBAL | BSF_WEAK + | BSF_SECONDARY | BSF_GNU_UNIQUE)) != 0 || bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)); diff --git a/binutils/readelf.c b/binutils/readelf.c index eb41e10dae9..4b6ce39f69d 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -11133,6 +11133,7 @@ get_symbol_binding (Filedata * filedata, unsigned int binding) case STB_LOCAL: return "LOCAL"; case STB_GLOBAL: return "GLOBAL"; case STB_WEAK: return "WEAK"; + case STB_SECONDARY: return "SECOND"; default: if (binding >= STB_LOPROC && binding <= STB_HIPROC) snprintf (buff, sizeof (buff), _(": %d"), diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index f3f7fc5cb78..9a3c5c6d84a 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -68,6 +68,7 @@ static void obj_elf_line (int); static void obj_elf_size (int); static void obj_elf_type (int); static void obj_elf_ident (int); +static void obj_elf_secondary (int); static void obj_elf_weak (int); static void obj_elf_local (int); static void obj_elf_visibility (int); @@ -97,6 +98,7 @@ static const pseudo_typeS elf_pseudo_table[] = {"type", obj_elf_type, 0}, {"version", obj_elf_version, 0}, {"weak", obj_elf_weak, 0}, + {"secondary", obj_elf_secondary, 0}, /* These define symbol visibility. */ {"internal", obj_elf_visibility, STV_INTERNAL}, @@ -447,6 +449,29 @@ obj_elf_local (int ignore ATTRIBUTE_UNUSED) demand_empty_rest_of_line (); } +static void +obj_elf_secondary (int ignore ATTRIBUTE_UNUSED) +{ + int c; + symbolS *symbolP; + + do + { + symbolP = get_sym_from_input_line_and_check (); + c = *input_line_pointer; + S_SET_SECONDARY (symbolP); + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (*input_line_pointer == '\n') + c = '\n'; + } + } + while (c == ','); + demand_empty_rest_of_line (); +} + static void obj_elf_weak (int ignore ATTRIBUTE_UNUSED) { @@ -457,7 +482,8 @@ obj_elf_weak (int ignore ATTRIBUTE_UNUSED) { symbolP = get_sym_from_input_line_and_check (); c = *input_line_pointer; - S_SET_WEAK (symbolP); + if (!S_IS_SECONDARY (symbolP)) + S_SET_WEAK (symbolP); if (c == ',') { input_line_pointer++; @@ -2549,6 +2575,9 @@ elf_frob_symbol (symbolS *symp, int *puntp) if (S_IS_WEAK (symp)) S_SET_WEAK (symp2); + if (S_IS_SECONDARY (symp)) + S_SET_SECONDARY (symp2); + if (S_IS_EXTERNAL (symp)) S_SET_EXTERNAL (symp2); } @@ -2576,12 +2605,15 @@ elf_frob_symbol (symbolS *symp, int *puntp) } } - /* Double check weak symbols. */ - if (S_IS_WEAK (symp)) + /* Double check weak and secondary symbols. */ + if (S_IS_COMMON (symp)) { - if (S_IS_COMMON (symp)) + if (S_IS_WEAK (symp)) as_bad (_("symbol `%s' can not be both weak and common"), S_GET_NAME (symp)); + else if (S_IS_SECONDARY (symp)) + as_bad (_("symbol `%s' can not be both secondary and common"), + S_GET_NAME (symp)); } } @@ -2801,7 +2833,9 @@ elf_frob_file_before_adjust (void) /* If there was .symver or .weak, but symbol was neither defined nor used anywhere, remove it. */ if (!is_defined - && (sy_obj->versioned_name || S_IS_WEAK (symp)) + && (sy_obj->versioned_name + || S_IS_WEAK (symp) + || S_IS_SECONDARY (symp)) && symbol_used_p (symp) == 0 && symbol_used_in_reloc_p (symp) == 0) symbol_remove (symp, &symbol_rootP, &symbol_lastP); diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 8669879c87f..e56f7d2906d 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -4468,6 +4468,7 @@ Some machine configurations provide additional directives. * Print:: @code{.print @var{string}} @ifset ELF * Protected:: @code{.protected @var{names}} +* Secondary:: @code{.secondary @var{names}} @end ifset * Psize:: @code{.psize @var{lines}, @var{columns}} @@ -6367,6 +6368,14 @@ their binding: local, global or weak). The directive sets the visibility to components that defines them must be resolved to the definition in that component, even if a definition in another component would normally preempt this. + +@node Secondary +@section @code{.secondary @var{names}} + +@cindex @code{secondary} directive +This directive sets the secondary attribute on the comma separated list +of symbol @code{names}. If the symbols do not already exist, they will +be created. @end ifset @node Psize diff --git a/gas/symbols.c b/gas/symbols.c index 160b0f74021..386fc079d67 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -2228,6 +2228,14 @@ S_IS_WEAK (symbolS *s) return (s->bsym->flags & BSF_WEAK) != 0; } +int +S_IS_SECONDARY (symbolS *s) +{ + if (LOCAL_SYMBOL_CHECK (s)) + return 0; + return (s->bsym->flags & BSF_SECONDARY) != 0; +} + int S_IS_WEAKREFR (symbolS *s) { @@ -2277,7 +2285,7 @@ S_FORCE_RELOC (symbolS *s, int strict) else { if ((strict - && ((s->bsym->flags & BSF_WEAK) != 0 + && ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0 || (EXTERN_FORCE_RELOC && (s->bsym->flags & BSF_GLOBAL) != 0))) || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0) @@ -2418,9 +2426,9 @@ S_SET_EXTERNAL (symbolS *s) { if (LOCAL_SYMBOL_CHECK (s)) s = local_symbol_convert ((struct local_symbol *) s); - if ((s->bsym->flags & BSF_WEAK) != 0) + if ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0) { - /* Let .weak override .global. */ + /* Let .weak/.secondary override .global. */ return; } if (s->bsym->flags & BSF_SECTION_SYM) @@ -2438,7 +2446,7 @@ S_SET_EXTERNAL (symbolS *s) } #endif s->bsym->flags |= BSF_GLOBAL; - s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK); + s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK | BSF_SECONDARY); #ifdef TE_PE if (! an_external_name && S_GET_NAME(s)[0] != '.') @@ -2451,13 +2459,13 @@ S_CLEAR_EXTERNAL (symbolS *s) { if (LOCAL_SYMBOL_CHECK (s)) return; - if ((s->bsym->flags & BSF_WEAK) != 0) + if ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0) { - /* Let .weak override. */ + /* Let .weak/.secondary override. */ return; } s->bsym->flags |= BSF_LOCAL; - s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK); + s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK | BSF_SECONDARY); } void @@ -2469,7 +2477,16 @@ S_SET_WEAK (symbolS *s) obj_set_weak_hook (s); #endif s->bsym->flags |= BSF_WEAK; - s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL); + s->bsym->flags &= ~(BSF_GLOBAL | BSF_SECONDARY | BSF_LOCAL); +} + +void +S_SET_SECONDARY (symbolS *s) +{ + if (LOCAL_SYMBOL_CHECK (s)) + s = local_symbol_convert ((struct local_symbol *) s); + s->bsym->flags |= BSF_SECONDARY; + s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK | BSF_LOCAL); } void @@ -2526,6 +2543,12 @@ S_CLEAR_WEAKREFD (symbolS *s) s->bsym->flags &= ~BSF_WEAK; s->bsym->flags |= BSF_LOCAL; } + /* The same applies to secondary symbol. */ + else if (s->bsym->flags & BSF_SECONDARY) + { + s->bsym->flags &= ~BSF_SECONDARY; + s->bsym->flags |= BSF_LOCAL; + } } } diff --git a/gas/symbols.h b/gas/symbols.h index dafd677b9e1..c1b12882b9a 100644 --- a/gas/symbols.h +++ b/gas/symbols.h @@ -92,6 +92,7 @@ extern void S_SET_VALUE (symbolS *, valueT); extern int S_IS_FUNCTION (symbolS *); extern int S_IS_EXTERNAL (symbolS *); extern int S_IS_WEAK (symbolS *); +extern int S_IS_SECONDARY (symbolS *); extern int S_IS_WEAKREFR (symbolS *); extern int S_IS_WEAKREFD (symbolS *); extern int S_IS_COMMON (symbolS *); @@ -110,6 +111,7 @@ extern void S_SET_EXTERNAL (symbolS *); extern void S_SET_NAME (symbolS *, const char *); extern void S_CLEAR_EXTERNAL (symbolS *); extern void S_SET_WEAK (symbolS *); +extern void S_SET_SECONDARY (symbolS *); extern void S_SET_WEAKREFR (symbolS *); extern void S_CLEAR_WEAKREFR (symbolS *); extern void S_SET_WEAKREFD (symbolS *); diff --git a/gas/testsuite/gas/elf/common6.d b/gas/testsuite/gas/elf/common6.d new file mode 100644 index 00000000000..31ca43df9d8 --- /dev/null +++ b/gas/testsuite/gas/elf/common6.d @@ -0,0 +1,2 @@ +#name: common and secondary directives +#error_output: common6.l diff --git a/gas/testsuite/gas/elf/common6.l b/gas/testsuite/gas/elf/common6.l new file mode 100644 index 00000000000..58d5142fc81 --- /dev/null +++ b/gas/testsuite/gas/elf/common6.l @@ -0,0 +1,2 @@ +[^:]*: Assembler messages: +[^:]*: Error: symbol `foobar' can not be both secondary and common diff --git a/gas/testsuite/gas/elf/common6.s b/gas/testsuite/gas/elf/common6.s new file mode 100644 index 00000000000..37bd0ce2c05 --- /dev/null +++ b/gas/testsuite/gas/elf/common6.s @@ -0,0 +1,2 @@ + .comm foobar,30 + .secondary foobar diff --git a/gas/testsuite/gas/elf/common7.d b/gas/testsuite/gas/elf/common7.d new file mode 100644 index 00000000000..124a151e533 --- /dev/null +++ b/gas/testsuite/gas/elf/common7.d @@ -0,0 +1,2 @@ +#name: secondary and common directives +#error_output: common7.l diff --git a/gas/testsuite/gas/elf/common7.l b/gas/testsuite/gas/elf/common7.l new file mode 100644 index 00000000000..58d5142fc81 --- /dev/null +++ b/gas/testsuite/gas/elf/common7.l @@ -0,0 +1,2 @@ +[^:]*: Assembler messages: +[^:]*: Error: symbol `foobar' can not be both secondary and common diff --git a/gas/testsuite/gas/elf/common7.s b/gas/testsuite/gas/elf/common7.s new file mode 100644 index 00000000000..df8b7ed7f5c --- /dev/null +++ b/gas/testsuite/gas/elf/common7.s @@ -0,0 +1,2 @@ + .secondary foobar + .comm foobar,30 diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index c80175cc51d..e52f76e3656 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -296,8 +296,13 @@ if { [is_elf_format] } then { run_dump_test "common5b" run_dump_test "common5c" run_dump_test "common5d" + run_dump_test "common6" + run_dump_test "common7" } + run_elf_list_test "secondary1" "" "" "-s" "| grep \"secondary_\"" + run_elf_list_test "secondary2" "" "" "-s" "| grep \"secondary_\"" + run_dump_test "strtab" run_dump_test "bignums" diff --git a/gas/testsuite/gas/elf/secondary1.e b/gas/testsuite/gas/elf/secondary1.e new file mode 100644 index 00000000000..da00dfb9859 --- /dev/null +++ b/gas/testsuite/gas/elf/secondary1.e @@ -0,0 +1,4 @@ + +.: 0+0 +1 +FUNC +SECOND +DEFAULT +. secondary_function1 + +.: 0+1 +1 +FUNC +SECOND +DEFAULT +. secondary_function2 + +.: 0+0 +1 +OBJECT +SECOND +DEFAULT +. secondary_object1 + +.: 0+1 +1 +OBJECT +SECOND +DEFAULT +. secondary_object2 diff --git a/gas/testsuite/gas/elf/secondary1.s b/gas/testsuite/gas/elf/secondary1.s new file mode 100644 index 00000000000..6a3032dacd2 --- /dev/null +++ b/gas/testsuite/gas/elf/secondary1.s @@ -0,0 +1,33 @@ + .text + + .size secondary_function1,1 + .secondary secondary_function1 + .weak secondary_function1 + .type secondary_function1,%function +secondary_function1: + .byte 0x0 + .size secondary_function1,1 + + .size secondary_function2,1 + .weak secondary_function2 + .secondary secondary_function2 + .type secondary_function2,%function +secondary_function2: + .byte 0x0 + .size secondary_function2,1 + + + .data + .type secondary_object1,%object + .weak secondary_object1 + .secondary secondary_object1 +secondary_object1: + .byte 0x0 + .size secondary_object1,1 + + .type secondary_object2,%object + .weak secondary_object2 + .secondary secondary_object2 +secondary_object2: + .byte 0x0 + .size secondary_object2,1 diff --git a/gas/testsuite/gas/elf/secondary2.e b/gas/testsuite/gas/elf/secondary2.e new file mode 100644 index 00000000000..0470eb82405 --- /dev/null +++ b/gas/testsuite/gas/elf/secondary2.e @@ -0,0 +1 @@ + +.: 0+ +0 +[A-Z]+ +WEAK +DEFAULT +UND secondary_function diff --git a/gas/testsuite/gas/elf/secondary2.s b/gas/testsuite/gas/elf/secondary2.s new file mode 100644 index 00000000000..234330ab992 --- /dev/null +++ b/gas/testsuite/gas/elf/secondary2.s @@ -0,0 +1,5 @@ + .text + .secondary secondary_function + .dc.a secondary_function + .data + .secondary secondary_object diff --git a/gas/testsuite/gas/elf/type.e b/gas/testsuite/gas/elf/type.e index a1159bf4fbc..d4c0548b860 100644 --- a/gas/testsuite/gas/elf/type.e +++ b/gas/testsuite/gas/elf/type.e @@ -3,5 +3,7 @@ +.+: 0+0 +1 +OBJECT +LOCAL +DEFAULT +. object +.+: 0+1 +1 +TLS +LOCAL +DEFAULT +. tls_object +.+: 0+2 +1 +NOTYPE +LOCAL +DEFAULT +. notype + +.+: 0+2 +1 +FUNC +SECOND +DEFAULT +. secondary_function +.+: 0+3 +1 +OBJECT +UNIQUE +DEFAULT +. unique_global + +.+: 0+4 +1 +OBJECT +SECOND +DEFAULT +. secondary_object +.+: 0+1 +1 +(COMMON|OBJECT) +GLOBAL +DEFAULT +COM common diff --git a/gas/testsuite/gas/elf/type.s b/gas/testsuite/gas/elf/type.s index d0a1afd2fa0..bd7df2cb964 100644 --- a/gas/testsuite/gas/elf/type.s +++ b/gas/testsuite/gas/elf/type.s @@ -10,6 +10,12 @@ function: indirect_function: .byte 0x0 + .size secondary_function,1 + .secondary secondary_function + .type secondary_function,%function +secondary_function: + .byte 0x0 + .data .type object,%object @@ -32,6 +38,11 @@ unique_global: .byte 0x0 .size unique_global,1 + .type secondary_object,%object + .secondary secondary_object +secondary_object: + .byte 0x0 + .size secondary_object,1 + .comm common, 1 .type common,STT_COMMON - \ No newline at end of file diff --git a/include/bfdlink.h b/include/bfdlink.h index 84b9dd7a0a0..671788f51a8 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -126,6 +126,9 @@ struct bfd_link_hash_entry outside of an output section statement. */ unsigned int rel_from_abs : 1; + /* Set if it is a secondary symbol. */ + unsigned int secondary : 1; + /* A union of information depending upon the type. */ union { @@ -420,6 +423,9 @@ struct bfd_link_info /* TRUE if .gnu.hash section should be created. */ unsigned int emit_gnu_hash: 1; + /* TRUE if secondary symbols should be generated. */ + unsigned int emit_secondary: 1; + /* If TRUE reduce memory overheads, at the expense of speed. This will cause map file generation to use an O(N^2) algorithm and disable caching ELF symbol buffer. */ diff --git a/include/elf/common.h b/include/elf/common.h index 6741c34a007..aeaaea9dd37 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -905,6 +905,7 @@ #define STB_LOCAL 0 /* Symbol not visible outside obj */ #define STB_GLOBAL 1 /* Symbol visible outside obj */ #define STB_WEAK 2 /* Like globals, lower precedence */ +#define STB_SECONDARY 3 /* Like weaks, lower precedence */ #define STB_LOOS 10 /* OS-specific semantics */ #define STB_GNU_UNIQUE 10 /* Symbol is unique in namespace */ #define STB_HIOS 12 /* OS-specific semantics */ diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em index bb7e5375303..ed2fd3d5445 100644 --- a/ld/emultempl/elf.em +++ b/ld/emultempl/elf.em @@ -811,6 +811,8 @@ fragment < + +void +bar (void) +{ +#ifdef SHARED + printf ("library bar (SHARED)\n"); +#else + printf ("library bar\n"); +#endif +} diff --git a/ld/testsuite/ld-elf/library1.out b/ld/testsuite/ld-elf/library1.out new file mode 100644 index 00000000000..2050e746e5a --- /dev/null +++ b/ld/testsuite/ld-elf/library1.out @@ -0,0 +1 @@ +library bar diff --git a/ld/testsuite/ld-elf/library2.c b/ld/testsuite/ld-elf/library2.c new file mode 100644 index 00000000000..271ebd6ef1a --- /dev/null +++ b/ld/testsuite/ld-elf/library2.c @@ -0,0 +1,12 @@ +#include + +void +__attribute__((weak)) +bar (void) +{ +#ifdef SHARED + printf ("weak library bar (SHARED)\n"); +#else + printf ("weak library bar\n"); +#endif +} diff --git a/ld/testsuite/ld-elf/library2.out b/ld/testsuite/ld-elf/library2.out new file mode 100644 index 00000000000..ddd3d10e794 --- /dev/null +++ b/ld/testsuite/ld-elf/library2.out @@ -0,0 +1 @@ +weak library bar diff --git a/ld/testsuite/ld-elf/library3.out b/ld/testsuite/ld-elf/library3.out new file mode 100644 index 00000000000..881856e6639 --- /dev/null +++ b/ld/testsuite/ld-elf/library3.out @@ -0,0 +1 @@ +library bar (SHARED) diff --git a/ld/testsuite/ld-elf/library4.out b/ld/testsuite/ld-elf/library4.out new file mode 100644 index 00000000000..1ff18403d51 --- /dev/null +++ b/ld/testsuite/ld-elf/library4.out @@ -0,0 +1 @@ +weak library bar (SHARED) diff --git a/ld/testsuite/ld-elf/library5a.c b/ld/testsuite/ld-elf/library5a.c new file mode 100644 index 00000000000..7e44bb4b578 --- /dev/null +++ b/ld/testsuite/ld-elf/library5a.c @@ -0,0 +1,16 @@ +#include + +asm (".secondary bar"); +asm (".weak bar"); + +void +bar (void) +{ + printf ("secondary bar\n"); +} + +void +xxx (void) +{ + printf ("xxx\n"); +} diff --git a/ld/testsuite/ld-elf/library5b.c b/ld/testsuite/ld-elf/library5b.c new file mode 100644 index 00000000000..f44d97c2ad8 --- /dev/null +++ b/ld/testsuite/ld-elf/library5b.c @@ -0,0 +1,10 @@ +#include + +extern void bar (void); + +void +foo (void) +{ + printf ("foo\n"); + bar (); +} diff --git a/ld/testsuite/ld-elf/library6a.c b/ld/testsuite/ld-elf/library6a.c new file mode 100644 index 00000000000..7de81b31a47 --- /dev/null +++ b/ld/testsuite/ld-elf/library6a.c @@ -0,0 +1,4 @@ +void +bar (void) +{ +} diff --git a/ld/testsuite/ld-elf/library6b.c b/ld/testsuite/ld-elf/library6b.c new file mode 100644 index 00000000000..528fd893305 --- /dev/null +++ b/ld/testsuite/ld-elf/library6b.c @@ -0,0 +1,7 @@ +extern void bar (void); + +void +xxx (void) +{ + bar (); +} diff --git a/ld/testsuite/ld-elf/library6c.c b/ld/testsuite/ld-elf/library6c.c new file mode 100644 index 00000000000..60f4b922ad4 --- /dev/null +++ b/ld/testsuite/ld-elf/library6c.c @@ -0,0 +1,9 @@ +extern void abort (void); + +asm (".secondary bar"); + +void +bar (void) +{ + abort (); +} diff --git a/ld/testsuite/ld-elf/library7a.c b/ld/testsuite/ld-elf/library7a.c new file mode 100644 index 00000000000..10cd8bfee26 --- /dev/null +++ b/ld/testsuite/ld-elf/library7a.c @@ -0,0 +1 @@ +int bar; diff --git a/ld/testsuite/ld-elf/library7b.c b/ld/testsuite/ld-elf/library7b.c new file mode 100644 index 00000000000..5f67848a29f --- /dev/null +++ b/ld/testsuite/ld-elf/library7b.c @@ -0,0 +1,7 @@ +extern int bar; + +int +xxx (void) +{ + return bar; +} diff --git a/ld/testsuite/ld-elf/library7c.c b/ld/testsuite/ld-elf/library7c.c new file mode 100644 index 00000000000..aa57fde8197 --- /dev/null +++ b/ld/testsuite/ld-elf/library7c.c @@ -0,0 +1,3 @@ +asm (".secondary bar"); + +int bar = 3; diff --git a/ld/testsuite/ld-elf/library8.map b/ld/testsuite/ld-elf/library8.map new file mode 100644 index 00000000000..bcbb4dea890 --- /dev/null +++ b/ld/testsuite/ld-elf/library8.map @@ -0,0 +1,4 @@ +VERS_1 { + global: bar; _bar; + local: *; +}; diff --git a/ld/testsuite/ld-elf/library8a.c b/ld/testsuite/ld-elf/library8a.c new file mode 100644 index 00000000000..29a75087a02 --- /dev/null +++ b/ld/testsuite/ld-elf/library8a.c @@ -0,0 +1,10 @@ +#if 1 +asm (".secondary bar"); +#else +asm (".weak bar"); +#endif + +void +bar (void) +{ +} diff --git a/ld/testsuite/ld-elf/library8a.rd b/ld/testsuite/ld-elf/library8a.rd new file mode 100644 index 00000000000..a593fbdc2cf --- /dev/null +++ b/ld/testsuite/ld-elf/library8a.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +SECOND +DEFAULT +[0-9]+ +_?bar@@VERS_1 +#... diff --git a/ld/testsuite/ld-elf/library8b.c b/ld/testsuite/ld-elf/library8b.c new file mode 100644 index 00000000000..7de81b31a47 --- /dev/null +++ b/ld/testsuite/ld-elf/library8b.c @@ -0,0 +1,4 @@ +void +bar (void) +{ +} diff --git a/ld/testsuite/ld-elf/library8b.rd b/ld/testsuite/ld-elf/library8b.rd new file mode 100644 index 00000000000..fc18d1ad625 --- /dev/null +++ b/ld/testsuite/ld-elf/library8b.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?bar@@VERS_1 +#... diff --git a/ld/testsuite/ld-elf/library8c.c b/ld/testsuite/ld-elf/library8c.c new file mode 100644 index 00000000000..dfb6a22edb8 --- /dev/null +++ b/ld/testsuite/ld-elf/library8c.c @@ -0,0 +1,7 @@ +extern void bar (); + +void +foo (void) +{ + bar (); +} diff --git a/ld/testsuite/ld-elf/library8c.rd b/ld/testsuite/ld-elf/library8c.rd new file mode 100644 index 00000000000..e2e58f021bb --- /dev/null +++ b/ld/testsuite/ld-elf/library8c.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +0+ +0+ +FUNC +GLOBAL +DEFAULT +UND +_?bar@VERS_1 +\([0-9]+\) +#... diff --git a/ld/testsuite/ld-elf/secondary-foo.c b/ld/testsuite/ld-elf/secondary-foo.c new file mode 100644 index 00000000000..8b23ec8f2b7 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary-foo.c @@ -0,0 +1,7 @@ +extern void bar (void); + +void +foo (void) +{ + bar (); +} diff --git a/ld/testsuite/ld-elf/secondary-main.c b/ld/testsuite/ld-elf/secondary-main.c new file mode 100644 index 00000000000..f1cb6b492bd --- /dev/null +++ b/ld/testsuite/ld-elf/secondary-main.c @@ -0,0 +1,8 @@ +extern void foo (void); + +int +main (void) +{ + foo (); + return 0; +} diff --git a/ld/testsuite/ld-elf/secondary.c b/ld/testsuite/ld-elf/secondary.c new file mode 100644 index 00000000000..6d64ed7652e --- /dev/null +++ b/ld/testsuite/ld-elf/secondary.c @@ -0,0 +1,9 @@ +#include + +asm (".secondary bar"); + +void +bar (void) +{ + printf ("secondary bar\n"); +} diff --git a/ld/testsuite/ld-elf/secondary.exp b/ld/testsuite/ld-elf/secondary.exp new file mode 100644 index 00000000000..63223326557 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary.exp @@ -0,0 +1,186 @@ +# Expect script for ELF secondary symbol tests. +# Copyright 2012 +# Free Software Foundation, Inc. +# +# This file is part of the GNU Binutils. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. +# + +# Exclude non-ELF targets. + +# The following tests require running the executable generated by ld, +# or enough of a build environment to create a fully linked executable. +# This is not commonly available when testing a cross-built linker. +if ![isnative] { + return +} + +if ![is_elf_format] { + return +} + +# Check to see if the C compiler works +if { [which $CC] == 0 } { + return +} + +set build_tests { + {"Build secondary1.o" + "-r -nostdlib" "" + {secondary.c} {{readelf {-s} secondary.rd}} "secondary1.o"} + {"Build secondary1.so" + "-Wl,-z,nosecondary -shared" "-fPIC" + {secondary.c} {{readelf {--dyn-syms} secondary1.rd}} "secondary1.so"} + {"Build secondary2.so" + "-shared" "-fPIC" + {secondary.c} {{readelf {--dyn-syms} secondary2.rd}} "secondary2.so"} + {"Build libfoo.so" + "-shared" "-fPIC" + {secondary-foo.c} {} "libfoo.so"} + {"Build secondary-main with secondary.o" + "tmpdir/secondary.o tmpdir/libfoo.so" "" + {secondary-main.c} {{readelf {--dyn-syms} secondary1.rd}} "secondary"} + {"Build library1.so" + "-shared" "-fPIC -DSHARED" + {library1.c} {} "library1.so"} + {"Build library2.so" + "-shared" "-fPIC -DSHARED" + {library2.c} {} "library2.so"} + {"Build library1.a" + "" "" + {library1.c} {} "library1.a"} + {"Build library2.a" + "" "" + {library2.c} {} "library2.a"} + {"Build secondary3a.o" + "" "" + {secondary3a.s} {} "secondary3a.a"} + {"Build secondary3" + "-nostdlib tmpdir/secondary3a.o" "" + {secondary3b.s} {{readelf {-s} secondary3.rd}} "secondary3"} + {"Build secondary4.so" + "-nostdlib -shared tmpdir/secondary3a.o" "" + {secondary4.s} {{readelf {--dyn-syms} secondary4.rd}} "secondary4.so"} + {"Build library5a.a" + "" "" + {library5a.c} {} "library5a.a"} + {"Build library5b.a" + "" "" + {library5b.c} {} "library5b.a"} + {"Build secondary5.a" + "" "" + {secondary5.c} {} "secondary5.a"} + {"Build library6a.a" + "" "" + {library6a.c} {} "library6a.a"} + {"Build library6b.a" + "" "" + {library6b.c} {} "library6b.a"} + {"Build library6c.a" + "" "" + {library6c.c} {} "library6c.a"} + {"Build secondary6.a" + "" "" + {secondary6.c} {} "secondary6.a"} + {"Build library7a.a" + "" "" + {library7a.c} {} "library7a.a"} + {"Build library7b.a" + "" "" + {library7b.c} {} "library7b.a"} + {"Build library7c.a" + "" "" + {library7c.c} {} "library7c.a"} + {"Build secondary7.a" + "" "" + {secondary7.c} {} "secondary7.a"} + {"Build library8a.so" + "-shared -Wl,--version-script=library8.map" "-fPIC" + {library8a.c} {{readelf {-s} library8a.rd}} "library8a.so"} + {"Build library8b.so" + "-shared -Wl,--version-script=library8.map" "-fPIC" + {library8b.c} {{readelf {-s} library8b.rd}} "library8b.so"} + {"Build library8c.a" + "" "-fPIC" + {library8c.c} {} "library8c.a"} + {"Build library8c.so" + "-shared -Wl,--version-script=library8.map tmpdir/library8c.o tmpdir/library8a.so tmpdir/library8b.so" + "-fPIC" + {dummy.c} {{readelf {-s} library8c.rd}} "library8c.so"} + {"Build secondary8a.so" + "-shared -Wl,--version-script=secondary8a.map" "-fPIC" + {secondary8a.c} {{readelf {-s} secondary8a.rd}} "secondary8a.so"} + {"Build secondary8b.a" + "" "-fPIC" + {secondary8b.c} {} "secondary8b.a"} + {"Build secondary8b.so" + "-shared -Wl,--start-group tmpdir/secondary8a.so tmpdir/secondary8b.o -Wl,--end-group" + "-fPIC" + {dummy.c} {{readelf {-s} secondary8b.rd}} "secondary8b.so"} +} + +run_cc_link_tests $build_tests + +set run_tests { + {"Run secondary-main with secondary.o" + "tmpdir/secondary.o tmpdir/libfoo.so" "" + {secondary-main.c} "secondary1" "secondary1.out"} + {"Run secondary-main with secondary1.so" + "tmpdir/secondary1.so tmpdir/libfoo.so" "" + {secondary-main.c} "secondary2" "secondary1.out"} + {"Run secondary-main with secondary.o library1.o" + "tmpdir/secondary.o tmpdir/secondary.o tmpdir/library1.o tmpdir/libfoo.so" "" + {secondary-main.c} "secondary3" "library1.out"} + {"Run secondary-main with library1.o secondary.o" + "tmpdir/library1.o tmpdir/secondary.o tmpdir/secondary.o tmpdir/libfoo.so" "" + {secondary-main.c} "secondary4" "library1.out"} + {"Run secondary-main with secondary.o library2.o" + "tmpdir/secondary.o tmpdir/library2.o tmpdir/libfoo.so" "" + {secondary-main.c} "secondary5" "library2.out"} + {"Run secondary-main with library2.o secondary.o" + "tmpdir/library2.o tmpdir/secondary.o tmpdir/libfoo.so" "" + {secondary-main.c} "secondary6" "library2.out"} + {"Run secondary-main with secondary.o library1.so" + "tmpdir/secondary.o tmpdir/library1.so tmpdir/libfoo.so" "" + {secondary-main.c} "secondary7" "library3.out"} + {"Run secondary-main with library1.so secondary.o" + "tmpdir/library1.so tmpdir/secondary.o tmpdir/libfoo.so" "" + {secondary-main.c} "secondary8" "library3.out"} + {"Run secondary-main with secondary.o library2.so" + "tmpdir/secondary.o tmpdir/library2.so tmpdir/libfoo.so" "" + {secondary-main.c} "secondary9" "library4.out"} + {"Run secondary-main with library2.so secondary.o" + "tmpdir/library2.so tmpdir/secondary.o tmpdir/libfoo.so" "" + {secondary-main.c} "secondary10" "library4.out"} + {"Run secondary5 with library5a.a library5b.a" + "tmpdir/secondary5.o tmpdir/library5a.a tmpdir/library5b.a" "" + {dummy.c} "secondary5a" "secondary5.out"} + {"Run secondary5 with -( library5a.a library5b.a -)" + "tmpdir/secondary5.o -\\( tmpdir/library5a.a tmpdir/library5b.a -\\)" "" + {dummy.c} "secondary5b" "secondary5.out"} + {"Run secondary5 with -( library5a.a library5b.a -) -( library5a.a library5b.a -)" + "tmpdir/secondary5.o -\\( tmpdir/library5a.a tmpdir/library5b.a -\\) -\\( tmpdir/library5a.a tmpdir/library5b.a -\\)" "" + {dummy.c} "secondary5c" "secondary5.out"} + {"Run secondary6 with -( library6a.a library6b.a library6c.a -)" + "tmpdir/secondary6.o -\\( tmpdir/library6a.a tmpdir/library6b.a tmpdir/library6c.a -\\)" "" + {dummy.c} "secondary6" "secondary6.out"} + {"Run secondary7 with -( library7a.a library7b.a library7c.a -)" + "tmpdir/secondary7.o -\\( tmpdir/library7a.a tmpdir/library7b.a tmpdir/library7c.a -\\)" "" + {dummy.c} "secondary7" "secondary7.out"} +} + +run_ld_link_exec_tests [] $run_tests diff --git a/ld/testsuite/ld-elf/secondary.rd b/ld/testsuite/ld-elf/secondary.rd new file mode 100644 index 00000000000..9931c045b09 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary.rd @@ -0,0 +1,5 @@ +Symbol table '\.symtab' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +SECOND +DEFAULT +[0-9]+ +_?bar +#... diff --git a/ld/testsuite/ld-elf/secondary1.out b/ld/testsuite/ld-elf/secondary1.out new file mode 100644 index 00000000000..8d9378f95b4 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary1.out @@ -0,0 +1 @@ +secondary bar diff --git a/ld/testsuite/ld-elf/secondary1.rd b/ld/testsuite/ld-elf/secondary1.rd new file mode 100644 index 00000000000..89d6d76d43e --- /dev/null +++ b/ld/testsuite/ld-elf/secondary1.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +WEAK +DEFAULT +[0-9]+ +_?bar +#... diff --git a/ld/testsuite/ld-elf/secondary2.rd b/ld/testsuite/ld-elf/secondary2.rd new file mode 100644 index 00000000000..ff618a035ca --- /dev/null +++ b/ld/testsuite/ld-elf/secondary2.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +SECOND +DEFAULT +[0-9]+ +_?bar +#... diff --git a/ld/testsuite/ld-elf/secondary3.rd b/ld/testsuite/ld-elf/secondary3.rd new file mode 100644 index 00000000000..562244a0294 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary3.rd @@ -0,0 +1,6 @@ +Symbol table '\.symtab' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#failif +#... + +[0-9]+: +0+ +0+ +[A-Z]+ +WEAK +DEFAULT +UND +_?foo +#... diff --git a/ld/testsuite/ld-elf/secondary3a.s b/ld/testsuite/ld-elf/secondary3a.s new file mode 100644 index 00000000000..16a130043ef --- /dev/null +++ b/ld/testsuite/ld-elf/secondary3a.s @@ -0,0 +1,4 @@ + .section .text,"axG",%progbits,foo_group,comdat + .global bar +bar: + .byte 0 diff --git a/ld/testsuite/ld-elf/secondary3b.s b/ld/testsuite/ld-elf/secondary3b.s new file mode 100644 index 00000000000..cc6f37bd7e2 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary3b.s @@ -0,0 +1,20 @@ + .section .text,"axG",%progbits,foo_group,comdat + .secondary foo + .global bar +foo: + .byte 0 +bar: + .byte 0 + .data + .dc.a foo + + .text + .global start /* Used by SH targets. */ +start: + .global _start +_start: + .global __start +__start: + .global main /* Used by HPPA targets. */ +main: + .dc.a bar diff --git a/ld/testsuite/ld-elf/secondary4.rd b/ld/testsuite/ld-elf/secondary4.rd new file mode 100644 index 00000000000..e84b1a6cb86 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary4.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +0+ +0+ +[A-Z]+ +WEAK +DEFAULT +UND +_?foo +#... diff --git a/ld/testsuite/ld-elf/secondary4.s b/ld/testsuite/ld-elf/secondary4.s new file mode 100644 index 00000000000..a2acf21c573 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary4.s @@ -0,0 +1,9 @@ + .section .text,"axG",%progbits,foo_group,comdat + .secondary foo + .global bar +foo: + .byte 0 +bar: + .byte 0 + .data + .dc.a foo diff --git a/ld/testsuite/ld-elf/secondary5.c b/ld/testsuite/ld-elf/secondary5.c new file mode 100644 index 00000000000..a2b2f20695a --- /dev/null +++ b/ld/testsuite/ld-elf/secondary5.c @@ -0,0 +1,10 @@ +extern void foo (void); +extern void xxx (void); + +int +main (void) +{ + foo (); + xxx (); + return 0; +} diff --git a/ld/testsuite/ld-elf/secondary5.out b/ld/testsuite/ld-elf/secondary5.out new file mode 100644 index 00000000000..730c35dceb3 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary5.out @@ -0,0 +1,3 @@ +foo +secondary bar +xxx diff --git a/ld/testsuite/ld-elf/secondary6.c b/ld/testsuite/ld-elf/secondary6.c new file mode 100644 index 00000000000..2a7e17b94b0 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary6.c @@ -0,0 +1,11 @@ +#include + +extern void xxx (void); + +int +main (void) +{ + xxx (); + printf ("OK\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/secondary6.out b/ld/testsuite/ld-elf/secondary6.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary6.out @@ -0,0 +1 @@ +OK diff --git a/ld/testsuite/ld-elf/secondary7.c b/ld/testsuite/ld-elf/secondary7.c new file mode 100644 index 00000000000..9a67352e95c --- /dev/null +++ b/ld/testsuite/ld-elf/secondary7.c @@ -0,0 +1,13 @@ +#include + +extern void abort (void); +extern int xxx (void); + +int +main (void) +{ + if (xxx () != 0) + abort (); + printf ("OK\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/secondary7.out b/ld/testsuite/ld-elf/secondary7.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary7.out @@ -0,0 +1 @@ +OK diff --git a/ld/testsuite/ld-elf/secondary8a.c b/ld/testsuite/ld-elf/secondary8a.c new file mode 100644 index 00000000000..22b55aa4256 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary8a.c @@ -0,0 +1,13 @@ +#if 1 +asm (".secondary __bar"); +asm (".secondary bar"); +#else +asm (".weak __bar"); +asm (".weak bar"); +#endif + +void +__bar (void) +{ +} +asm (".set bar, __bar"); diff --git a/ld/testsuite/ld-elf/secondary8a.map b/ld/testsuite/ld-elf/secondary8a.map new file mode 100644 index 00000000000..29476406f7c --- /dev/null +++ b/ld/testsuite/ld-elf/secondary8a.map @@ -0,0 +1,4 @@ +VERS_1 { + global: bar; + local: *; +}; diff --git a/ld/testsuite/ld-elf/secondary8a.rd b/ld/testsuite/ld-elf/secondary8a.rd new file mode 100644 index 00000000000..f52033c4dad --- /dev/null +++ b/ld/testsuite/ld-elf/secondary8a.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +SECOND +DEFAULT +[0-9]+ +_?bar@@VERS_1 +#... diff --git a/ld/testsuite/ld-elf/secondary8b.c b/ld/testsuite/ld-elf/secondary8b.c new file mode 100644 index 00000000000..22b55aa4256 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary8b.c @@ -0,0 +1,13 @@ +#if 1 +asm (".secondary __bar"); +asm (".secondary bar"); +#else +asm (".weak __bar"); +asm (".weak bar"); +#endif + +void +__bar (void) +{ +} +asm (".set bar, __bar"); diff --git a/ld/testsuite/ld-elf/secondary8b.rd b/ld/testsuite/ld-elf/secondary8b.rd new file mode 100644 index 00000000000..276c3ce72f5 --- /dev/null +++ b/ld/testsuite/ld-elf/secondary8b.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +0+ +0+ +FUNC +SECOND +DEFAULT +UND +_?bar@VERS_1 +\([0-9]+\) +#... -- 2.26.0