/* ELF linking support for BFD.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009
+ 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
return NULL;
h = (struct elf_link_hash_entry *) bh;
h->def_regular = 1;
+ h->non_elf = 0;
h->type = STT_OBJECT;
h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
_bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
{
flagword flags;
- register asection *s;
+ asection *s;
const struct elf_backend_data *bed;
if (! is_elf_hash_table (info->hash))
if (provide && hidden)
{
- const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
-
+ bed = get_elf_backend_data (output_bfd);
h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
}
break;
}
+ /* Differentiate strong and weak symbols. */
+ newweak = bind == STB_WEAK;
+ oldweak = (h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_undefweak);
+
/* In cases involving weak versioned symbols, we may wind up trying
to merge a symbol with itself. Catch that here, to avoid the
confusion that results if we try to override a symbol with
_GLOBAL_OFFSET_TABLE_, which are regular symbols defined in a
dynamic object, which we do want to handle here. */
if (abfd == oldbfd
+ && (newweak || oldweak)
&& ((abfd->flags & DYNAMIC) == 0
|| !h->def_regular))
return TRUE;
was referenced before. */
if (h->ref_regular)
{
- const struct elf_backend_data *bed
- = get_elf_backend_data (abfd);
struct elf_link_hash_entry *vh = *sym_hash;
+
vh->root.type = h->root.type;
h->root.type = bfd_link_hash_indirect;
(*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
return TRUE;
}
- /* Differentiate strong and weak symbols. */
- newweak = bind == STB_WEAK;
- oldweak = (h->root.type == bfd_link_hash_defweak
- || h->root.type == bfd_link_hash_undefweak);
-
if (bind == STB_GNU_UNIQUE)
h->unique_global = 1;
/* Handle the case where we had a versioned symbol in a dynamic
library and now find a definition in a normal object. In this
case, we make the versioned symbol point to the normal one. */
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
flip->root.type = h->root.type;
flip->root.u.undef.abfd = h->root.u.undef.abfd;
h->root.type = bfd_link_hash_indirect;
{
if (! dynamic)
{
- if (info->shared
+ if (! info->executable
|| hi->ref_dynamic)
*dynsym = TRUE;
}
{
if (! dynamic)
{
- if (info->shared
+ if (! info->executable
|| hi->ref_dynamic)
*dynsym = TRUE;
}
return FALSE;
}
}
- else if (r_symndx != 0)
+ else if (r_symndx != STN_UNDEF)
{
(*_bfd_error_handler)
(_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'"
according to the KEEP_MEMORY argument. If O has two relocation
sections (both REL and RELA relocations), then the REL_HDR
relocations will appear first in INTERNAL_RELOCS, followed by the
- REL_HDR2 relocations. */
+ RELA_HDR relocations. */
Elf_Internal_Rela *
_bfd_elf_link_read_relocs (bfd *abfd,
Elf_Internal_Rela *internal_relocs,
bfd_boolean keep_memory)
{
- Elf_Internal_Shdr *rel_hdr;
void *alloc1 = NULL;
Elf_Internal_Rela *alloc2 = NULL;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
+ Elf_Internal_Rela *internal_rela_relocs;
- if (elf_section_data (o)->relocs != NULL)
- return elf_section_data (o)->relocs;
+ if (esdo->relocs != NULL)
+ return esdo->relocs;
if (o->reloc_count == 0)
return NULL;
- rel_hdr = &elf_section_data (o)->rel_hdr;
-
if (internal_relocs == NULL)
{
bfd_size_type size;
if (external_relocs == NULL)
{
- bfd_size_type size = rel_hdr->sh_size;
+ bfd_size_type size = 0;
+
+ if (esdo->rel.hdr)
+ size += esdo->rel.hdr->sh_size;
+ if (esdo->rela.hdr)
+ size += esdo->rela.hdr->sh_size;
- if (elf_section_data (o)->rel_hdr2)
- size += elf_section_data (o)->rel_hdr2->sh_size;
alloc1 = bfd_malloc (size);
if (alloc1 == NULL)
goto error_return;
external_relocs = alloc1;
}
- if (!elf_link_read_relocs_from_section (abfd, o, rel_hdr,
- external_relocs,
- internal_relocs))
- goto error_return;
- if (elf_section_data (o)->rel_hdr2
- && (!elf_link_read_relocs_from_section
- (abfd, o,
- elf_section_data (o)->rel_hdr2,
- ((bfd_byte *) external_relocs) + rel_hdr->sh_size,
- internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr)
- * bed->s->int_rels_per_ext_rel))))
+ internal_rela_relocs = internal_relocs;
+ if (esdo->rel.hdr)
+ {
+ if (!elf_link_read_relocs_from_section (abfd, o, esdo->rel.hdr,
+ external_relocs,
+ internal_relocs))
+ goto error_return;
+ external_relocs = (((bfd_byte *) external_relocs)
+ + esdo->rel.hdr->sh_size);
+ internal_rela_relocs += (NUM_SHDR_ENTRIES (esdo->rel.hdr)
+ * bed->s->int_rels_per_ext_rel);
+ }
+
+ if (esdo->rela.hdr
+ && (!elf_link_read_relocs_from_section (abfd, o, esdo->rela.hdr,
+ external_relocs,
+ internal_rela_relocs)))
goto error_return;
/* Cache the results for next time, if we can. */
if (keep_memory)
- elf_section_data (o)->relocs = internal_relocs;
+ esdo->relocs = internal_relocs;
if (alloc1 != NULL)
free (alloc1);
static bfd_boolean
_bfd_elf_link_size_reloc_section (bfd *abfd,
- Elf_Internal_Shdr *rel_hdr,
- asection *o)
+ struct bfd_elf_section_reloc_data *reldata)
{
- bfd_size_type reloc_count;
- bfd_size_type num_rel_hashes;
-
- /* Figure out how many relocations there will be. */
- if (rel_hdr == &elf_section_data (o)->rel_hdr)
- reloc_count = elf_section_data (o)->rel_count;
- else
- reloc_count = elf_section_data (o)->rel_count2;
-
- num_rel_hashes = o->reloc_count;
- if (num_rel_hashes < reloc_count)
- num_rel_hashes = reloc_count;
+ Elf_Internal_Shdr *rel_hdr = reldata->hdr;
/* That allows us to calculate the size of the section. */
- rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count;
+ rel_hdr->sh_size = rel_hdr->sh_entsize * reldata->count;
/* The contents field must last into write_object_contents, so we
allocate it with bfd_alloc rather than malloc. Also since we
if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
return FALSE;
- /* We only allocate one set of hash entries, so we only do it the
- first time we are called. */
- if (elf_section_data (o)->rel_hashes == NULL
- && num_rel_hashes)
+ if (reldata->hashes == NULL && reldata->count)
{
struct elf_link_hash_entry **p;
p = (struct elf_link_hash_entry **)
- bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *));
+ bfd_zmalloc (reldata->count * sizeof (struct elf_link_hash_entry *));
if (p == NULL)
return FALSE;
- elf_section_data (o)->rel_hashes = p;
+ reldata->hashes = p;
}
return TRUE;
Elf_Internal_Rela *irela;
Elf_Internal_Rela *irelaend;
bfd_byte *erel;
- Elf_Internal_Shdr *output_rel_hdr;
+ struct bfd_elf_section_reloc_data *output_reldata;
asection *output_section;
- unsigned int *rel_countp = NULL;
const struct elf_backend_data *bed;
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
+ struct bfd_elf_section_data *esdo;
output_section = input_section->output_section;
- output_rel_hdr = NULL;
- if (elf_section_data (output_section)->rel_hdr.sh_entsize
- == input_rel_hdr->sh_entsize)
+ bed = get_elf_backend_data (output_bfd);
+ esdo = elf_section_data (output_section);
+ if (esdo->rel.hdr && esdo->rel.hdr->sh_entsize == input_rel_hdr->sh_entsize)
{
- output_rel_hdr = &elf_section_data (output_section)->rel_hdr;
- rel_countp = &elf_section_data (output_section)->rel_count;
+ output_reldata = &esdo->rel;
+ swap_out = bed->s->swap_reloc_out;
}
- else if (elf_section_data (output_section)->rel_hdr2
- && (elf_section_data (output_section)->rel_hdr2->sh_entsize
- == input_rel_hdr->sh_entsize))
+ else if (esdo->rela.hdr
+ && esdo->rela.hdr->sh_entsize == input_rel_hdr->sh_entsize)
{
- output_rel_hdr = elf_section_data (output_section)->rel_hdr2;
- rel_countp = &elf_section_data (output_section)->rel_count2;
+ output_reldata = &esdo->rela;
+ swap_out = bed->s->swap_reloca_out;
}
else
{
return FALSE;
}
- bed = get_elf_backend_data (output_bfd);
- if (input_rel_hdr->sh_entsize == bed->s->sizeof_rel)
- swap_out = bed->s->swap_reloc_out;
- else if (input_rel_hdr->sh_entsize == bed->s->sizeof_rela)
- swap_out = bed->s->swap_reloca_out;
- else
- abort ();
-
- erel = output_rel_hdr->contents;
- erel += *rel_countp * input_rel_hdr->sh_entsize;
+ erel = output_reldata->hdr->contents;
+ erel += output_reldata->count * input_rel_hdr->sh_entsize;
irela = internal_relocs;
irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
* bed->s->int_rels_per_ext_rel);
/* Bump the counter, so that we know where to add the next set of
relocations. */
- *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr);
+ output_reldata->count += NUM_SHDR_ENTRIES (input_rel_hdr);
return TRUE;
}
bfd_boolean
_bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
struct bfd_link_info *info,
- bfd_boolean ignore_protected)
+ bfd_boolean not_local_protected)
{
bfd_boolean binding_stays_local_p;
const struct elf_backend_data *bed;
/* Proper resolution for function pointer equality may require
that these symbols perhaps be resolved dynamically, even though
we should be resolving them to the current module. */
- if (!ignore_protected || !bed->is_function_type (h->type))
+ if (!not_local_protected || !bed->is_function_type (h->type))
binding_stays_local_p = TRUE;
break;
}
/* If it isn't defined locally, then clearly it's dynamic. */
- if (!h->def_regular)
+ if (!h->def_regular && !ELF_COMMON_DEF_P (h))
return TRUE;
/* Otherwise, the symbol is dynamic if binding rules don't tell
/* Return true if the symbol referred to by H should be considered
to resolve local to the current module, and false otherwise. Differs
from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of
- undefined symbols and weak symbols. */
+ undefined symbols. The two functions are virtually identical except
+ for the place where forced_local and dynindx == -1 are tested. If
+ either of those tests are true, _bfd_elf_dynamic_symbol_p will say
+ the symbol is local, while _bfd_elf_symbol_refs_local_p will say
+ the symbol is local only for defined symbols.
+ It might seem that _bfd_elf_dynamic_symbol_p could be rewritten as
+ !_bfd_elf_symbol_refs_local_p, except that targets differ in their
+ treatment of undefined weak symbols. For those that do not make
+ undefined weak symbols dynamic, both functions may return false. */
bfd_boolean
_bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
bfd_boolean common;
unsigned int old_alignment;
bfd *old_bfd;
+ bfd * undef_bfd = NULL;
override = FALSE;
unsigned int vernum = 0;
bfd_boolean skip;
+ /* If this is a definition of a symbol which was previously
+ referenced in a non-weak manner then make a note of the bfd
+ that contained the reference. This is used if we need to
+ refer to the source of the reference later on. */
+ if (! bfd_is_und_section (sec))
+ {
+ h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+
+ if (h != NULL
+ && h->root.type == bfd_link_hash_undefined
+ && h->root.u.undef.abfd)
+ undef_bfd = h->root.u.undef.abfd;
+ }
+
if (ever == NULL)
{
if (info->default_imported_symver)
name = newname;
}
+ /* If necessary, make a second attempt to locate the bfd
+ containing an unresolved, non-weak reference to the
+ current symbol. */
+ if (! bfd_is_und_section (sec) && undef_bfd == NULL)
+ {
+ h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+
+ if (h != NULL
+ && h->root.type == bfd_link_hash_undefined
+ && h->root.u.undef.abfd)
+ undef_bfd = h->root.u.undef.abfd;
+ }
+
if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
&value, &old_alignment,
sym_hash, &skip, &override,
h = (struct elf_link_hash_entry *) h->root.u.i.link;
*sym_hash = h;
- h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
+ if (is_elf_hash_table (htab))
+ h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
new_weakdef = FALSE;
if (dynamic
if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
{
/* We don't want to make debug symbol dynamic. */
- (*bed->elf_backend_hide_symbol) (info, h, TRUE);
dynsym = FALSE;
}
+ if (definition)
+ h->target_internal = isym->st_target_internal;
+
/* Check to see if we need to add an indirect symbol for
the default name. */
if (definition || h->root.type == bfd_link_hash_common)
/* A symbol from a library loaded via DT_NEEDED of some
other library is referenced by a regular object.
Add a DT_NEEDED entry for it. Issue an error if
- --no-add-needed is used. */
- if ((elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
+ --no-add-needed is used and the reference was not
+ a weak one. */
+ if (undef_bfd != NULL
+ && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
{
(*_bfd_error_handler)
- (_("%s: invalid DSO for symbol `%s' definition"),
+ (_("%B: undefined reference to symbol '%s'"),
+ undef_bfd, name);
+ (*_bfd_error_handler)
+ (_("note: '%s' is defined in DSO %B so try adding it to the linker command line"),
abfd, name);
- bfd_set_error (bfd_error_bad_value);
+ bfd_set_error (bfd_error_invalid_operation);
goto error_free_vers;
}
if (! dynamic
&& is_elf_hash_table (htab)
&& bed->check_relocs != NULL
+ && elf_object_id (abfd) == elf_hash_table_id (htab)
&& (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
{
asection *o;
undefs_tail = info->hash->undefs_tail;
- if (! (*info->callbacks->add_archive_element) (info, element,
- symdef->name))
+ if (!(*info->callbacks
+ ->add_archive_element) (info, element, symdef->name, &element))
goto error_return;
- if (! bfd_link_add_symbols (element, info))
+ if (!bfd_link_add_symbols (element, info))
goto error_return;
/* If there are any new undefined symbols, we need to make
Therefore the result is always a good payoff between few collisions
(= short chain lengths) and table size. */
static size_t
-compute_bucket_count (struct bfd_link_info *info,
+compute_bucket_count (struct bfd_link_info *info ATTRIBUTE_UNUSED,
unsigned long int *hashcodes ATTRIBUTE_UNUSED,
unsigned long int nsyms,
int gnu_hash)
const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
unsigned long int *counts;
bfd_size_type amt;
+ unsigned int no_improvement_count = 0;
/* Possible optimization parameters: if we have NSYMS symbols we say
that the hashing table must at least have NSYMS/4 and at most
{
best_chlen = max;
best_size = i;
+ no_improvement_count = 0;
}
+ /* PR 11843: Avoid futile long searches for the best bucket size
+ when there are a large number of symbols. */
+ else if (++no_improvement_count == 100)
+ break;
}
free (counts);
return best_size;
}
+/* Size any SHT_GROUP section for ld -r. */
+
+bfd_boolean
+_bfd_elf_size_group_sections (struct bfd_link_info *info)
+{
+ bfd *ibfd;
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+ && !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr))
+ return FALSE;
+ return TRUE;
+}
+
/* Set up the sizes and contents of the ELF dynamic sections. This is
called by the ELF linker emulation before_allocation routine. We
must set the sizes of the sections before the linker sets the
elf_hash_table (info)->init_plt_refcount
= elf_hash_table (info)->init_plt_offset;
+ if (info->relocatable
+ && !_bfd_elf_size_group_sections (info))
+ return FALSE;
+
/* The backend may have to create some sections regardless of whether
we're dynamic or not. */
if (bed->elf_backend_always_size_sections
{
const char *verstr, *name;
size_t namelen, verlen, newlen;
- char *newname, *p;
+ char *newname, *p, leading_char;
struct elf_link_hash_entry *newh;
+ leading_char = bfd_get_symbol_leading_char (output_bfd);
name = d->pattern;
- namelen = strlen (name);
+ namelen = strlen (name) + (leading_char != '\0');
verstr = t->name;
verlen = strlen (verstr);
newlen = namelen + verlen + 3;
newname = (char *) bfd_malloc (newlen);
if (newname == NULL)
return FALSE;
- memcpy (newname, name, namelen);
+ newname[0] = leading_char;
+ memcpy (newname + (leading_char != '\0'), name, namelen);
/* Check the hidden versioned definition. */
p = newname + namelen;
{
struct bfd_elf_version_deps *n;
+ /* Don't emit base version twice. */
+ if (t->vernum == 0)
+ continue;
+
size += sizeof (Elf_External_Verdef);
size += sizeof (Elf_External_Verdaux);
++cdefs;
unsigned int cdeps;
struct bfd_elf_version_deps *n;
+ /* Don't emit the base version twice. */
+ if (t->vernum == 0)
+ continue;
+
cdeps = 0;
for (n = t->deps; n != NULL; n = n->next)
++cdeps;
def.vd_hash = bfd_elf_hash (t->name);
def.vd_aux = sizeof (Elf_External_Verdef);
def.vd_next = 0;
- if (t->next != NULL)
+
+ /* If a basever node is next, it *must* be the last node in
+ the chain, otherwise Verdef construction breaks. */
+ if (t->next != NULL && t->next->vernum == 0)
+ BFD_ASSERT (t->next->next == NULL);
+
+ if (t->next != NULL && t->next->vernum != 0)
def.vd_next = (sizeof (Elf_External_Verdef)
+ (cdeps + 1) * sizeof (Elf_External_Verdaux));
unsigned int crefs;
bfd_byte *p;
- /* Build the version definition section. */
+ /* Build the version dependency section. */
size = 0;
crefs = 0;
for (t = elf_tdata (output_bfd)->verref;
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
- unsigned int entsize)
+ unsigned int entsize,
+ enum elf_target_id target_id)
{
bfd_boolean ret;
int can_refcount = get_elf_backend_data (abfd)->can_refcount;
table->dynsymcount = 1;
ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
+
table->root.type = bfd_link_elf_hash_table;
+ table->hash_table_id = target_id;
return ret;
}
return NULL;
if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry)))
+ sizeof (struct elf_link_hash_entry),
+ GENERIC_ELF_DATA))
{
free (ret);
return NULL;
"chunksz %ld, start %ld, len %ld, oplen %ld\n"
" dest: %8.8lx, mask: %8.8lx, reloc: %8.8lx\n",
lsb0_p, signed_p, trunc_p, wordsz, chunksz, start, len,
- oplen, x, mask, relocation);
+ oplen, (unsigned long) x, (unsigned long) mask,
+ (unsigned long) relocation);
#endif
r = bfd_reloc_ok;
" shifted mask: %8.8lx\n"
" shifted/masked reloc: %8.8lx\n"
" result: %8.8lx\n",
- relocation, (mask << shift),
- ((relocation & mask) << shift), x);
+ (unsigned long) relocation, (unsigned long) (mask << shift),
+ (unsigned long) ((relocation & mask) << shift), (unsigned long) x);
#endif
/* FIXME: octets_per_byte. */
put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
/* When performing a relocatable link, the input relocations are
preserved. But, if they reference global symbols, the indices
- referenced must be updated. Update all the relocations in
- REL_HDR (there are COUNT of them), using the data in REL_HASH. */
+ referenced must be updated. Update all the relocations found in
+ RELDATA. */
static void
elf_link_adjust_relocs (bfd *abfd,
- Elf_Internal_Shdr *rel_hdr,
- unsigned int count,
- struct elf_link_hash_entry **rel_hash)
+ struct bfd_elf_section_reloc_data *reldata)
{
unsigned int i;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
bfd_vma r_type_mask;
int r_sym_shift;
+ unsigned int count = reldata->count;
+ struct elf_link_hash_entry **rel_hash = reldata->hashes;
- if (rel_hdr->sh_entsize == bed->s->sizeof_rel)
+ if (reldata->hdr->sh_entsize == bed->s->sizeof_rel)
{
swap_in = bed->s->swap_reloc_in;
swap_out = bed->s->swap_reloc_out;
}
- else if (rel_hdr->sh_entsize == bed->s->sizeof_rela)
+ else if (reldata->hdr->sh_entsize == bed->s->sizeof_rela)
{
swap_in = bed->s->swap_reloca_in;
swap_out = bed->s->swap_reloca_out;
r_sym_shift = 32;
}
- erela = rel_hdr->contents;
- for (i = 0; i < count; i++, rel_hash++, erela += rel_hdr->sh_entsize)
+ erela = reldata->hdr->contents;
+ for (i = 0; i < count; i++, rel_hash++, erela += reldata->hdr->sh_entsize)
{
Elf_Internal_Rela irela[MAX_INT_RELS_PER_EXT_REL];
unsigned int j;
_bfd_elf_swap_versym_in (input, ever, &iver);
- if ((iver.vs_vers & VERSYM_HIDDEN) == 0)
+ if ((iver.vs_vers & VERSYM_HIDDEN) == 0
+ && !(h->def_regular
+ && h->forced_local))
{
/* If we have a non-hidden versioned sym, then it should
- have provided a definition for the undefined sym. */
+ have provided a definition for the undefined sym unless
+ it is defined in a non-shared object and forced local.
+ */
abort ();
}
{
/* If we have an undefined symbol reference here then it must have
come from a shared library that is being linked in. (Undefined
- references in regular files have already been handled). */
+ references in regular files have already been handled unless
+ they are in unreferenced sections which are removed by garbage
+ collection). */
bfd_boolean ignore_undef = FALSE;
/* Some symbols may be special in that the fact that they're
ignore_undef = bed->elf_backend_ignore_undef_symbol (h);
/* If we are reporting errors for this situation then do so now. */
- if (ignore_undef == FALSE
+ if (!ignore_undef
&& h->ref_dynamic
- && ! h->ref_regular
+ && (!h->ref_regular || finfo->info->gc_sections)
&& ! elf_link_check_versioned_symbol (finfo->info, bed, h)
&& finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
{
if (! (finfo->info->callbacks->undefined_symbol
- (finfo->info, h->root.root.string, h->root.u.undef.abfd,
+ (finfo->info, h->root.root.string,
+ h->ref_regular ? NULL : h->root.u.undef.abfd,
NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR)))
{
+ bfd_set_error (bfd_error_bad_value);
eoinfo->failed = TRUE;
return FALSE;
}
&& !h->dynamic_weak
&& ! elf_link_check_versioned_symbol (finfo->info, bed, h))
{
- (*_bfd_error_handler)
- (_("%B: %s symbol `%s' in %B is referenced by DSO"),
- finfo->output_bfd,
- h->root.u.def.section == bfd_abs_section_ptr
- ? finfo->output_bfd : h->root.u.def.section->owner,
- ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
- ? "internal"
- : ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
- ? "hidden" : "local",
- h->root.root.string);
+ bfd *def_bfd;
+ const char *msg;
+
+ if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
+ msg = _("%B: internal symbol `%s' in %B is referenced by DSO");
+ else if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+ msg = _("%B: hidden symbol `%s' in %B is referenced by DSO");
+ else
+ msg = _("%B: local symbol `%s' in %B is referenced by DSO");
+ def_bfd = finfo->output_bfd;
+ if (h->root.u.def.section != bfd_abs_section_ptr)
+ def_bfd = h->root.u.def.section->owner;
+ (*_bfd_error_handler) (msg, finfo->output_bfd, def_bfd,
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
eoinfo->failed = TRUE;
return FALSE;
}
|| h->root.type == bfd_link_hash_defweak)
&& elf_discarded_section (h->root.u.def.section))
strip = TRUE;
+ else if ((h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ && h->root.u.undef.abfd != NULL
+ && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
+ strip = TRUE;
else
strip = FALSE;
/* If we're stripping it, and it's not a dynamic symbol, there's
- nothing else to do unless it is a forced local symbol. */
+ nothing else to do unless it is a forced local symbol or a
+ STT_GNU_IFUNC symbol. */
if (strip
&& h->dynindx == -1
+ && h->type != STT_GNU_IFUNC
&& !h->forced_local)
return TRUE;
sym.st_size = h->size;
sym.st_other = h->other;
if (h->forced_local)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
+ {
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
+ /* Turn off visibility on local symbol. */
+ sym.st_other &= ~ELF_ST_VISIBILITY (-1);
+ }
else if (h->unique_global)
sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
else if (h->root.type == bfd_link_hash_undefweak
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;
switch (h->root.type)
{
(*_bfd_error_handler)
(_("%B: could not find output section %A for input section %A"),
finfo->output_bfd, input_sec->output_section, input_sec);
+ bfd_set_error (bfd_error_nonrepresentable_section);
eoinfo->failed = TRUE;
return FALSE;
}
&& h->root.type == bfd_link_hash_undefined
&& !h->def_regular)
{
- (*_bfd_error_handler)
- (_("%B: %s symbol `%s' isn't defined"),
- finfo->output_bfd,
- ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED
- ? "protected"
- : ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL
- ? "internal" : "hidden",
- h->root.root.string);
+ const char *msg;
+
+ if (ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED)
+ msg = _("%B: protected symbol `%s' isn't defined");
+ else if (ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL)
+ msg = _("%B: internal symbol `%s' isn't defined");
+ else
+ msg = _("%B: hidden symbol `%s' isn't defined");
+ (*_bfd_error_handler) (msg, finfo->output_bfd, h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
eoinfo->failed = TRUE;
return FALSE;
}
contents = elf_section_data (o)->this_hdr.contents;
else
{
- bfd_size_type amt = o->rawsize ? o->rawsize : o->size;
-
contents = finfo->contents;
- if (! bfd_get_section_contents (input_bfd, o, contents, 0, amt))
+ if (! bfd_get_full_section_contents (input_bfd, o, &contents))
return FALSE;
}
#ifdef DEBUG
printf ("Encountered a complex symbol!");
printf (" (input_bfd %s, section %s, reloc %ld\n",
- input_bfd->filename, o->name, rel - internal_relocs);
+ input_bfd->filename, o->name,
+ (long) (rel - internal_relocs));
printf (" symbol: idx %8.8lx, name %s\n",
r_symndx, sym_name);
printf (" reloc : info %8.8lx, addr %8.8lx\n",
discarded section. */
if ((sec = *ps) != NULL && elf_discarded_section (sec))
{
- BFD_ASSERT (r_symndx != 0);
+ BFD_ASSERT (r_symndx != STN_UNDEF);
if (action_discarded & COMPLAIN)
(*finfo->info->callbacks->einfo)
(_("%X`%s' referenced in section `%A' of %B: "
|| finfo->info->emitrelocations)
{
Elf_Internal_Rela *irela;
- Elf_Internal_Rela *irelaend;
+ Elf_Internal_Rela *irelaend, *irelamid;
bfd_vma last_offset;
struct elf_link_hash_entry **rel_hash;
- struct elf_link_hash_entry **rel_hash_list;
- Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2;
+ struct elf_link_hash_entry **rel_hash_list, **rela_hash_list;
+ Elf_Internal_Shdr *input_rel_hdr, *input_rela_hdr;
unsigned int next_erel;
bfd_boolean rela_normal;
+ struct bfd_elf_section_data *esdi, *esdo;
- input_rel_hdr = &elf_section_data (o)->rel_hdr;
- rela_normal = (bed->rela_normal
- && (input_rel_hdr->sh_entsize
- == bed->s->sizeof_rela));
+ esdi = elf_section_data (o);
+ esdo = elf_section_data (o->output_section);
+ rela_normal = FALSE;
/* Adjust the reloc addresses and symbol indices. */
irela = internal_relocs;
irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
- rel_hash = (elf_section_data (o->output_section)->rel_hashes
- + elf_section_data (o->output_section)->rel_count
- + elf_section_data (o->output_section)->rel_count2);
+ rel_hash = esdo->rel.hashes + esdo->rel.count;
+ /* We start processing the REL relocs, if any. When we reach
+ IRELAMID in the loop, we switch to the RELA relocs. */
+ irelamid = irela;
+ if (esdi->rel.hdr != NULL)
+ irelamid += (NUM_SHDR_ENTRIES (esdi->rel.hdr)
+ * bed->s->int_rels_per_ext_rel);
rel_hash_list = rel_hash;
+ rela_hash_list = NULL;
last_offset = o->output_offset;
if (!finfo->info->relocatable)
last_offset += o->output_section->vma;
next_erel = 0;
}
+ if (irela == irelamid)
+ {
+ rel_hash = esdo->rela.hashes + esdo->rela.count;
+ rela_hash_list = rel_hash;
+ rela_normal = bed->rela_normal;
+ }
+
irela->r_offset = _bfd_elf_section_offset (output_bfd,
finfo->info, o,
irela->r_offset);
/* I suppose the backend ought to fill in the
section of any STT_SECTION symbol against a
processor specific section. */
- r_symndx = 0;
+ r_symndx = STN_UNDEF;
if (bfd_is_abs_section (sec))
;
else if (sec == NULL || sec->owner == NULL)
if (!bfd_is_abs_section (osec))
{
r_symndx = osec->target_index;
- if (r_symndx == 0)
+ if (r_symndx == STN_UNDEF)
{
struct elf_link_hash_table *htab;
asection *oi;
}
}
- BFD_ASSERT (r_symndx != 0);
+ BFD_ASSERT (r_symndx != STN_UNDEF);
}
}
}
/* Swap out the relocs. */
- if (input_rel_hdr->sh_size != 0
- && !bed->elf_backend_emit_relocs (output_bfd, o,
- input_rel_hdr,
- internal_relocs,
- rel_hash_list))
- return FALSE;
-
- input_rel_hdr2 = elf_section_data (o)->rel_hdr2;
- if (input_rel_hdr2 && input_rel_hdr2->sh_size != 0)
+ input_rel_hdr = esdi->rel.hdr;
+ if (input_rel_hdr && input_rel_hdr->sh_size != 0)
{
+ if (!bed->elf_backend_emit_relocs (output_bfd, o,
+ input_rel_hdr,
+ internal_relocs,
+ rel_hash_list))
+ return FALSE;
internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr)
* bed->s->int_rels_per_ext_rel);
rel_hash_list += NUM_SHDR_ENTRIES (input_rel_hdr);
+ }
+
+ input_rela_hdr = esdi->rela.hdr;
+ if (input_rela_hdr && input_rela_hdr->sh_size != 0)
+ {
if (!bed->elf_backend_emit_relocs (output_bfd, o,
- input_rel_hdr2,
+ input_rela_hdr,
internal_relocs,
- rel_hash_list))
+ rela_hash_list))
return FALSE;
}
}
{
/* FIXME: octets_per_byte. */
if (! (o->flags & SEC_EXCLUDE)
- && ! (o->output_section->flags & SEC_NEVER_LOAD)
&& ! bfd_set_section_contents (output_bfd, o->output_section,
contents,
(file_ptr) o->output_offset,
long indx;
bfd_vma offset;
bfd_vma addend;
+ struct bfd_elf_section_reloc_data *reldata;
struct elf_link_hash_entry **rel_hash_ptr;
Elf_Internal_Shdr *rel_hdr;
const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
Elf_Internal_Rela irel[MAX_INT_RELS_PER_EXT_REL];
bfd_byte *erel;
unsigned int i;
+ struct bfd_elf_section_data *esdo = elf_section_data (output_section);
howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
if (howto == NULL)
addend = link_order->u.reloc.p->addend;
+ if (esdo->rel.hdr)
+ reldata = &esdo->rel;
+ else if (esdo->rela.hdr)
+ reldata = &esdo->rela;
+ else
+ {
+ reldata = NULL;
+ BFD_ASSERT (0);
+ }
+
/* Figure out the symbol index. */
- rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
- + elf_section_data (output_section)->rel_count
- + elf_section_data (output_section)->rel_count2);
+ rel_hash_ptr = reldata->hashes + reldata->count;
if (link_order->type == bfd_section_reloc_link_order)
{
indx = link_order->u.reloc.p->u.section->target_index;
else
irel[0].r_info = ELF64_R_INFO (indx, howto->type);
- rel_hdr = &elf_section_data (output_section)->rel_hdr;
+ rel_hdr = reldata->hdr;
erel = rel_hdr->contents;
if (rel_hdr->sh_type == SHT_REL)
{
- erel += (elf_section_data (output_section)->rel_count
- * bed->s->sizeof_rel);
+ erel += reldata->count * bed->s->sizeof_rel;
(*bed->s->swap_reloc_out) (output_bfd, irel, erel);
}
else
{
irel[0].r_addend = addend;
- erel += (elf_section_data (output_section)->rel_count
- * bed->s->sizeof_rela);
+ erel += reldata->count * bed->s->sizeof_rela;
(*bed->s->swap_reloca_out) (output_bfd, irel, erel);
}
- ++elf_section_data (output_section)->rel_count;
+ ++reldata->count;
return TRUE;
}
bfd_boolean emit_relocs;
bfd *dynobj;
struct elf_final_link_info finfo;
- register asection *o;
- register struct bfd_link_order *p;
- register bfd *sub;
+ asection *o;
+ struct bfd_link_order *p;
+ bfd *sub;
bfd_size_type max_contents_size;
bfd_size_type max_external_reloc_size;
bfd_size_type max_internal_reloc_count;
{
unsigned int reloc_count = 0;
struct bfd_elf_section_data *esdi = NULL;
- unsigned int *rel_count1;
if (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order)
if ((sec->flags & SEC_RELOC) != 0)
{
- size_t ext_size;
+ size_t ext_size = 0;
+
+ if (esdi->rel.hdr != NULL)
+ ext_size = esdi->rel.hdr->sh_size;
+ if (esdi->rela.hdr != NULL)
+ ext_size += esdi->rela.hdr->sh_size;
- ext_size = elf_section_data (sec)->rel_hdr.sh_size;
if (ext_size > max_external_reloc_size)
max_external_reloc_size = ext_size;
if (sec->reloc_count > max_internal_reloc_count)
o->reloc_count += reloc_count;
- /* MIPS may have a mix of REL and RELA relocs on sections.
- To support this curious ABI we keep reloc counts in
- elf_section_data too. We must be careful to add the
- relocations from the input section to the right output
- count. FIXME: Get rid of one count. We have
- o->reloc_count == esdo->rel_count + esdo->rel_count2. */
- rel_count1 = &esdo->rel_count;
- if (esdi != NULL)
+ if (p->type == bfd_indirect_link_order
+ && (info->relocatable || info->emitrelocations))
{
- bfd_boolean same_size;
- bfd_size_type entsize1;
-
- entsize1 = esdi->rel_hdr.sh_entsize;
- /* PR 9827: If the header size has not been set yet then
- assume that it will match the output section's reloc type. */
- if (entsize1 == 0)
- entsize1 = o->use_rela_p ? bed->s->sizeof_rela : bed->s->sizeof_rel;
+ if (esdi->rel.hdr)
+ esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr);
+ if (esdi->rela.hdr)
+ esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr);
+ }
+ else
+ {
+ if (o->use_rela_p)
+ esdo->rela.count += reloc_count;
else
- BFD_ASSERT (entsize1 == bed->s->sizeof_rel
- || entsize1 == bed->s->sizeof_rela);
- same_size = !o->use_rela_p == (entsize1 == bed->s->sizeof_rel);
-
- if (!same_size)
- rel_count1 = &esdo->rel_count2;
-
- if (esdi->rel_hdr2 != NULL)
- {
- bfd_size_type entsize2 = esdi->rel_hdr2->sh_entsize;
- unsigned int alt_count;
- unsigned int *rel_count2;
-
- BFD_ASSERT (entsize2 != entsize1
- && (entsize2 == bed->s->sizeof_rel
- || entsize2 == bed->s->sizeof_rela));
-
- rel_count2 = &esdo->rel_count2;
- if (!same_size)
- rel_count2 = &esdo->rel_count;
-
- /* The following is probably too simplistic if the
- backend counts output relocs unusually. */
- BFD_ASSERT (bed->elf_backend_count_relocs == NULL);
- alt_count = NUM_SHDR_ENTRIES (esdi->rel_hdr2);
- *rel_count2 += alt_count;
- reloc_count -= alt_count;
- }
+ esdo->rel.count += reloc_count;
}
- *rel_count1 += reloc_count;
}
if (o->reloc_count > 0)
/* Set sizes, and assign file positions for reloc sections. */
for (o = abfd->sections; o != NULL; o = o->next)
{
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
if ((o->flags & SEC_RELOC) != 0)
{
- if (!(_bfd_elf_link_size_reloc_section
- (abfd, &elf_section_data (o)->rel_hdr, o)))
+ if (esdo->rel.hdr
+ && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rel)))
goto error_return;
- if (elf_section_data (o)->rel_hdr2
- && !(_bfd_elf_link_size_reloc_section
- (abfd, elf_section_data (o)->rel_hdr2, o)))
+ if (esdo->rela.hdr
+ && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rela)))
goto error_return;
}
/* Now, reset REL_COUNT and REL_COUNT2 so that we can use them
to count upwards while actually outputting the relocations. */
- elf_section_data (o)->rel_count = 0;
- elf_section_data (o)->rel_count2 = 0;
+ esdo->rel.count = 0;
+ esdo->rela.count = 0;
}
_bfd_elf_assign_file_positions_for_relocs (abfd);
elfsym.st_info = 0;
elfsym.st_other = 0;
elfsym.st_shndx = SHN_UNDEF;
+ elfsym.st_target_internal = 0;
if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
NULL) != 1)
goto error_return;
elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
elfsym.st_other = 0;
elfsym.st_value = 0;
+ elfsym.st_target_internal = 0;
for (i = 1; i < elf_numsections (abfd); i++)
{
o = bfd_section_from_elf_index (abfd, i);
if (size == 0
&& (sec->flags & SEC_HAS_CONTENTS) == 0)
{
- struct bfd_link_order *o = sec->map_tail.link_order;
- if (o != NULL)
- size = o->offset + o->size;
+ struct bfd_link_order *ord = sec->map_tail.link_order;
+
+ if (ord != NULL)
+ size = ord->offset + ord->size;
}
end = sec->vma + size;
}
base = elf_hash_table (info)->tls_sec->vma;
- end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power);
+ /* Only align end of TLS section if static TLS doesn't have special
+ alignment requirements. */
+ if (bed->static_tls_alignment == 1)
+ end = align_power (end,
+ elf_hash_table (info)->tls_sec->alignment_power);
elf_hash_table (info)->tls_size = end - base;
}
else
{
if (! _bfd_default_link_order (abfd, info, o, p))
- goto error_return;
+ {
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour (sub)
+ == bfd_target_elf_flavour)
+ && (elf_elfheader (sub)->e_ident[EI_CLASS]
+ != bed->s->elfclass))
+ {
+ const char *iclass, *oclass;
+
+ if (bed->s->elfclass == ELFCLASS64)
+ {
+ iclass = "ELFCLASS32";
+ oclass = "ELFCLASS64";
+ }
+ else
+ {
+ iclass = "ELFCLASS64";
+ oclass = "ELFCLASS32";
+ }
+
+ bfd_set_error (bfd_error_wrong_format);
+ (*_bfd_error_handler)
+ (_("%B: file class %s incompatible with %s"),
+ sub, iclass, oclass);
+ }
+
+ goto error_return;
+ }
}
}
}
sym.st_name = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
sym.st_other = 0;
+ sym.st_target_internal = 0;
for (s = abfd->sections; s != NULL; s = s->next)
{
asection *s;
bfd_byte *dest;
- sym.st_size = e->isym.st_size;
- sym.st_other = e->isym.st_other;
-
- /* Copy the internal symbol as is.
+ /* Copy the internal symbol and turn off visibility.
Note that we saved a word of storage and overwrote
the original st_name with the dynstr_index. */
sym = e->isym;
+ sym.st_other &= ~ELF_ST_VISIBILITY (-1);
s = bfd_section_from_elf_index (e->input_bfd,
e->isym.st_shndx);
/* Adjust the relocs to have the correct symbol indices. */
for (o = abfd->sections; o != NULL; o = o->next)
{
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
if ((o->flags & SEC_RELOC) == 0)
continue;
- elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr,
- elf_section_data (o)->rel_count,
- elf_section_data (o)->rel_hashes);
- if (elf_section_data (o)->rel_hdr2 != NULL)
- elf_link_adjust_relocs (abfd, elf_section_data (o)->rel_hdr2,
- elf_section_data (o)->rel_count2,
- (elf_section_data (o)->rel_hashes
- + elf_section_data (o)->rel_count));
+ if (esdo->rel.hdr != NULL)
+ elf_link_adjust_relocs (abfd, &esdo->rel);
+ if (esdo->rela.hdr != NULL)
+ elf_link_adjust_relocs (abfd, &esdo->rela);
/* Set the reloc_count field to 0 to prevent write_relocs from
trying to swap the relocs out itself. */
free (finfo.symshndxbuf);
for (o = abfd->sections; o != NULL; o = o->next)
{
- if ((o->flags & SEC_RELOC) != 0
- && elf_section_data (o)->rel_hashes != NULL)
- free (elf_section_data (o)->rel_hashes);
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
+ if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
+ free (esdo->rel.hashes);
+ if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
+ free (esdo->rela.hashes);
}
elf_tdata (abfd)->linker = TRUE;
free (finfo.symshndxbuf);
for (o = abfd->sections; o != NULL; o = o->next)
{
- if ((o->flags & SEC_RELOC) != 0
- && elf_section_data (o)->rel_hashes != NULL)
- free (elf_section_data (o)->rel_hashes);
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
+ if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
+ free (esdo->rel.hashes);
+ if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
+ free (esdo->rela.hashes);
}
return FALSE;
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
+ const char *sec_name;
+
if (h != NULL)
{
switch (h->root.type)
case bfd_link_hash_common:
return h->root.u.c.p->section;
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ /* To work around a glibc bug, keep all XXX input sections
+ when there is an as yet undefined reference to __start_XXX
+ or __stop_XXX symbols. The linker will later define such
+ symbols for orphan input sections that have a name
+ representable as a C identifier. */
+ if (strncmp (h->root.root.string, "__start_", 8) == 0)
+ sec_name = h->root.root.string + 8;
+ else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
+ sec_name = h->root.root.string + 7;
+ else
+ sec_name = NULL;
+
+ if (sec_name && *sec_name != '\0')
+ {
+ bfd *i;
+
+ for (i = info->input_bfds; i; i = i->link_next)
+ {
+ sec = bfd_get_section_by_name (i, sec_name);
+ if (sec)
+ sec->flags |= SEC_KEEP;
+ }
+ }
+ break;
+
default:
break;
}
struct elf_link_hash_entry *h;
r_symndx = cookie->rel->r_info >> cookie->r_sym_shift;
- if (r_symndx == 0)
+ if (r_symndx == STN_UNDEF)
return NULL;
if (r_symndx >= cookie->locsymcount
o->gc_mark = first->gc_mark;
}
else if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
- || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
+ || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0
+ || elf_section_data (o)->this_hdr.sh_type == SHT_NOTE)
{
- /* Keep debug and special sections. */
+ /* Keep debug, special and SHT_NOTE sections. */
o->gc_mark = 1;
}
continue;
r_symndx = rcookie->rel->r_info >> rcookie->r_sym_shift;
- if (r_symndx == SHN_UNDEF)
+ if (r_symndx == STN_UNDEF)
return TRUE;
if (r_symndx >= rcookie->locsymcount
/* Routines to support the creation of dynamic relocs. */
-/* Return true if NAME is a name of a relocation
- section associated with section S. */
-
-static bfd_boolean
-is_reloc_section (bfd_boolean rela, const char * name, asection * s)
-{
- if (rela)
- return CONST_STRNEQ (name, ".rela")
- && strcmp (bfd_get_section_name (NULL, s), name + 5) == 0;
-
- return CONST_STRNEQ (name, ".rel")
- && strcmp (bfd_get_section_name (NULL, s), name + 4) == 0;
-}
-
/* Returns the name of the dynamic reloc section associated with SEC. */
static const char *
asection * sec,
bfd_boolean is_rela)
{
- const char * name;
- unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
- unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name;
+ char *name;
+ const char *old_name = bfd_get_section_name (NULL, sec);
+ const char *prefix = is_rela ? ".rela" : ".rel";
- name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
- if (name == NULL)
+ if (old_name == NULL)
return NULL;
- if (! is_reloc_section (is_rela, name, sec))
- {
- static bfd_boolean complained = FALSE;
-
- if (! complained)
- {
- (*_bfd_error_handler)
- (_("%B: bad relocation section name `%s\'"), abfd, name);
- complained = TRUE;
- }
- name = NULL;
- }
+ name = bfd_alloc (abfd, strlen (prefix) + strlen (old_name) + 1);
+ sprintf (name, "%s%s", prefix, old_name);
return name;
}
section does not exist it is created and attached to the DYNOBJ
bfd and stored in the SRELOC field of SEC's elf_section_data
structure.
-
+
ALIGNMENT is the alignment for the newly created section and
IS_RELA defines whether the name should be .rela.<SEC's name>
or .rel.<SEC's name>. The section name is looked up in the
return reloc_sec;
}
+
+/* Copy the ELF symbol type associated with a linker hash entry. */
+void
+_bfd_elf_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry * hdest,
+ struct bfd_link_hash_entry * hsrc)
+{
+ struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *)hdest;
+ struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc;
+
+ ehdest->type = ehsrc->type;
+ ehdest->target_internal = ehsrc->target_internal;
+}
+
+/* Append a RELA relocation REL to section S in BFD. */
+
+void
+elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
+ BFD_ASSERT (loc + bed->s->sizeof_rela <= s->contents + s->size);
+ bed->s->swap_reloca_out (abfd, rel, loc);
+}
+
+/* Append a REL relocation REL to section S in BFD. */
+
+void
+elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rel);
+ BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
+ bed->s->swap_reloca_out (abfd, rel, loc);
+}