blob: eeeb95ee8bdbf7f6bb1e220a7bf0b878293d23d9 [file] [log] [blame]
From c7beb33d82923479aab9638145e23b26f4c68e2d Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 4 Nov 2013 09:35:07 -0800
Subject: [PATCH] Add STB_SECONDARY support to gas and ld
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.
---
ChangeLog.secondary | 221 +++++++++++++++++++++++++++++++++++
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 | 171 ++++++++++++++++++++-------
bfd/elfn32-mips.c | 5 +-
bfd/linker.c | 44 ++++++-
bfd/syms.c | 14 +++
binutils/nm.c | 1 +
binutils/readelf.c | 1 +
gas/config/obj-elf.c | 42 ++++++-
gas/doc/as.texinfo | 9 ++
gas/symbols.c | 39 +++++--
gas/symbols.h | 2 +
gas/testsuite/gas/elf/common3.d | 2 +
gas/testsuite/gas/elf/common3.l | 2 +
gas/testsuite/gas/elf/common3.s | 2 +
gas/testsuite/gas/elf/common4.d | 2 +
gas/testsuite/gas/elf/common4.l | 2 +
gas/testsuite/gas/elf/common4.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/elf32.em | 4 +
ld/ld.texinfo | 4 +
ld/ldmain.c | 1 +
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 | 176 ++++++++++++++++++++++++++++
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 | 5 +
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 +
75 files changed, 1026 insertions(+), 63 deletions(-)
create mode 100644 ChangeLog.secondary
create mode 100644 gas/testsuite/gas/elf/common3.d
create mode 100644 gas/testsuite/gas/elf/common3.l
create mode 100644 gas/testsuite/gas/elf/common3.s
create mode 100644 gas/testsuite/gas/elf/common4.d
create mode 100644 gas/testsuite/gas/elf/common4.l
create mode 100644 gas/testsuite/gas/elf/common4.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
diff --git a/ChangeLog.secondary b/ChangeLog.secondary
new file mode 100644
index 0000000..f3bb59d
--- /dev/null
+++ b/ChangeLog.secondary
@@ -0,0 +1,221 @@
+bfd/
+
+2012-09-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf-bfd.h (_bfd_elf_merge_symbol): Add a boolean argument to
+ indicate if the old definition is secondary.
+
+ * elf32-sh-symbian.c (sh_symbian_relocate_section): Pass FALSE
+ to _bfd_elf_merge_symbol.
+
+ * 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.
+ (_bfd_elf_add_default_symbol): Add a boolean argument to if the
+ old definition is secondary.
+ (elf_link_add_object_symbols): Pass oldsecondary to
+ _bfd_elf_merge_symbol and _bfd_elf_add_default_symbol.
+
+2012-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (is_global_data_symbol_definition): Renamed to ...
+ (is_global_symbol_definition): This. If secondary symbols are
+ ignored, count function and common symbols as global definition.
+ (elf_link_is_defined_archive_symbol): Updated.
+
+2012-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (is_global_data_symbol_definition): Add an argument
+ to ignore secondary symbols.
+ (elf_link_is_defined_archive_symbol): Likewise and pass it to
+ is_global_data_symbol_definition.
+ (elf_link_add_archive_symbols): Ignore another secondary
+ definition.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (elf_link_output_extsym): Generate STB_SECONDARY
+ symbols if needed.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf.c (swap_out_syms): Output undefined secondary symbols
+ as weak.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (_bfd_elf_merge_symbol): Allow overriding secondary
+ symbols.
+ (elf_link_add_object_symbols): Treat secondary symbols as weak
+ symbols. Allow overriding secondary symbols.
+ (elf_link_add_archive_symbols): Keep searching if a definition
+ is secondary.
+ (elf_link_output_extsym): Treat secondary symbols as weak
+ symbols.
+ * linker.c (_bfd_generic_link_add_one_symbol): Treat secondary
+ symbol as weak symbol. Mark secondary symbol.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * 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): Handle SECONDARY symbol.
+ * elf64-ia64-vms.c (elf64_vms_link_add_object_symbols): Likewise.
+ * elfcode.h (elf_slurp_symbol_table): Likewise.
+ * elflink.c (elf_link_add_object_symbols): Likewise.
+
+ * syms.c (BSF_SECONDARY): New.
+ (bfd_print_symbol_vandf): Handle SECONDARY symbol.
+ (bfd_decode_symclass): Likewise.
+
+ * bfd-in2.h: Regenerated.
+
+binutils/
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * nm.c (filter_symbols): Treat BSF_SECONDARY symbol as global.
+
+ * readelf.c (get_symbol_binding): Handle STB_SECONDARY.
+
+gas/
+
+2012-09-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/obj-elf.c (obj_elf_weak): Don't set symbol weak on
+ secondary symbol.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/obj-elf.c (elf_frob_symbol): Handle secondary symbol
+ for .symver. Also remove the unused secondary symbol.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * 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".
+ (elf_frob_symbol): Also check secondary symbols.
+
+ * doc/as.texinfo: Document .secondary directive.
+
+gas/testsuite/
+
+2012-09-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * 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/
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * bfdlink.h (bfd_link_info): Add emit_secondary.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * bfdlink.h (bfd_link_hash_entry): Add secondary.
+
+include/elf/
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * common.h (STB_SECONDARY): New.
+
+ld/
+
+2012-09-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld.texinfo: Change "-z secondary" to "-z nosecondary".
+
+ * ldmain.c (main): Initialize link_info.emit_secondary to TRUE.
+
+ * 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".
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld.texinfo: Document "-z secondary".
+
+ * emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Set
+ to link_info.emit_secondary to TRUE for "-z secondary".
+ (gld${EMULATION_NAME}_list_options): Add "-z secondary".
+
+ld/testsuite/
+
+2012-09-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-elf/secondary.exp: Update -Wl,-z,secondary with
+ -Wl,-z,nosecondary.
+
+2012-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * 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/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/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.
diff --git a/bfd/archive.c b/bfd/archive.c
index 40a3395..0d80fc5 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -2337,6 +2337,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 27fc3fe..fdc1138 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6168,6 +6168,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 9dc6b6d..97816f4 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3259,7 +3259,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)));
}
@@ -6922,8 +6925,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);
@@ -6937,6 +6941,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 af405bc..e84efad 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2154,7 +2154,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 dd86e3c..0ff1798 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 a49a708..b09ab77 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1281,6 +1281,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 c1e7948..984cee6 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -885,7 +885,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,
@@ -895,6 +896,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,
@@ -910,7 +912,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;
*skip = FALSE;
@@ -968,9 +970,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;
@@ -1001,7 +1011,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;
@@ -1250,7 +1260,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. */
@@ -1365,10 +1375,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))))
@@ -1407,8 +1421,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
@@ -1439,18 +1454,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
@@ -1553,8 +1570,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,
@@ -1564,6 +1581,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)
{
@@ -1608,8 +1626,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))
+ &hi, oldsecondary, poldbfd, NULL, NULL,
+ &skip, &override, &type_change_ok
+ , &size_change_ok))
return FALSE;
if (skip)
@@ -1723,8 +1742,8 @@ 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))
+ &hi, oldsecondary, poldbfd, NULL, NULL, &skip,
+ &override, &type_change_ok, &size_change_ok))
return FALSE;
if (skip)
@@ -2868,31 +2887,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. */
@@ -2911,9 +2940,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;
@@ -2974,7 +3006,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;
}
}
@@ -3822,6 +3855,7 @@ error_free_dyn:
bfd_boolean common;
unsigned int old_alignment;
bfd *old_bfd;
+ bfd_boolean oldsecondary;
override = FALSE;
@@ -3849,6 +3883,10 @@ error_free_dyn:
flags = BSF_WEAK;
break;
+ case STB_SECONDARY:
+ flags = BSF_SECONDARY;
+ break;
+
case STB_GNU_UNIQUE:
flags = BSF_GNU_UNIQUE;
break;
@@ -4084,7 +4122,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))
goto error_free_vers;
@@ -4104,7 +4142,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,
@@ -4184,10 +4227,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)
@@ -4216,6 +4263,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
@@ -4234,7 +4288,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
@@ -5024,16 +5079,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);
@@ -8807,7 +8873,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 ((flinfo->info->relocatable
+ || (!flinfo->info->executable
+ && 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;
@@ -8938,7 +9018,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);
@@ -8964,10 +9045,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 (!flinfo->info->relocatable
&& 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 1286cc1..b5c5fa2 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -3262,7 +3262,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 abdf5b0..9cb5cc4 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:
@@ -1561,6 +1600,9 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
h->u.def.section = section;
h->u.def.value = value;
+ /* 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 a1d1d77..6077121 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 ecd147e..300fd13 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 7463c55..6596a21 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -9262,6 +9262,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 e2ef99e..ab61461 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},
@@ -443,6 +445,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;
@@ -452,7 +477,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++;
@@ -2194,18 +2220,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
@@ -2419,7 +2451,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 251b6d5..0cf993d 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -4270,6 +4270,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}}
@@ -5952,6 +5953,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 6af8604..87f22d6 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 4c83033..f765aec 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 0000000..e73f6c5
--- /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 0000000..58d5142
--- /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 0000000..df8b7ed
--- /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 0000000..aca59c0
--- /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 0000000..58d5142
--- /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 0000000..37bd0ce
--- /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 f17f7e0..65bb3c5 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -203,6 +203,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_\""
load_lib gas-dg.exp
dg-init
diff --git a/gas/testsuite/gas/elf/secondary1.e b/gas/testsuite/gas/elf/secondary1.e
new file mode 100644
index 0000000..da00dfb
--- /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 0000000..6a3032d
--- /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 0000000..0470eb8
--- /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 0000000..234330a
--- /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 a1159bf..d4c0548 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 d0a1afd..bd7df2c 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 125683d..5565050 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -93,6 +93,9 @@ struct bfd_link_hash_entry
unsigned int non_ir_ref : 1;
+ /* Set if it is a secondary symbol. */
+ unsigned int secondary : 1;
+
/* A union of information depending upon the type. */
union
{
@@ -355,6 +358,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 e8ae3ac..b1e66d4 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -664,6 +664,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 67c437d..d842c5d 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -2326,6 +2326,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
@@ -2453,6 +2455,8 @@ fragment <<EOF
-z relro Create RELRO program header\n"));
fprintf (file, _("\
-z stacksize=SIZE Set size of stack segment\n"));
+ fprintf (file, _("\
+ -z nosecondary Convert secondary symbols to weak symbols\n"));
EOF
fi
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index e71be5e..30dddd4 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1121,6 +1121,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 77235d5..096ce2e 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -279,6 +279,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/testsuite/ld-elf/library1.c b/ld/testsuite/ld-elf/library1.c
new file mode 100644
index 0000000..28e255d
--- /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 0000000..2050e74
--- /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 0000000..271ebd6
--- /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 0000000..ddd3d10
--- /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 0000000..881856e
--- /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 0000000..1ff1840
--- /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 0000000..7e44bb4
--- /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 0000000..f44d97c
--- /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 0000000..7de81b3
--- /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 0000000..528fd89
--- /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 0000000..60f4b92
--- /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 0000000..10cd8bf
--- /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 0000000..5f67848
--- /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 0000000..aa57fde
--- /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 0000000..bcbb4de
--- /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 0000000..29a7508
--- /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 0000000..a593fbd
--- /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 0000000..7de81b3
--- /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 0000000..fc18d1a
--- /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 0000000..dfb6a22
--- /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 0000000..317631f
--- /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
+#...
diff --git a/ld/testsuite/ld-elf/secondary-foo.c b/ld/testsuite/ld-elf/secondary-foo.c
new file mode 100644
index 0000000..8b23ec8
--- /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 0000000..f1cb6b4
--- /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 0000000..6d64ed7
--- /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 0000000..5143262
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary.exp
@@ -0,0 +1,176 @@
+# 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"}
+}
+
+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 0000000..9931c04
--- /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 0000000..8d9378f
--- /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 0000000..89d6d76
--- /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 0000000..ff618a0
--- /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 0000000..93c3469
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary3.rd
@@ -0,0 +1,5 @@
+Symbol table '\.symtab' 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/secondary3a.s b/ld/testsuite/ld-elf/secondary3a.s
new file mode 100644
index 0000000..16a1300
--- /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 0000000..cc6f37b
--- /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 0000000..e84b1a6
--- /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 0000000..a2acf21
--- /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 0000000..a2b2f20
--- /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 0000000..730c35d
--- /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 0000000..2a7e17b
--- /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 0000000..d86bac9
--- /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 0000000..9a67352
--- /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 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary7.out
@@ -0,0 +1 @@
+OK
--
1.9.3