Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-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 2 of the License, or
-(at your option) any later version.
+ 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 2 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.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
bed->got_symbol_offset, NULL, FALSE, bed->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->def_regular = 1;
h->type = STT_OBJECT;
if (! info->executable
get_elf_backend_data (abfd)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->def_regular = 1;
h->type = STT_OBJECT;
if (! info->executable
flags = bed->dynamic_sec_flags;
pltflags = flags;
- pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
+ /* We do not clear SEC_ALLOC here because we still want the OS to
+ allocate space for the section; it's just that there's nothing
+ to read in from the object file. */
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
+ else
+ pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
FALSE, get_elf_backend_data (abfd)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->def_regular = 1;
h->type = STT_OBJECT;
if (! info->executable
if (h->root.type != bfd_link_hash_undefined
&& h->root.type != bfd_link_hash_undefweak)
{
- h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+ h->forced_local = 1;
return TRUE;
}
h->root.type = bfd_link_hash_new;
if (h->root.type == bfd_link_hash_new)
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
+ h->non_elf = 0;
/* If this symbol is being provided by the linker script, and it is
currently defined by a dynamic object, but not by a regular
object, then mark it as undefined so that the generic linker will
force the correct value. */
if (provide
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ && h->def_dynamic
+ && !h->def_regular)
h->root.type = bfd_link_hash_undefined;
/* If this symbol is not being provided by the linker script, and it is
then clear out any version information because the symbol will not be
associated with the dynamic object any more. */
if (!provide
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ && h->def_dynamic
+ && !h->def_regular)
h->verinfo.verdef = NULL;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->def_regular = 1;
- if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
- | ELF_LINK_HASH_REF_DYNAMIC)) != 0
+ if ((h->def_dynamic
+ || h->ref_dynamic
|| info->shared)
&& h->dynindx == -1)
{
/* If this is a weak defined symbol, and we know a corresponding
real symbol from the same dynamic object, make sure the real
symbol is also made into a dynamic symbol. */
- if (h->weakdef != NULL
- && h->weakdef->dynindx == -1)
+ if (h->u.weakdef != NULL
+ && h->u.weakdef->dynindx == -1)
{
- if (! bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h->u.weakdef))
return FALSE;
}
}
bfd *dynobj = elf_hash_table (info)->dynobj;
if (dynobj != NULL
- && (ip = bfd_get_section_by_name (dynobj, p->name))
- != NULL
+ && (ip = bfd_get_section_by_name (dynobj, p->name)) != NULL
&& (ip->flags & SEC_LINKER_CREATED)
&& ip->output_section == p)
return TRUE;
bfd_boolean *type_change_ok,
bfd_boolean *size_change_ok)
{
- asection *sec;
+ asection *sec, *oldsec;
struct elf_link_hash_entry *h;
struct elf_link_hash_entry *flip;
int bind;
if (h->root.type == bfd_link_hash_new)
{
- h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+ h->non_elf = 0;
return TRUE;
}
- /* OLDBFD is a BFD associated with the existing symbol. */
+ /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
+ existing symbol. */
switch (h->root.type)
{
default:
oldbfd = NULL;
+ oldsec = NULL;
break;
case bfd_link_hash_undefined:
case bfd_link_hash_undefweak:
oldbfd = h->root.u.undef.abfd;
+ oldsec = NULL;
break;
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
oldbfd = h->root.u.def.section->owner;
+ oldsec = h->root.u.def.section;
break;
case bfd_link_hash_common:
oldbfd = h->root.u.c.p->section->owner;
+ oldsec = h->root.u.c.p->section;
break;
}
dynamic object, which we do want to handle here. */
if (abfd == oldbfd
&& ((abfd->flags & DYNAMIC) == 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ || !h->def_regular))
return TRUE;
/* NEWDYN and OLDDYN indicate whether the new or old symbol,
else
olddef = TRUE;
+ /* Check TLS symbol. */
+ if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)
+ && ELF_ST_TYPE (sym->st_info) != h->type)
+ {
+ bfd *ntbfd, *tbfd;
+ bfd_boolean ntdef, tdef;
+ asection *ntsec, *tsec;
+
+ if (h->type == STT_TLS)
+ {
+ ntbfd = abfd;
+ ntsec = sec;
+ ntdef = newdef;
+ tbfd = oldbfd;
+ tsec = oldsec;
+ tdef = olddef;
+ }
+ else
+ {
+ ntbfd = oldbfd;
+ ntsec = oldsec;
+ ntdef = olddef;
+ tbfd = abfd;
+ tsec = sec;
+ tdef = newdef;
+ }
+
+ if (tdef && ntdef)
+ (*_bfd_error_handler)
+ (_("%s: TLS definition in %B section %A mismatches non-TLS definition in %B section %A"),
+ tbfd, tsec, ntbfd, ntsec, h->root.root.string);
+ else if (!tdef && !ntdef)
+ (*_bfd_error_handler)
+ (_("%s: TLS reference in %B mismatches non-TLS reference in %B"),
+ tbfd, ntbfd, h->root.root.string);
+ else if (tdef)
+ (*_bfd_error_handler)
+ (_("%s: TLS definition in %B section %A mismatches non-TLS reference in %B"),
+ tbfd, tsec, ntbfd, h->root.root.string);
+ else
+ (*_bfd_error_handler)
+ (_("%s: TLS reference in %B mismatches non-TLS definition in %B section %A"),
+ tbfd, ntbfd, ntsec, h->root.root.string);
+
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
/* We need to remember if a symbol has a definition in a dynamic
object or is weak in all dynamic objects. Internal and hidden
visibility will make it unavailable to dynamic objects. */
- if (newdyn && (h->elf_link_hash_flags & ELF_LINK_DYNAMIC_DEF) == 0)
+ if (newdyn && !h->dynamic_def)
{
if (!bfd_is_und_section (sec))
- h->elf_link_hash_flags |= ELF_LINK_DYNAMIC_DEF;
+ h->dynamic_def = 1;
else
{
/* Check if this symbol is weak in all dynamic objects. If it
is the first time we see it in a dynamic object, we mark
if it is weak. Otherwise, we clear it. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
+ if (!h->ref_dynamic)
{
if (bind == STB_WEAK)
- h->elf_link_hash_flags |= ELF_LINK_DYNAMIC_WEAK;
+ h->dynamic_weak = 1;
}
else if (bind != STB_WEAK)
- h->elf_link_hash_flags &= ~ELF_LINK_DYNAMIC_WEAK;
+ h->dynamic_weak = 0;
}
}
{
*skip = TRUE;
/* Make sure this symbol is dynamic. */
- h->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
+ h->ref_dynamic = 1;
/* A protected symbol has external availability. Make sure it is
recorded as dynamic.
}
else if (!newdyn
&& ELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
+ && h->def_dynamic)
{
/* If the new symbol with non-default visibility comes from a
relocatable file and the old definition comes from a dynamic
if ((*sym_hash)->root.type == bfd_link_hash_indirect)
h = *sym_hash;
- if ((h->root.und_next || info->hash->undefs_tail == &h->root)
+ if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root)
&& bfd_is_und_section (sec))
{
/* If the new symbol is undefined and the old symbol was
also undefined before, we need to make sure
_bfd_generic_link_add_one_symbol doesn't mess
- up the linker hash table undefs list. Since the old
+ up the linker hash table undefs list. Since the old
definition came from a dynamic object, it is still on the
undefs list. */
h->root.type = bfd_link_hash_undefined;
- /* FIXME: What if the new symbol is weak undefined? */
h->root.u.undef.abfd = abfd;
}
else
h->root.u.undef.abfd = NULL;
}
- if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
+ if (h->def_dynamic)
{
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_DEF_DYNAMIC;
- h->elf_link_hash_flags |= (ELF_LINK_HASH_REF_DYNAMIC
- | ELF_LINK_DYNAMIC_DEF);
+ h->def_dynamic = 0;
+ h->ref_dynamic = 1;
+ h->dynamic_def = 1;
}
/* FIXME: Should we check type and size for protected symbol? */
h->size = 0;
if (olddyn
&& olddef
&& h->root.type == bfd_link_hash_defined
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && h->def_dynamic
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& (h->root.u.def.section->flags & SEC_LOAD) == 0
&& h->size > 0
|| h->type == STT_FUNC)))
&& olddyn
&& olddef
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
+ && h->def_dynamic)
{
/* Change the hash table entry to undefined, and let
_bfd_generic_link_add_one_symbol do the right thing with the
h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
(*bed->elf_backend_copy_indirect_symbol) (bed, flip, h);
flip->root.u.undef.abfd = h->root.u.undef.abfd;
- if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
+ if (h->def_dynamic)
{
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_DEF_DYNAMIC;
- flip->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
+ h->def_dynamic = 0;
+ flip->ref_dynamic = 1;
}
}
h->root.type = bfd_link_hash_indirect;
h->root.u.i.link = (struct bfd_link_hash_entry *) hi;
- if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
+ if (h->def_dynamic)
{
- h->elf_link_hash_flags &=~ ELF_LINK_HASH_DEF_DYNAMIC;
- hi->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
- if (hi->elf_link_hash_flags
- & (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_DEF_REGULAR))
+ h->def_dynamic = 0;
+ hi->ref_dynamic = 1;
+ if (hi->ref_regular
+ || hi->def_regular)
{
if (! bfd_elf_link_record_dynamic_symbol (info, hi))
return FALSE;
if (! dynamic)
{
if (info->shared
- || ((hi->elf_link_hash_flags
- & ELF_LINK_HASH_REF_DYNAMIC) != 0))
+ || hi->ref_dynamic)
*dynsym = TRUE;
}
else
{
- if ((hi->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0)
+ if (hi->ref_regular)
*dynsym = TRUE;
}
}
if (! dynamic)
{
if (info->shared
- || ((hi->elf_link_hash_flags
- & ELF_LINK_HASH_REF_DYNAMIC) != 0))
+ || hi->ref_dynamic)
*dynsym = TRUE;
}
else
{
- if ((hi->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0)
+ if (hi->ref_regular)
*dynsym = TRUE;
}
}
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->dynindx == -1
- && (h->elf_link_hash_flags
- & (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0)
+ && (h->def_regular
+ || h->ref_regular))
{
struct bfd_elf_version_tree *t;
struct bfd_elf_version_expr *d;
/* We only care about symbols defined in shared objects with version
information. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+ if (!h->def_dynamic
+ || h->def_regular
|| h->dynindx == -1
|| h->verinfo.verdef == NULL)
return TRUE;
/* We only need version numbers for symbols defined in regular
objects. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ if (!h->def_regular)
return TRUE;
bed = get_elf_backend_data (sinfo->output_bfd);
if (*p == '\0')
{
if (hidden)
- h->elf_link_hash_flags |= ELF_LINK_HIDDEN;
+ h->hidden = 1;
return TRUE;
}
}
if (hidden)
- h->elf_link_hash_flags |= ELF_LINK_HIDDEN;
+ h->hidden = 1;
}
/* If we don't have a version for this symbol, see if we can find
DEF_REGULAR and REF_REGULAR correctly. This is the only way to
permit a non-ELF file to correctly refer to a symbol defined in
an ELF dynamic object. */
- if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) != 0)
+ if (h->non_elf)
{
while (h->root.type == bfd_link_hash_indirect)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- h->elf_link_hash_flags |= (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR_NONWEAK);
+ {
+ h->ref_regular = 1;
+ h->ref_regular_nonweak = 1;
+ }
else
{
if (h->root.u.def.section->owner != NULL
&& (bfd_get_flavour (h->root.u.def.section->owner)
== bfd_target_elf_flavour))
- h->elf_link_hash_flags |= (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR_NONWEAK);
+ {
+ h->ref_regular = 1;
+ h->ref_regular_nonweak = 1;
+ }
else
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->def_regular = 1;
}
if (h->dynindx == -1
- && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0))
+ && (h->def_dynamic
+ || h->ref_dynamic))
{
if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
{
}
else
{
- /* Unfortunately, ELF_LINK_NON_ELF is only correct if the symbol
+ /* Unfortunately, NON_ELF is only correct if the symbol
was first seen in a non-ELF file. Fortunately, if the symbol
was first seen in an ELF file, we're probably OK unless the
symbol was defined in a non-ELF file. Catch that case here.
a dynamic object, and then later in a non-ELF regular object. */
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ && !h->def_regular
&& (h->root.u.def.section->owner != NULL
? (bfd_get_flavour (h->root.u.def.section->owner)
!= bfd_target_elf_flavour)
: (bfd_is_abs_section (h->root.u.def.section)
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) == 0)))
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ && !h->def_dynamic)))
+ h->def_regular = 1;
}
/* If this is a final link, and the symbol was defined as a common
symbol in a regular object file, and there was no definition in
any dynamic object, then the linker will have allocated space for
- the symbol in a common section but the ELF_LINK_HASH_DEF_REGULAR
+ the symbol in a common section but the DEF_REGULAR
flag will not have been set. */
if (h->root.type == bfd_link_hash_defined
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+ && !h->def_regular
+ && h->ref_regular
+ && !h->def_dynamic
&& (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->def_regular = 1;
/* If -Bsymbolic was used (which means to bind references to global
symbols to the definition within the shared object), and this
need a PLT entry. Likewise, if the symbol has non-default
visibility. If the symbol has hidden or internal visibility, we
will force it local. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
+ if (h->needs_plt
&& eif->info->shared
&& is_elf_hash_table (eif->info->hash)
&& (eif->info->symbolic
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+ && h->def_regular)
{
const struct elf_backend_data *bed;
bfd_boolean force_local;
/* If this is a weak defined symbol in a dynamic object, and we know
the real definition in the dynamic object, copy interesting flags
over to the real definition. */
- if (h->weakdef != NULL)
+ if (h->u.weakdef != NULL)
{
struct elf_link_hash_entry *weakdef;
- weakdef = h->weakdef;
+ weakdef = h->u.weakdef;
if (h->root.type == bfd_link_hash_indirect)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|| h->root.type == bfd_link_hash_defweak);
BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
|| weakdef->root.type == bfd_link_hash_defweak);
- BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
+ BFD_ASSERT (weakdef->def_dynamic);
/* If the real definition is defined by a regular object file,
don't do anything special. See the longer description in
_bfd_elf_adjust_dynamic_symbol, below. */
- if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
- h->weakdef = NULL;
+ if (weakdef->def_regular)
+ h->u.weakdef = NULL;
else
{
const struct elf_backend_data *bed;
to the dynamic symbol table. FIXME: Do we normally need to worry
about symbols which are defined by one dynamic object and
referenced by another one? */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0
- && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
- && (h->weakdef == NULL || h->weakdef->dynindx == -1))))
+ if (!h->needs_plt
+ && (h->def_regular
+ || !h->def_dynamic
+ || (!h->ref_regular
+ && (h->u.weakdef == NULL || h->u.weakdef->dynindx == -1))))
{
h->plt = elf_hash_table (eif->info)->init_offset;
return TRUE;
/* If we've already adjusted this symbol, don't do it again. This
can happen via a recursive call. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
+ if (h->dynamic_adjusted)
return TRUE;
/* Don't look at this symbol again. Note that we must set this
after checking the above conditions, because we may look at a
symbol once, decide not to do anything, and then get called
recursively later after REF_REGULAR is set below. */
- h->elf_link_hash_flags |= ELF_LINK_HASH_DYNAMIC_ADJUSTED;
+ h->dynamic_adjusted = 1;
/* If this is a weak definition, and we know a real definition, and
the real symbol is not itself defined by a regular object file,
wind up at different memory locations. The tzset call will set
_timezone, leaving timezone unchanged. */
- if (h->weakdef != NULL)
+ if (h->u.weakdef != NULL)
{
/* If we get to this point, we know there is an implicit
reference by a regular object file via the weak symbol H.
FIXME: Is this really true? What if the traversal finds
- H->WEAKDEF before it finds H? */
- h->weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+ H->U.WEAKDEF before it finds H? */
+ h->u.weakdef->ref_regular = 1;
- if (! _bfd_elf_adjust_dynamic_symbol (h->weakdef, eif))
+ if (! _bfd_elf_adjust_dynamic_symbol (h->u.weakdef, eif))
return FALSE;
}
code, and the assembly code fails to set the symbol type. */
if (h->size == 0
&& h->type == STT_NOTYPE
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
+ && !h->needs_plt)
(*_bfd_error_handler)
(_("warning: type and size of dynamic symbol `%s' are not defined"),
h->root.root.string);
/* If it was forced local, then clearly it's not dynamic. */
if (h->dynindx == -1)
return FALSE;
- if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
+ if (h->forced_local)
return FALSE;
/* Identify the cases where name binding rules say that a
}
/* If it isn't defined locally, then clearly it's dynamic. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ if (!h->def_regular)
return TRUE;
/* Otherwise, the symbol is dynamic if binding rules don't tell
/* Do nothing. */;
/* If we don't have a definition in a regular file, then we can't
resolve locally. The sym is either undefined or dynamic. */
- else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ else if (!h->def_regular)
return FALSE;
/* Forced local symbols resolve locally. */
- if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ if (h->forced_local)
return TRUE;
/* As do non-dynamic symbols. */
if (! is_elf_hash_table (hash_table))
return FALSE;
+ if (info->warn_shared_textrel && info->shared && tag == DT_TEXTREL)
+ _bfd_error_handler
+ (_("warning: creating a DT_TEXTREL in a shared object."));
+
bed = get_elf_backend_data (hash_table->dynobj);
s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
BFD_ASSERT (s != NULL);
|| !is_elf_hash_table (hash_table)
|| hash_table->root.creator != abfd->xvec)
{
- bfd_set_error (bfd_error_invalid_operation);
+ if (info->relocatable)
+ bfd_set_error (bfd_error_invalid_operation);
+ else
+ bfd_set_error (bfd_error_wrong_format);
goto error_return;
}
}
&& (flags & BSF_WEAK) != 0
&& ELF_ST_TYPE (isym->st_info) != STT_FUNC
&& is_elf_hash_table (hash_table)
- && h->weakdef == NULL)
+ && h->u.weakdef == NULL)
{
/* Keep a list of all weak defined non function symbols from
a dynamic object, using the weakdef field. Later in this
dynamic object, and we will be using that previous
definition anyhow. */
- h->weakdef = weaks;
+ h->u.weakdef = weaks;
weaks = h;
new_weakdef = TRUE;
}
if (is_elf_hash_table (hash_table))
{
- int old_flags;
bfd_boolean dynsym;
- int new_flag;
/* Check the alignment when a common symbol is involved. This
can change when a common symbol is overridden by a normal
(*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
dynamic);
+ /* If this symbol has default visibility and the user has requested
+ we not re-export it, then mark it as hidden. */
+ if (definition && !dynamic
+ && (abfd->no_export
+ || (abfd->my_archive && abfd->my_archive->no_export))
+ && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
+ isym->st_other = STV_HIDDEN | (isym->st_other & ~ ELF_ST_VISIBILITY (-1));
+
if (isym->st_other != 0 && !dynamic)
{
unsigned char hvis, symvis, other, nvis;
the number of dynamic symbols we find. A dynamic symbol
is one which is referenced or defined by both a regular
object and a shared object. */
- old_flags = h->elf_link_hash_flags;
dynsym = FALSE;
if (! dynamic)
{
if (! definition)
{
- new_flag = ELF_LINK_HASH_REF_REGULAR;
+ h->ref_regular = 1;
if (bind != STB_WEAK)
- new_flag |= ELF_LINK_HASH_REF_REGULAR_NONWEAK;
+ h->ref_regular_nonweak = 1;
}
else
- new_flag = ELF_LINK_HASH_DEF_REGULAR;
+ h->def_regular = 1;
if (! info->executable
- || (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
- | ELF_LINK_HASH_REF_DYNAMIC)) != 0)
+ || h->def_dynamic
+ || h->ref_dynamic)
dynsym = TRUE;
}
else
{
if (! definition)
- new_flag = ELF_LINK_HASH_REF_DYNAMIC;
+ h->ref_dynamic = 1;
else
- new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
- if ((old_flags & (ELF_LINK_HASH_DEF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR)) != 0
- || (h->weakdef != NULL
+ h->def_dynamic = 1;
+ if (h->def_regular
+ || h->ref_regular
+ || (h->u.weakdef != NULL
&& ! new_weakdef
- && h->weakdef->dynindx != -1))
+ && h->u.weakdef->dynindx != -1))
dynsym = TRUE;
}
- h->elf_link_hash_flags |= new_flag;
-
/* Check to see if we need to add an indirect symbol for
the default name. */
if (definition || h->root.type == bfd_link_hash_common)
{
if (! bfd_elf_link_record_dynamic_symbol (info, h))
goto error_free_vers;
- if (h->weakdef != NULL
+ if (h->u.weakdef != NULL
&& ! new_weakdef
- && h->weakdef->dynindx == -1)
+ && h->u.weakdef->dynindx == -1)
{
- if (! bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h->u.weakdef))
goto error_free_vers;
}
}
if (!add_needed
&& definition
&& dynsym
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0)
+ && h->ref_regular)
{
int ret;
const char *soname = elf_dt_name (abfd);
size_t i, j, idx;
hlook = weaks;
- weaks = hlook->weakdef;
- hlook->weakdef = NULL;
+ weaks = hlook->u.weakdef;
+ hlook->u.weakdef = NULL;
BFD_ASSERT (hlook->root.type == bfd_link_hash_defined
|| hlook->root.type == bfd_link_hash_defweak
break;
else if (h != hlook)
{
- hlook->weakdef = h;
+ hlook->u.weakdef = h;
/* If the weak definition is in the list of dynamic
symbols, make sure the real definition is put
/* And store it in the struct so that we can put it in the hash table
later. */
- h->elf_hash_value = ha;
+ h->u.elf_hash_value = ha;
if (alc != NULL)
free (alc);
/* Mark this version if there is a definition and it is
not defined in a shared object. */
if (newh != NULL
- && ((newh->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) == 0)
+ && !newh->def_dynamic
&& (newh->root.type == bfd_link_hash_defined
|| newh->root.type == bfd_link_hash_defweak))
d->symver = 1;
return FALSE;
/* Add some entries to the .dynamic section. We fill in some of the
- values later, in elf_bfd_final_link, but we must add the entries
+ values later, in bfd_elf_final_link, but we must add the entries
now so that we know the final size of the .dynamic section. */
/* If there are initialization and/or finalization functions to
FALSE, FALSE)
: NULL);
if (h != NULL
- && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_DEF_REGULAR)) != 0)
+ && (h->ref_regular
+ || h->def_regular))
{
if (!_bfd_elf_add_dynamic_entry (info, DT_INIT, 0))
return FALSE;
FALSE, FALSE)
: NULL);
if (h != NULL
- && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_DEF_REGULAR)) != 0)
+ && (h->ref_regular
+ || h->def_regular))
{
if (!_bfd_elf_add_dynamic_entry (info, DT_FINI, 0))
return FALSE;
get_elf_backend_data (dynobj)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->non_elf = 0;
+ h->def_regular = 1;
h->type = STT_OBJECT;
h->verinfo.vertree = t;
bfd_byte *erel, *erelend;
asection *o = lo->u.indirect.section;
+ if (o->contents == NULL && o->size != 0)
+ {
+ /* This is a reloc section that is being handled as a normal
+ section. See bfd_section_from_shdr. We can't combine
+ relocs in this case. */
+ free (sort);
+ return 0;
+ }
erel = o->contents;
erelend = o->contents + o->size;
p = sort + o->output_offset / ext_size * sort_elt;
/* Decide whether to output this symbol in this pass. */
if (eoinfo->localsyms)
{
- if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ if (!h->forced_local)
return TRUE;
}
else
{
- if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ if (h->forced_local)
return TRUE;
}
references in regular files have already been handled). If we
are reporting errors for this situation then do so now. */
if (h->root.type == bfd_link_hash_undefined
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+ && h->ref_dynamic
+ && !h->ref_regular
&& ! elf_link_check_versioned_symbol (finfo->info, bed, h)
&& finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
{
shared libraries. */
if (! finfo->info->relocatable
&& (! finfo->info->shared)
- && (h->elf_link_hash_flags
- & (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_DYNAMIC_DEF | ELF_LINK_DYNAMIC_WEAK))
- == (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC)
+ && h->forced_local
+ && h->ref_dynamic
+ && !h->dynamic_def
+ && !h->dynamic_weak
&& ! elf_link_check_versioned_symbol (finfo->info, bed, h))
{
(*_bfd_error_handler)
output it. */
if (h->indx == -2)
strip = FALSE;
- else if (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+ else if ((h->def_dynamic
+ || h->ref_dynamic)
+ && !h->def_regular
+ && !h->ref_regular)
strip = TRUE;
else if (finfo->info->strip == strip_all)
strip = TRUE;
nothing else to do unless it is a forced local symbol. */
if (strip
&& h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ && !h->forced_local)
return TRUE;
sym.st_value = 0;
sym.st_size = h->size;
sym.st_other = h->other;
- if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ if (h->forced_local)
sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
else if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_defweak)
symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for
forced local syms when non-shared is due to a historical quirk. */
if ((h->dynindx != -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ || h->forced_local)
&& ((finfo->info->shared
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ || !h->forced_local)
&& elf_hash_table (finfo->info)->dynamic_sections_created)
{
if (! ((*bed->elf_backend_finish_dynamic_symbol)
because it might not be marked as undefined until the
finish_dynamic_symbol routine gets through with it. */
if (sym.st_shndx == SHN_UNDEF
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
+ && h->ref_regular
&& (ELF_ST_BIND (sym.st_info) == STB_GLOBAL
|| ELF_ST_BIND (sym.st_info) == STB_WEAK))
{
int bindtype;
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) != 0)
+ if (h->ref_regular_nonweak)
bindtype = STB_GLOBAL;
else
bindtype = STB_WEAK;
&& ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT
&& ELF_ST_BIND (sym.st_info) != STB_WEAK
&& h->root.type == bfd_link_hash_undefined
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ && !h->def_regular)
{
(*_bfd_error_handler)
(_("%B: %s symbol `%s' isn't defined"),
bed->s->swap_symbol_out (finfo->output_bfd, &sym, esym, 0);
bucketcount = elf_hash_table (finfo->info)->bucketcount;
- bucket = h->elf_hash_value % bucketcount;
+ bucket = h->u.elf_hash_value % bucketcount;
hash_entry_size
= elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize;
bucketpos = ((bfd_byte *) finfo->hash_sec->contents
Elf_Internal_Versym iversym;
Elf_External_Versym *eversym;
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ if (!h->def_regular)
{
if (h->verinfo.verdef == NULL)
iversym.vs_vers = 0;
iversym.vs_vers = h->verinfo.vertree->vernum + 1;
}
- if ((h->elf_link_hash_flags & ELF_LINK_HIDDEN) != 0)
+ if (h->hidden)
iversym.vs_vers |= VERSYM_HIDDEN;
eversym = (Elf_External_Versym *) finfo->symver_sec->contents;
return FALSE;
}
-/* Return TRUE if we should complain about a reloc in SEC against a
- symbol defined in a discarded section. */
-
-static bfd_boolean
-elf_section_complain_discarded (asection *sec)
+enum action_discarded
+ {
+ COMPLAIN = 1,
+ PRETEND = 2
+ };
+
+/* Return a mask saying how ld should treat relocations in SEC against
+ symbols defined in discarded sections. If this function returns
+ COMPLAIN set, ld will issue a warning message. If this function
+ returns PRETEND set, and the discarded section was link-once and the
+ same size as the kept link-once section, ld will pretend that the
+ symbol was actually defined in the kept section. Otherwise ld will
+ zero the reloc (at least that is the intent, but some cooperation by
+ the target dependent code is needed, particularly for REL targets). */
+
+static unsigned int
+elf_action_discarded (asection *sec)
{
- if (strncmp (".stab", sec->name, 5) == 0
- && (!sec->name[5] ||
- (sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
- return FALSE;
+ if (sec->flags & SEC_DEBUGGING)
+ return PRETEND;
if (strcmp (".eh_frame", sec->name) == 0)
- return FALSE;
+ return 0;
if (strcmp (".gcc_except_table", sec->name) == 0)
- return FALSE;
+ return 0;
if (strcmp (".PARISC.unwind", sec->name) == 0)
- return FALSE;
+ return 0;
if (strcmp (".fixup", sec->name) == 0)
- return FALSE;
+ return 0;
- return TRUE;
+ return COMPLAIN | PRETEND;
}
/* Find a match between a section and a member of a section group. */
if (!elf_section_ignore_discarded_relocs (o))
{
Elf_Internal_Rela *rel, *relend;
- bfd_boolean complain = elf_section_complain_discarded (o);
+ unsigned int action = elf_action_discarded (o);
rel = internal_relocs;
relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
struct elf_link_hash_entry *h = NULL;
const char *sym_name;
+ if (r_symndx == STN_UNDEF)
+ continue;
+
if (r_symndx >= locsymcount
|| (elf_bad_symtab (input_bfd)
&& finfo->sections[r_symndx] == NULL))
discarded section. */
if ((sec = *ps) != NULL && elf_discarded_section (sec))
{
- if ((o->flags & SEC_DEBUGGING) != 0)
- {
- BFD_ASSERT (r_symndx != 0);
-
- /* Try to preserve debug information.
- FIXME: This is quite broken. Modifying
- the symbol here means we will be changing
- all uses of the symbol, not just those in
- debug sections. The only thing that makes
- this half reasonable is that debug sections
- tend to come after other sections. Of
- course, that doesn't help with globals.
- ??? All link-once sections of the same name
- ought to define the same set of symbols, so
- it would seem that globals ought to always
- be defined in the kept section. */
- if (sec->kept_section != NULL)
- {
- asection *member;
+ asection *kept;
- /* Check if it is a linkonce section or
- member of a comdat group. */
- if (elf_sec_group (sec) == NULL
- && sec->size == sec->kept_section->size)
- {
- *ps = sec->kept_section;
- continue;
- }
- else if (elf_sec_group (sec) != NULL
- && (member = match_group_member (sec, sec->kept_section))
- && sec->size == member->size)
- {
- *ps = member;
- continue;
- }
- }
- }
- else if (complain)
+ BFD_ASSERT (r_symndx != 0);
+ if (action & COMPLAIN)
{
(*_bfd_error_handler)
(_("`%s' referenced in section `%A' of %B: "
o, input_bfd, sec, sec->owner, sym_name);
}
+ /* Try to do the best we can to support buggy old
+ versions of gcc. If we've warned, or this is
+ debugging info, pretend that the symbol is
+ really defined in the kept linkonce section.
+ FIXME: This is quite broken. Modifying the
+ symbol here means we will be changing all later
+ uses of the symbol, not just in this section.
+ The only thing that makes this half reasonable
+ is that we warn in non-debug sections, and
+ debug sections tend to come after other
+ sections. */
+ kept = sec->kept_section;
+ if (kept != NULL && (action & PRETEND))
+ {
+ if (elf_sec_group (sec) != NULL)
+ kept = match_group_member (sec, kept);
+ if (kept != NULL
+ && sec->size == kept->size)
+ {
+ *ps = kept;
+ continue;
+ }
+ }
+
/* Remove the symbol reference from the reloc, but
don't kill the reloc completely. This is so that
a zero value will be written into the section,
symbol. We set the rel_hash entry for this
reloc to point to the global hash table entry
for this symbol. The symbol index is then
- set at the end of elf_bfd_final_link. */
+ set at the end of bfd_elf_final_link. */
indx = r_symndx - extsymoff;
rh = elf_sym_hashes (input_bfd)[indx];
while (rh->root.type == bfd_link_hash_indirect
else
sym_name = link_order->u.reloc.p->u.name;
if (! ((*info->callbacks->reloc_overflow)
- (info, sym_name, howto->name, addend, NULL, NULL, 0)))
+ (info, NULL, sym_name, howto->name, addend, NULL,
+ NULL, (bfd_vma) 0)))
{
free (buf);
return FALSE;
if (! _bfd_elf_compute_section_file_positions (abfd, info))
goto error_return;
- /* That created the reloc sections. Set their sizes, and assign
- them file positions, and allocate some buffers. */
+ /* Set sizes, and assign file positions for reloc sections. */
for (o = abfd->sections; o != NULL; o = o->next)
{
if ((o->flags & SEC_RELOC) != 0)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
/* Those that are not vtables. */
- if (h->vtable_parent == NULL)
+ if (h->vtable == NULL || h->vtable->parent == NULL)
return TRUE;
/* Those vtables that do not have parents, we cannot merge. */
- if (h->vtable_parent == (struct elf_link_hash_entry *) -1)
+ if (h->vtable->parent == (struct elf_link_hash_entry *) -1)
return TRUE;
/* If we've already been done, exit. */
- if (h->vtable_entries_used && h->vtable_entries_used[-1])
+ if (h->vtable->used && h->vtable->used[-1])
return TRUE;
/* Make sure the parent's table is up to date. */
- elf_gc_propagate_vtable_entries_used (h->vtable_parent, okp);
+ elf_gc_propagate_vtable_entries_used (h->vtable->parent, okp);
- if (h->vtable_entries_used == NULL)
+ if (h->vtable->used == NULL)
{
/* None of this table's entries were referenced. Re-use the
parent's table. */
- h->vtable_entries_used = h->vtable_parent->vtable_entries_used;
- h->vtable_entries_size = h->vtable_parent->vtable_entries_size;
+ h->vtable->used = h->vtable->parent->vtable->used;
+ h->vtable->size = h->vtable->parent->vtable->size;
}
else
{
bfd_boolean *cu, *pu;
/* Or the parent's entries into ours. */
- cu = h->vtable_entries_used;
+ cu = h->vtable->used;
cu[-1] = TRUE;
- pu = h->vtable_parent->vtable_entries_used;
+ pu = h->vtable->parent->vtable->used;
if (pu != NULL)
{
const struct elf_backend_data *bed;
bed = get_elf_backend_data (h->root.u.def.section->owner);
log_file_align = bed->s->log_file_align;
- n = h->vtable_parent->vtable_entries_size >> log_file_align;
+ n = h->vtable->parent->vtable->size >> log_file_align;
while (n--)
{
if (*pu)
/* Take care of both those symbols that do not describe vtables as
well as those that are not loaded. */
- if (h->vtable_parent == NULL)
+ if (h->vtable == NULL || h->vtable->parent == NULL)
return TRUE;
BFD_ASSERT (h->root.type == bfd_link_hash_defined
if (rel->r_offset >= hstart && rel->r_offset < hend)
{
/* If the entry is in use, do nothing. */
- if (h->vtable_entries_used
- && (rel->r_offset - hstart) < h->vtable_entries_size)
+ if (h->vtable->used
+ && (rel->r_offset - hstart) < h->vtable->size)
{
bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
- if (h->vtable_entries_used[entry])
+ if (h->vtable->used[entry])
continue;
}
/* Otherwise, kill it. */
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC))
+ && h->ref_dynamic)
h->root.u.def.section->flags |= SEC_KEEP;
return TRUE;
return FALSE;
win:
+ if (!child->vtable)
+ {
+ child->vtable = bfd_zalloc (abfd, sizeof (*child->vtable));
+ if (!child->vtable)
+ return FALSE;
+ }
if (!h)
{
/* This *should* only be the absolute section. It could potentially
would be bad. It isn't worth paging in the local symbols to be
sure though; that case should simply be handled by the assembler. */
- child->vtable_parent = (struct elf_link_hash_entry *) -1;
+ child->vtable->parent = (struct elf_link_hash_entry *) -1;
}
else
- child->vtable_parent = h;
+ child->vtable->parent = h;
return TRUE;
}
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
unsigned int log_file_align = bed->s->log_file_align;
- if (addend >= h->vtable_entries_size)
+ if (!h->vtable)
+ {
+ h->vtable = bfd_zalloc (abfd, sizeof (*h->vtable));
+ if (!h->vtable)
+ return FALSE;
+ }
+
+ if (addend >= h->vtable->size)
{
size_t size, bytes, file_align;
- bfd_boolean *ptr = h->vtable_entries_used;
+ bfd_boolean *ptr = h->vtable->used;
/* While the symbol is undefined, we have to be prepared to handle
a zero size. */
{
size_t oldbytes;
- oldbytes = (((h->vtable_entries_size >> log_file_align) + 1)
+ oldbytes = (((h->vtable->size >> log_file_align) + 1)
* sizeof (bfd_boolean));
memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
}
return FALSE;
/* And arrange for that done flag to be at index -1. */
- h->vtable_entries_used = ptr + 1;
- h->vtable_entries_size = size;
+ h->vtable->used = ptr + 1;
+ h->vtable->size = size;
}
- h->vtable_entries_used[addend >> log_file_align] = TRUE;
+ h->vtable->used[addend >> log_file_align] = TRUE;
return TRUE;
}
return ret;
}
-struct already_linked_section
-{
- asection *sec;
- asection *linked;
-};
-
-/* Check if the member of a single member comdat group matches a
- linkonce section and vice versa. */
-static bfd_boolean
-try_match_symbols_in_sections
- (struct bfd_section_already_linked_hash_entry *h, void *info)
-{
- struct bfd_section_already_linked *l;
- struct already_linked_section *s
- = (struct already_linked_section *) info;
-
- if (elf_sec_group (s->sec) == NULL)
- {
- /* It is a linkonce section. Try to match it with the member of a
- single member comdat group. */
- for (l = h->entry; l != NULL; l = l->next)
- if ((l->sec->flags & SEC_GROUP))
- {
- asection *first = elf_next_in_group (l->sec);
-
- if (first != NULL
- && elf_next_in_group (first) == first
- && bfd_elf_match_symbols_in_sections (first, s->sec))
- {
- s->linked = first;
- return FALSE;
- }
- }
- }
- else
- {
- /* It is the member of a single member comdat group. Try to match
- it with a linkonce section. */
- for (l = h->entry; l != NULL; l = l->next)
- if ((l->sec->flags & SEC_GROUP) == 0
- && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL
- && bfd_elf_match_symbols_in_sections (l->sec, s->sec))
- {
- s->linked = l->sec;
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static bfd_boolean
-already_linked (asection *sec, asection *group)
-{
- struct already_linked_section result;
-
- result.sec = sec;
- result.linked = NULL;
-
- bfd_section_already_linked_table_traverse
- (try_match_symbols_in_sections, &result);
-
- if (result.linked)
- {
- sec->output_section = bfd_abs_section_ptr;
- sec->kept_section = result.linked;
-
- /* Also discard the group section. */
- if (group)
- group->output_section = bfd_abs_section_ptr;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
void
_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
{
flagword flags;
- const char *name;
+ const char *name, *p;
struct bfd_section_already_linked *l;
struct bfd_section_already_linked_hash_entry *already_linked_list;
asection *group;
name = bfd_get_section_name (abfd, sec);
- already_linked_list = bfd_section_already_linked_table_lookup (name);
+ if (strncmp (name, ".gnu.linkonce.", sizeof (".gnu.linkonce.") - 1) == 0
+ && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+ p++;
+ else
+ p = name;
+
+ already_linked_list = bfd_section_already_linked_table_lookup (p);
for (l = already_linked_list->entry; l != NULL; l = l->next)
{
a linkonce section with a linkonce section, and ignore comdat
section. */
if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+ && strcmp (name, l->sec->name) == 0
&& bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
{
/* The section has already been linked. See if we should
- issue a warning. */
+ issue a warning. */
switch (flags & SEC_LINK_DUPLICATES)
{
default:
section. We only record the discarded comdat group. Otherwise
the undiscarded group will be discarded incorrectly later since
itself has been recorded. */
- if (! already_linked (elf_next_in_group (sec), group))
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
+ if ((l->sec->flags & SEC_GROUP) == 0
+ && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL
+ && bfd_elf_match_symbols_in_sections (l->sec,
+ elf_next_in_group (sec)))
+ {
+ elf_next_in_group (sec)->output_section = bfd_abs_section_ptr;
+ elf_next_in_group (sec)->kept_section = l->sec;
+ group->output_section = bfd_abs_section_ptr;
+ break;
+ }
+ if (l == NULL)
return;
}
else
/* There is no direct match. But for linkonce section, we should
check if there is a match with comdat group member. We always
record the linkonce section, discarded or not. */
- already_linked (sec, group);
-
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
+ if (l->sec->flags & SEC_GROUP)
+ {
+ asection *first = elf_next_in_group (l->sec);
+
+ if (first != NULL
+ && elf_next_in_group (first) == first
+ && bfd_elf_match_symbols_in_sections (first, sec))
+ {
+ sec->output_section = bfd_abs_section_ptr;
+ sec->kept_section = l->sec;
+ break;
+ }
+ }
+
/* This is the first section with this name. Record it. */
bfd_section_already_linked_table_insert (already_linked_list, sec);
}