diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2013-11-04 09:35:07 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-09-17 05:24:15 -0700 |
commit | ef1ce0a3648bd8d6b086bf3e05143a187d5b807f (patch) | |
tree | 9a44a8cef2bb3d6ad93906129ff6636ed624833b | |
parent | d78908cff50f281dab6390646fb1b7c58236d83e (diff) | |
download | binutils-gdb-users/hjl/secondary.tar.gz |
Add STB_SECONDARY supportusers/hjl/secondary
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/common3.d: New file.
* gas/elf/common3.l: Likewise.
* gas/elf/common3.s: Likewise.
* gas/elf/common4.d: Likewise.
* gas/elf/common4.l: Likewise.
* gas/elf/common4.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 common3, common4, 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/elf32.em (gld${EMULATION_NAME}_handle_option): Set
to link_info.emit_secondary to FALSE for "-z nosecondary".
(gld${EMULATION_NAME}_list_options): Replace "-z secondary" with
"-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.
80 files changed, 862 insertions, 63 deletions
diff --git a/bfd/archive.c b/bfd/archive.c index 1715474ea6c..7e0a7533681 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -2372,6 +2372,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 51fa54f1d43..bb5b536e081 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6337,6 +6337,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 35c0f6cdf43..29cfec333e3 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -3625,7 +3625,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_get_section (sym)) || bfd_is_com_section (bfd_get_section (sym))); } @@ -7408,8 +7411,9 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"), #endif 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); @@ -7423,6 +7427,8 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"), 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 fff08e5568d..f1755799207 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -2258,7 +2258,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_get_section (sym)) || bfd_is_com_section (bfd_get_section (sym))); } diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c index 4dc5363f6bc..129413358ff 100644 --- a/bfd/elf64-ia64-vms.c +++ b/bfd/elf64-ia64-vms.c @@ -4926,6 +4926,10 @@ error_free_dyn: 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 7e309cf998e..17f44bc0907 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1280,6 +1280,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 8659099df0d..c4a0c1278e1 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -926,7 +926,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, @@ -936,6 +937,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, @@ -952,7 +954,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; @@ -1073,9 +1075,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; @@ -1106,7 +1116,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; @@ -1357,7 +1367,7 @@ _bfd_elf_merge_symbol (bfd *abfd, if (newdef && !newdyn && olddyn) newweak = FALSE; - if (olddef && newdyn) + if (olddef && newdyn && !oldsecondary) oldweak = FALSE; /* Allow changes between different types of function symbol. */ @@ -1472,10 +1482,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)))) @@ -1514,8 +1528,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 @@ -1546,18 +1561,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 @@ -1660,8 +1677,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, @@ -1671,6 +1688,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) { @@ -1716,6 +1734,11 @@ _bfd_elf_add_default_symbol (bfd *abfd, } } + /* 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; @@ -1736,8 +1759,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) @@ -1856,8 +1880,9 @@ nondefault: 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) @@ -3003,31 +3028,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. */ @@ -3046,9 +3081,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; bfd_size_type symcount; @@ -3113,7 +3151,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; } } @@ -3962,6 +4001,7 @@ error_free_dyn: unsigned int old_alignment; bfd *old_bfd; bfd_boolean matched; + bfd_boolean oldsecondary; override = FALSE; @@ -3989,6 +4029,10 @@ error_free_dyn: flags = BSF_WEAK; break; + case STB_SECONDARY: + flags = BSF_SECONDARY; + break; + case STB_GNU_UNIQUE: flags = BSF_GNU_UNIQUE; break; @@ -4224,7 +4268,7 @@ error_free_dyn: | (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)) @@ -4247,7 +4291,12 @@ error_free_dyn: && 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, @@ -4327,10 +4376,14 @@ error_free_dyn: 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) @@ -4359,6 +4412,13 @@ error_free_dyn: { 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 @@ -4377,7 +4437,8 @@ error_free_dyn: 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 @@ -5169,16 +5230,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); @@ -9190,7 +9262,21 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->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, h->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, h->type); + else + sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); + } else sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type); sym.st_target_internal = h->target_internal; @@ -9302,7 +9388,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; unsigned int type = ELF_ST_TYPE (sym.st_info); @@ -9328,10 +9415,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 504c3f39c69..7321f6d8261 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -3461,7 +3461,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_get_section (sym)) || bfd_is_com_section (bfd_get_section (sym))); } diff --git a/bfd/linker.c b/bfd/linker.c index 86a7a1945ba..233fc8c9d21 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1444,6 +1444,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); @@ -1508,15 +1509,53 @@ _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; do { enum link_action action; + enum bfd_link_hash_type type; + + type = h->type; + /* Convert a secondary symbol to a weak symbol. Backend is + responsible to let a weak symbol override a secondary + symbol. */ + if (h->secondary) + switch (type) + { + default: + break; + + case bfd_link_hash_undefined: + type = bfd_link_hash_undefweak; + break; + + case bfd_link_hash_defined: + type = bfd_link_hash_defweak; + break; + } cycle = FALSE; - action = link_action[(int) row][(int) h->type]; + action = link_action[(int) row][(int) type]; switch (action) { case FAIL: @@ -1562,6 +1601,9 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, h->u.def.value = value; h->linker_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 9d7a1f43c13..a514efb5ded 100644 --- a/bfd/syms.c +++ b/bfd/syms.c @@ -306,6 +306,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 @@ -489,6 +493,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' : ' ', @@ -692,6 +697,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 ad6e70dd842..a14ff733991 100644 --- a/binutils/nm.c +++ b/binutils/nm.c @@ -444,6 +444,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 12fb415eee7..865772af6d8 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -10002,6 +10002,7 @@ get_symbol_binding (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), _("<processor specific>: %d"), diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 031fafb91b4..430a4fb22c9 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}, @@ -442,6 +444,29 @@ obj_elf_local (int ignore ATTRIBUTE_UNUSED) } 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) { int c; @@ -451,7 +476,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++; @@ -2211,18 +2237,24 @@ 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); } } } - /* 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)); } #ifdef TC_MIPS @@ -2436,7 +2468,7 @@ elf_frob_file_before_adjust (void) /* If there was .weak foo, but foo was neither defined nor used anywhere, remove it. */ - else if (S_IS_WEAK (symp) + else if ((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.texinfo b/gas/doc/as.texinfo index fa3221e20be..bf825e3e072 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -4335,6 +4335,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}} @@ -6059,6 +6060,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 07362bbe1c1..24e7577060e 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -2033,6 +2033,14 @@ S_IS_WEAK (symbolS *s) } 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) { if (LOCAL_SYMBOL_CHECK (s)) @@ -2079,7 +2087,7 @@ S_FORCE_RELOC (symbolS *s, int strict) return ((struct local_symbol *) s)->lsy_section == undefined_section; return ((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 @@ -2215,9 +2223,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) @@ -2240,7 +2248,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] != '.') @@ -2253,13 +2261,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 @@ -2271,7 +2279,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 @@ -2328,6 +2345,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 cf4f30feeca..191cad15b12 100644 --- a/gas/symbols.h +++ b/gas/symbols.h @@ -91,6 +91,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 *); @@ -109,6 +110,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/common3.d b/gas/testsuite/gas/elf/common3.d new file mode 100644 index 00000000000..e73f6c5a399 --- /dev/null +++ b/gas/testsuite/gas/elf/common3.d @@ -0,0 +1,2 @@ +#name: secondary and common directives +#error-output: common3.l diff --git a/gas/testsuite/gas/elf/common3.l b/gas/testsuite/gas/elf/common3.l new file mode 100644 index 00000000000..58d5142fc81 --- /dev/null +++ b/gas/testsuite/gas/elf/common3.l @@ -0,0 +1,2 @@ +[^:]*: Assembler messages: +[^:]*: Error: symbol `foobar' can not be both secondary and common diff --git a/gas/testsuite/gas/elf/common3.s b/gas/testsuite/gas/elf/common3.s new file mode 100644 index 00000000000..df8b7ed7f5c --- /dev/null +++ b/gas/testsuite/gas/elf/common3.s @@ -0,0 +1,2 @@ + .secondary foobar + .comm foobar,30 diff --git a/gas/testsuite/gas/elf/common4.d b/gas/testsuite/gas/elf/common4.d new file mode 100644 index 00000000000..aca59c01ad9 --- /dev/null +++ b/gas/testsuite/gas/elf/common4.d @@ -0,0 +1,2 @@ +#name: common and secondary directives +#error-output: common4.l diff --git a/gas/testsuite/gas/elf/common4.l b/gas/testsuite/gas/elf/common4.l new file mode 100644 index 00000000000..58d5142fc81 --- /dev/null +++ b/gas/testsuite/gas/elf/common4.l @@ -0,0 +1,2 @@ +[^:]*: Assembler messages: +[^:]*: Error: symbol `foobar' can not be both secondary and common diff --git a/gas/testsuite/gas/elf/common4.s b/gas/testsuite/gas/elf/common4.s new file mode 100644 index 00000000000..37bd0ce2c05 --- /dev/null +++ b/gas/testsuite/gas/elf/common4.s @@ -0,0 +1,2 @@ + .comm foobar,30 + .secondary foobar diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 496e01a4ff3..2db944518f8 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -211,6 +211,11 @@ if { [is_elf_format] } then { run_dump_test "common1" run_dump_test "common2" + run_dump_test "common3" + run_dump_test "common4" + + run_elf_list_test "secondary1" "" "" "-s" "| grep \"secondary_\"" + run_elf_list_test "secondary2" "" "" "-s" "| grep \"secondary_\"" run_dump_test "strtab" 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 43bcc6a9040..e1c3d751c8e 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -99,6 +99,9 @@ struct bfd_link_hash_entry in a linker script. */ unsigned int linker_def : 1; + /* Set if it is a secondary symbol. */ + unsigned int secondary : 1; + /* A union of information depending upon the type. */ union { @@ -366,6 +369,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 e6d8c14d3a2..1e43b8e40bf 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -683,6 +683,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/elf32.em b/ld/emultempl/elf32.em index 7fe90894e8f..23833669386 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -2385,6 +2385,8 @@ fragment <<EOF link_info.error_textrel = FALSE; else if (strcmp (optarg, "textoff") == 0) link_info.error_textrel = FALSE; + else if (strcmp (optarg, "nosecondary") == 0) + link_info.emit_secondary = FALSE; EOF fi diff --git a/ld/ld.texinfo b/ld/ld.texinfo index be1d4906fae..bb9408de5ee 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1177,6 +1177,10 @@ Marks the object may contain $ORIGIN. @item relro Create an ELF @code{PT_GNU_RELRO} segment header in the object. +@item nosecondary +Convert secondary symbols to weak symbols when generating a shared +library. + @item max-page-size=@var{value} Set the emulation maximum page size to @var{value}. diff --git a/ld/ldmain.c b/ld/ldmain.c index 577928d5504..4c2b5a03440 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -278,6 +278,7 @@ main (int argc, char **argv) link_info.combreloc = TRUE; link_info.strip_discarded = TRUE; link_info.emit_hash = TRUE; + link_info.emit_secondary = TRUE; link_info.callbacks = &link_callbacks; link_info.input_bfds_tail = &link_info.input_bfds; /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init diff --git a/ld/lexsup.c b/ld/lexsup.c index 5dc56dc148e..536296d0e91 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -1732,6 +1732,8 @@ elf_shlib_list_options (FILE *file) fprintf (file, _("\ -z norelro Don't create RELRO program header\n")); fprintf (file, _("\ + -z nosecondary Convert secondary symbols to weak symbols\n")); + fprintf (file, _("\ -z stacksize=SIZE Set size of stack segment\n")); fprintf (file, _("\ -z text Treat DT_TEXTREL in shared object as error\n")); diff --git a/ld/testsuite/ld-elf/library1.c b/ld/testsuite/ld-elf/library1.c new file mode 100644 index 00000000000..28e255d318f --- /dev/null +++ b/ld/testsuite/ld-elf/library1.c @@ -0,0 +1,11 @@ +#include <stdio.h> + +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 <stdio.h> + +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 <stdio.h> + +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 <stdio.h> + +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 <stdio.h> + +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..2518db3c0a0 --- /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" + "-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 <stdio.h> + +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 <stdio.h> + +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]+\) +#... |