summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/archive.c1
-rw-r--r--bfd/bfd-in2.h4
-rw-r--r--bfd/elf.c10
-rw-r--r--bfd/elf32-mips.c5
-rw-r--r--bfd/elf64-ia64-vms.c4
-rw-r--r--bfd/elfcode.h3
-rw-r--r--bfd/elflink.c177
-rw-r--r--bfd/elfn32-mips.c5
-rw-r--r--bfd/linker.c44
-rw-r--r--bfd/syms.c14
10 files changed, 218 insertions, 49 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 '?';