/* 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.
_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);
}
return 1;
amt = sizeof (*entry);
- entry = bfd_alloc (input_bfd, amt);
+ entry = (struct elf_link_local_dynamic_entry *) bfd_alloc (input_bfd, amt);
if (entry == NULL)
return 0;
elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h,
void *data)
{
- size_t *count = data;
+ size_t *count = (size_t *) data;
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
void *data)
{
- size_t *count = data;
+ size_t *count = (size_t *) data;
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
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;
/* If a new weak symbol definition comes from a regular file and the
old symbol comes from a dynamic library, we treat the new one as
/* 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;
dynamic = (abfd->flags & DYNAMIC) != 0;
shortlen = p - name;
- shortname = bfd_hash_allocate (&info->hash->table, shortlen + 1);
+ shortname = (char *) bfd_hash_allocate (&info->hash->table, shortlen + 1);
if (shortname == NULL)
return FALSE;
memcpy (shortname, name, shortlen);
{
if (! dynamic)
{
- if (info->shared
+ if (! info->executable
|| hi->ref_dynamic)
*dynsym = TRUE;
}
nondefault:
len = strlen (name);
- shortname = bfd_hash_allocate (&info->hash->table, len);
+ shortname = (char *) bfd_hash_allocate (&info->hash->table, len);
if (shortname == NULL)
return FALSE;
memcpy (shortname, name, shortlen);
{
if (! dynamic)
{
- if (info->shared
+ if (! info->executable
|| hi->ref_dynamic)
*dynsym = TRUE;
}
static bfd_boolean
_bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
{
- struct elf_info_failed *eif = data;
+ struct elf_info_failed *eif = (struct elf_info_failed *) data;
/* Ignore this if we won't export it. */
if (!eif->info->export_dynamic && !h->dynamic)
_bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
void *data)
{
- struct elf_find_verdep_info *rinfo = data;
+ struct elf_find_verdep_info *rinfo = (struct elf_find_verdep_info *) data;
Elf_Internal_Verneed *t;
Elf_Internal_Vernaux *a;
bfd_size_type amt;
if (t == NULL)
{
amt = sizeof *t;
- t = bfd_zalloc (rinfo->info->output_bfd, amt);
+ t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd, amt);
if (t == NULL)
{
rinfo->failed = TRUE;
}
amt = sizeof *a;
- a = bfd_zalloc (rinfo->info->output_bfd, amt);
+ a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
if (a == NULL)
{
rinfo->failed = TRUE;
char *p;
bfd_size_type amt;
- sinfo = data;
+ sinfo = (struct elf_info_failed *) data;
info = sinfo->info;
if (h->root.type == bfd_link_hash_warning)
struct bfd_elf_version_expr *d;
len = p - h->root.root.string;
- alc = bfd_malloc (len);
+ alc = (char *) bfd_malloc (len);
if (alc == NULL)
{
sinfo->failed = TRUE;
return TRUE;
amt = sizeof *t;
- t = bfd_zalloc (info->output_bfd, amt);
+ t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, amt);
if (t == NULL)
{
sinfo->failed = TRUE;
return FALSE;
}
- erela = external_relocs;
+ erela = (const bfd_byte *) external_relocs;
erelaend = erela + shdr->sh_size;
irela = internal_relocs;
while (erela < erelaend)
size = o->reloc_count;
size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
if (keep_memory)
- internal_relocs = alloc2 = bfd_alloc (abfd, size);
+ internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
else
- internal_relocs = alloc2 = bfd_malloc (size);
+ internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
if (internal_relocs == NULL)
goto error_return;
}
allocate it with bfd_alloc rather than malloc. Also since we
cannot be sure that the contents will actually be filled in,
we zero the allocated space. */
- rel_hdr->contents = bfd_zalloc (abfd, rel_hdr->sh_size);
+ rel_hdr->contents = (unsigned char *) bfd_zalloc (abfd, rel_hdr->sh_size);
if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
return FALSE;
{
struct elf_link_hash_entry **p;
- p = bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *));
+ p = (struct elf_link_hash_entry **)
+ bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *));
if (p == NULL)
return FALSE;
static bfd_boolean
_bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
{
- struct elf_info_failed *eif = data;
+ struct elf_info_failed *eif = (struct elf_info_failed *) data;
bfd *dynobj;
const struct elf_backend_data *bed;
about symbols which are defined by one dynamic object and
referenced by another one? */
if (!h->needs_plt
+ && h->type != STT_GNU_IFUNC
&& (h->def_regular
|| !h->def_dynamic
|| (!h->ref_regular
&& ((sec = h->root.u.def.section)->flags & SEC_MERGE)
&& sec->sec_info_type == ELF_INFO_TYPE_MERGE)
{
- bfd *output_bfd = data;
+ bfd *output_bfd = (bfd *) data;
h->root.u.def.value =
_bfd_merged_section_offset (output_bfd,
BFD_ASSERT (s != NULL);
newsize = s->size + bed->s->sizeof_dyn;
- newcontents = bfd_realloc (s->contents, newsize);
+ newcontents = (bfd_byte *) bfd_realloc (s->contents, newsize);
if (newcontents == NULL)
return FALSE;
static bfd_boolean
elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data)
{
- struct elf_strtab_hash *dynstr = data;
+ struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data;
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
case DT_RUNPATH:
case DT_FILTER:
case DT_AUXILIARY:
+ case DT_AUDIT:
+ case DT_DEPAUDIT:
dyn.d_un.d_val = _bfd_elf_strtab_offset (dynstr, dyn.d_un.d_val);
break;
default:
}
sz = s->size;
- msg = bfd_alloc (abfd, sz + 1);
+ msg = (char *) bfd_alloc (abfd, sz + 1);
if (msg == NULL)
goto error_return;
{
asection *s;
const char *soname = NULL;
+ char *audit = NULL;
struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
int ret;
unsigned long shlink;
if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
- goto error_free_dyn;
+ {
+error_free_dyn:
+ free (dynbuf);
+ goto error_return;
+ }
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
if (elfsec == SHN_BAD)
unsigned int tagv = dyn.d_un.d_val;
amt = sizeof (struct bfd_link_needed_list);
- n = bfd_alloc (abfd, amt);
+ n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
if (n == NULL || fnm == NULL)
goto error_free_dyn;
amt = strlen (fnm) + 1;
- anm = bfd_alloc (abfd, amt);
+ anm = (char *) bfd_alloc (abfd, amt);
if (anm == NULL)
goto error_free_dyn;
memcpy (anm, fnm, amt);
unsigned int tagv = dyn.d_un.d_val;
amt = sizeof (struct bfd_link_needed_list);
- n = bfd_alloc (abfd, amt);
+ n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
if (n == NULL || fnm == NULL)
goto error_free_dyn;
amt = strlen (fnm) + 1;
- anm = bfd_alloc (abfd, amt);
+ anm = (char *) bfd_alloc (abfd, amt);
if (anm == NULL)
goto error_free_dyn;
memcpy (anm, fnm, amt);
unsigned int tagv = dyn.d_un.d_val;
amt = sizeof (struct bfd_link_needed_list);
- n = bfd_alloc (abfd, amt);
+ n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
if (n == NULL || fnm == NULL)
goto error_free_dyn;
amt = strlen (fnm) + 1;
- anm = bfd_alloc (abfd, amt);
+ anm = (char *) bfd_alloc (abfd, amt);
if (anm == NULL)
- {
- error_free_dyn:
- free (dynbuf);
- goto error_return;
- }
+ goto error_free_dyn;
memcpy (anm, fnm, amt);
n->name = anm;
n->by = abfd;
;
*pn = n;
}
+ if (dyn.d_tag == DT_AUDIT)
+ {
+ unsigned int tagv = dyn.d_un.d_val;
+ audit = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
+ }
}
free (dynbuf);
particular dynamic object more than once. */
if (ret > 0)
return TRUE;
+
+ /* Save the DT_AUDIT entry for the linker emulation code. */
+ elf_dt_audit (abfd) = audit;
}
/* If this is a dynamic object, we always link against the .dynsym
/* We store a pointer to the hash table entry for each external
symbol. */
amt = extsymcount * sizeof (struct elf_link_hash_entry *);
- sym_hash = bfd_alloc (abfd, amt);
+ sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt);
if (sym_hash == NULL)
goto error_free_sym;
elf_sym_hashes (abfd) = sym_hash;
Elf_Internal_Shdr *versymhdr;
versymhdr = &elf_tdata (abfd)->dynversym_hdr;
- extversym = bfd_malloc (versymhdr->sh_size);
+ extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
if (extversym == NULL)
goto error_free_sym;
amt = versymhdr->sh_size;
bfd_boolean common;
unsigned int old_alignment;
bfd *old_bfd;
+ bfd * undef_bfd = NULL;
override = FALSE;
common = bed->common_definition (isym);
bind = ELF_ST_BIND (isym->st_info);
- if (bind == STB_LOCAL)
+ switch (bind)
{
+ case STB_LOCAL:
/* This should be impossible, since ELF requires that all
global symbols follow all local symbols, and that sh_info
point to the first global symbol. Unfortunately, Irix 5
screws this up. */
continue;
- }
- else if (bind == STB_GLOBAL)
- {
+
+ case STB_GLOBAL:
if (isym->st_shndx != SHN_UNDEF && !common)
flags = BSF_GLOBAL;
- }
- else if (bind == STB_WEAK)
- flags = BSF_WEAK;
- else
- {
+ break;
+
+ case STB_WEAK:
+ flags = BSF_WEAK;
+ break;
+
+ case STB_GNU_UNIQUE:
+ flags = BSF_GNU_UNIQUE;
+ break;
+
+ default:
/* Leave it up to the processor backend. */
+ break;
}
if (isym->st_shndx == SHN_UNDEF)
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)
&& isym->st_shndx != SHN_UNDEF)
++newlen;
- newname = bfd_hash_allocate (&htab->root.table, newlen);
+ newname = (char *) bfd_hash_allocate (&htab->root.table, newlen);
if (newname == NULL)
goto error_free_vers;
memcpy (newname, name, namelen);
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,
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
*sym_hash = h;
+ h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
new_weakdef = FALSE;
if (dynamic
if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
&& (definition || h->type == STT_NOTYPE))
{
- if (h->type != STT_NOTYPE
- && h->type != ELF_ST_TYPE (isym->st_info)
- && ! type_change_ok)
- (*_bfd_error_handler)
- (_("Warning: type of symbol `%s' changed"
- " from %d to %d in %B"),
- abfd, name, h->type, ELF_ST_TYPE (isym->st_info));
+ unsigned int type = ELF_ST_TYPE (isym->st_info);
- h->type = ELF_ST_TYPE (isym->st_info);
- }
+ /* Turn an IFUNC symbol from a DSO into a normal FUNC
+ symbol. */
+ if (type == STT_GNU_IFUNC
+ && (abfd->flags & DYNAMIC) != 0)
+ type = STT_FUNC;
- /* STT_GNU_IFUNC symbol must go through PLT. */
- if (h->type == STT_GNU_IFUNC)
- h->needs_plt = 1;
+ if (h->type != type)
+ {
+ if (h->type != STT_NOTYPE && ! type_change_ok)
+ (*_bfd_error_handler)
+ (_("Warning: type of symbol `%s' changed"
+ " from %d to %d in %B"),
+ abfd, name, h->type, type);
+
+ h->type = type;
+ }
+ }
/* Merge st_other field. */
elf_merge_st_other (abfd, h, isym, definition, 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;
}
{
amt = ((isymend - isym + 1)
* sizeof (struct elf_link_hash_entry *));
- nondeflt_vers = bfd_malloc (amt);
+ nondeflt_vers =
+ (struct elf_link_hash_entry **) bfd_malloc (amt);
if (!nondeflt_vers)
goto error_free_vers;
}
/* 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;
}
- elf_dyn_lib_class (abfd) &= ~DYN_AS_NEEDED;
+ elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
+ (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);
add_needed = TRUE;
ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
continue;
amt = p - h->root.root.string;
- shortname = bfd_malloc (amt + 1);
+ shortname = (char *) bfd_malloc (amt + 1);
if (!shortname)
goto error_free_vers;
memcpy (shortname, h->root.root.string, amt);
defined symbol, search time for N weak defined symbols will be
O(N^2). Binary search will cut it down to O(NlogN). */
amt = extsymcount * sizeof (struct elf_link_hash_entry *);
- sorted_sym_hash = bfd_malloc (amt);
+ sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt);
if (sorted_sym_hash == NULL)
goto error_return;
sym_hash = sorted_sym_hash;
/* Add this bfd to the loaded list. */
struct elf_link_loaded_list *n;
- n = bfd_alloc (abfd, sizeof (struct elf_link_loaded_list));
+ n = (struct elf_link_loaded_list *)
+ bfd_alloc (abfd, sizeof (struct elf_link_loaded_list));
if (n == NULL)
goto error_return;
n->abfd = abfd;
/* First check with only one `@'. */
len = strlen (name);
- copy = bfd_alloc (abfd, len);
+ copy = (char *) bfd_alloc (abfd, len);
if (copy == NULL)
return (struct elf_link_hash_entry *) 0 - 1;
return TRUE;
amt = c;
amt *= sizeof (bfd_boolean);
- defined = bfd_zmalloc (amt);
- included = bfd_zmalloc (amt);
+ defined = (bfd_boolean *) bfd_zmalloc (amt);
+ included = (bfd_boolean *) bfd_zmalloc (amt);
if (defined == NULL || included == NULL)
goto error_return;
static bfd_boolean
elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
{
- struct hash_codes_info *inf = data;
+ struct hash_codes_info *inf = (struct hash_codes_info *) data;
const char *name;
char *p;
unsigned long ha;
p = strchr (name, ELF_VER_CHR);
if (p != NULL)
{
- alc = bfd_malloc (p - name + 1);
+ alc = (char *) bfd_malloc (p - name + 1);
if (alc == NULL)
{
inf->error = TRUE;
static bfd_boolean
elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
{
- struct collect_gnu_hash_codes *s = data;
+ struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data;
const char *name;
char *p;
unsigned long ha;
p = strchr (name, ELF_VER_CHR);
if (p != NULL)
{
- alc = bfd_malloc (p - name + 1);
+ alc = (char *) bfd_malloc (p - name + 1);
if (alc == NULL)
{
s->error = TRUE;
static bfd_boolean
elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data)
{
- struct collect_gnu_hash_codes *s = data;
+ struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data;
unsigned long int bucket;
unsigned long int val;
since the size could be large. */
amt = maxsize;
amt *= sizeof (unsigned long int);
- counts = bfd_malloc (amt);
+ counts = (unsigned long int *) bfd_malloc (amt);
if (counts == NULL)
return 0;
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
const char *soname,
const char *rpath,
const char *filter_shlib,
+ const char *audit,
+ const char *depaudit,
const char * const *auxiliary_filters,
struct bfd_link_info *info,
asection **sinterpptr,
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
}
}
+ if (audit != NULL)
+ {
+ bfd_size_type indx;
+
+ indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
+ TRUE);
+ if (indx == (bfd_size_type) -1
+ || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
+ return FALSE;
+ }
+
+ if (depaudit != NULL)
+ {
+ bfd_size_type indx;
+
+ indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
+ TRUE);
+ if (indx == (bfd_size_type) -1
+ || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
+ return FALSE;
+ }
+
eif.info = info;
eif.verdefs = verdefs;
eif.failed = FALSE;
verlen = strlen (verstr);
newlen = namelen + verlen + 3;
- newname = bfd_malloc (newlen);
+ newname = (char *) bfd_malloc (newlen);
if (newname == NULL)
return FALSE;
memcpy (newname, name, 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;
}
s->size = size;
- s->contents = bfd_alloc (output_bfd, s->size);
+ s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
if (s->contents == NULL && s->size != 0)
return FALSE;
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;
}
s->size = size;
- s->contents = bfd_alloc (output_bfd, s->size);
+ s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
if (s->contents == NULL)
return FALSE;
&& (s->flags & SEC_EXCLUDE) == 0)
{
s->size = dynsymcount * sizeof (Elf_External_Versym);
- s->contents = bfd_zalloc (output_bfd, s->size);
+ s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
if (s->contents == NULL)
return FALSE;
if (dynsymcount != 0)
{
- s->contents = bfd_alloc (output_bfd, s->size);
+ s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
if (s->contents == NULL)
return FALSE;
time store the values in an array so that we could use them for
optimizations. */
amt = dynsymcount * sizeof (unsigned long int);
- hashcodes = bfd_malloc (amt);
+ hashcodes = (unsigned long int *) bfd_malloc (amt);
if (hashcodes == NULL)
return FALSE;
hashinf.hashcodes = hashcodes;
BFD_ASSERT (s != NULL);
hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
- s->contents = bfd_zalloc (output_bfd, s->size);
+ s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
if (s->contents == NULL)
return FALSE;
time store the values in an array so that we could use them for
optimizations. */
amt = dynsymcount * 2 * sizeof (unsigned long int);
- cinfo.hashcodes = bfd_malloc (amt);
+ cinfo.hashcodes = (long unsigned int *) bfd_malloc (amt);
if (cinfo.hashcodes == NULL)
return FALSE;
BFD_ASSERT (cinfo.min_dynindx == -1);
free (cinfo.hashcodes);
s->size = 5 * 4 + bed->s->arch_size / 8;
- contents = bfd_zalloc (output_bfd, s->size);
+ contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
if (contents == NULL)
return FALSE;
s->contents = contents;
maskwords = 1 << (maskbitslog2 - cinfo.shift1);
amt = bucketcount * sizeof (unsigned long int) * 2;
amt += maskwords * sizeof (bfd_vma);
- cinfo.bitmask = bfd_malloc (amt);
+ cinfo.bitmask = (bfd_vma *) bfd_malloc (amt);
if (cinfo.bitmask == NULL)
{
free (cinfo.hashcodes);
return FALSE;
}
- cinfo.counts = (void *) (cinfo.bitmask + maskwords);
+ cinfo.counts = (long unsigned int *) (cinfo.bitmask + maskwords);
cinfo.indx = cinfo.counts + bucketcount;
cinfo.symindx = dynsymcount - cinfo.nsyms;
memset (cinfo.bitmask, 0, maskwords * sizeof (bfd_vma));
s->size = (4 + bucketcount + cinfo.nsyms) * 4;
s->size += cinfo.maskbits / 8;
- contents = bfd_zalloc (output_bfd, s->size);
+ contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
if (contents == NULL)
{
free (cinfo.bitmask);
subclass. */
if (entry == NULL)
{
- entry = bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry));
+ entry = (struct bfd_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry));
if (entry == NULL)
return entry;
}
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;
}
struct elf_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_link_hash_table);
- ret = bfd_malloc (amt);
+ ret = (struct elf_link_hash_table *) bfd_malloc (amt);
if (ret == NULL)
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;
goto error_return;
amt = sizeof *l;
- l = bfd_alloc (abfd, amt);
+ l = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
if (l == NULL)
goto error_return;
struct elf_symbuf_head *ssymbuf, *ssymhead;
bfd_size_type i, shndx_count, total_size;
- indbuf = bfd_malloc2 (symcount, sizeof (*indbuf));
+ indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf));
if (indbuf == NULL)
return NULL;
total_size = ((shndx_count + 1) * sizeof (*ssymbuf)
+ (indbufend - indbuf) * sizeof (*ssym));
- ssymbuf = bfd_malloc (total_size);
+ ssymbuf = (struct elf_symbuf_head *) bfd_malloc (total_size);
if (ssymbuf == NULL)
{
free (indbuf);
result = FALSE;
isymbuf1 = NULL;
isymbuf2 = NULL;
- ssymbuf1 = elf_tdata (bfd1)->symbuf;
- ssymbuf2 = elf_tdata (bfd2)->symbuf;
+ ssymbuf1 = (struct elf_symbuf_head *) elf_tdata (bfd1)->symbuf;
+ ssymbuf2 = (struct elf_symbuf_head *) elf_tdata (bfd2)->symbuf;
if (ssymbuf1 == NULL)
{
if (count1 == 0 || count2 == 0 || count1 != count2)
goto done;
- symtable1 = bfd_malloc (count1 * sizeof (struct elf_symbol));
- symtable2 = bfd_malloc (count2 * sizeof (struct elf_symbol));
+ symtable1 = (struct elf_symbol *)
+ bfd_malloc (count1 * sizeof (struct elf_symbol));
+ symtable2 = (struct elf_symbol *)
+ bfd_malloc (count2 * sizeof (struct elf_symbol));
if (symtable1 == NULL || symtable2 == NULL)
goto done;
goto done;
}
- symtable1 = bfd_malloc (symcount1 * sizeof (struct elf_symbol));
- symtable2 = bfd_malloc (symcount2 * sizeof (struct elf_symbol));
+ symtable1 = (struct elf_symbol *)
+ bfd_malloc (symcount1 * sizeof (struct elf_symbol));
+ symtable2 = (struct elf_symbol *)
+ bfd_malloc (symcount2 * sizeof (struct elf_symbol));
if (symtable1 == NULL || symtable2 == NULL)
goto done;
else
shift = (8 * wordsz) - (start + len);
+ /* FIXME: octets_per_byte. */
x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset);
#ifdef DEBUG
relocation, (mask << shift),
((relocation & mask) << shift), x);
#endif
+ /* FIXME: octets_per_byte. */
put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
return r;
}
static int
elf_link_sort_cmp1 (const void *A, const void *B)
{
- const struct elf_link_sort_rela *a = A;
- const struct elf_link_sort_rela *b = B;
+ const struct elf_link_sort_rela *a = (const struct elf_link_sort_rela *) A;
+ const struct elf_link_sort_rela *b = (const struct elf_link_sort_rela *) B;
int relativea, relativeb;
relativea = a->type == reloc_class_relative;
static int
elf_link_sort_cmp2 (const void *A, const void *B)
{
- const struct elf_link_sort_rela *a = A;
- const struct elf_link_sort_rela *b = B;
+ const struct elf_link_sort_rela *a = (const struct elf_link_sort_rela *) A;
+ const struct elf_link_sort_rela *b = (const struct elf_link_sort_rela *) B;
int copya, copyb;
if (a->u.offset < b->u.offset)
count = dynamic_relocs->size / ext_size;
if (count == 0)
return 0;
- sort = bfd_zmalloc (sort_elt * count);
+ sort = (bfd_byte *) bfd_zmalloc (sort_elt * count);
if (sort == NULL)
{
}
erel = o->contents;
erelend = o->contents + o->size;
+ /* FIXME: octets_per_byte. */
p = sort + o->output_offset / ext_size * sort_elt;
while (erel < erelend)
erel = o->contents;
erelend = o->contents + o->size;
+ /* FIXME: octets_per_byte. */
p = sort + o->output_offset / ext_size * sort_elt;
while (erel < erelend)
{
bfd_size_type amt;
amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
- destshndx = bfd_realloc (destshndx, amt * 2);
+ destshndx = (Elf_External_Sym_Shndx *) bfd_realloc (destshndx,
+ amt * 2);
if (destshndx == NULL)
return 0;
finfo->symshndxbuf = destshndx;
/* Read in any version definitions. */
versymhdr = &elf_tdata (input)->dynversym_hdr;
- extversym = bfd_malloc (versymhdr->sh_size);
+ extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
if (extversym == NULL)
goto error_ret;
_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 ();
}
static bfd_boolean
elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
{
- struct elf_outext_info *eoinfo = data;
+ struct elf_outext_info *eoinfo = (struct elf_outext_info *) data;
struct elf_final_link_info *finfo = eoinfo->finfo;
bfd_boolean strip;
Elf_Internal_Sym sym;
{
/* 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
/* If we are reporting errors for this situation then do so now. */
if (ignore_undef == FALSE
&& 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)))
{
eoinfo->failed = TRUE;
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
|| h->root.type == bfd_link_hash_defweak)
sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
forced local syms when non-shared is due to a historical quirk.
STT_GNU_IFUNC symbol must go through PLT. */
if ((h->type == STT_GNU_IFUNC
- && h->ref_regular
+ && h->def_regular
&& !finfo->info->relocatable)
|| ((h->dynindx != -1
|| h->forced_local)
|| ELF_ST_BIND (sym.st_info) == STB_WEAK))
{
int bindtype;
+ unsigned int type = ELF_ST_TYPE (sym.st_info);
+
+ /* Turn an undefined IFUNC symbol into a normal FUNC symbol. */
+ if (type == STT_GNU_IFUNC)
+ type = STT_FUNC;
if (h->ref_regular_nonweak)
bindtype = STB_GLOBAL;
else
bindtype = STB_WEAK;
- sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
+ sym.st_info = ELF_ST_INFO (bindtype, type);
}
/* If this is a symbol defined in a dynamic library, don't use the
break;
default:
{
+ /* 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,
bfd_boolean ok;
const char *sym_name;
- size = bfd_get_reloc_size (howto);
- buf = bfd_zmalloc (size);
+ size = (bfd_size_type) bfd_get_reloc_size (howto);
+ buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == NULL)
return FALSE;
rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
offset &= ~(bfd_vma) 0 << s->alignment_power;
s->output_offset = offset;
sections[n]->offset = offset;
+ /* FIXME: octets_per_byte. */
offset += sections[n]->size;
}
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;
finfo.symbuf_size = max_sym_count;
amt = finfo.symbuf_size;
amt *= bed->s->sizeof_sym;
- finfo.symbuf = bfd_malloc (amt);
+ finfo.symbuf = (bfd_byte *) bfd_malloc (amt);
if (finfo.symbuf == NULL)
goto error_return;
if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
finfo.shndxbuf_size = amt;
amt *= sizeof (Elf_External_Sym_Shndx);
- finfo.symshndxbuf = bfd_zmalloc (amt);
+ finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt);
if (finfo.symshndxbuf == NULL)
goto error_return;
}
files. */
if (max_contents_size != 0)
{
- finfo.contents = bfd_malloc (max_contents_size);
+ finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
if (finfo.contents == NULL)
goto error_return;
}
{
amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
amt *= sizeof (Elf_Internal_Rela);
- finfo.internal_relocs = bfd_malloc (amt);
+ finfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
if (finfo.internal_relocs == NULL)
goto error_return;
}
if (max_sym_count != 0)
{
amt = max_sym_count * bed->s->sizeof_sym;
- finfo.external_syms = bfd_malloc (amt);
+ finfo.external_syms = (bfd_byte *) bfd_malloc (amt);
if (finfo.external_syms == NULL)
goto error_return;
amt = max_sym_count * sizeof (Elf_Internal_Sym);
- finfo.internal_syms = bfd_malloc (amt);
+ finfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
if (finfo.internal_syms == NULL)
goto error_return;
amt = max_sym_count * sizeof (long);
- finfo.indices = bfd_malloc (amt);
+ finfo.indices = (long int *) bfd_malloc (amt);
if (finfo.indices == NULL)
goto error_return;
amt = max_sym_count * sizeof (asection *);
- finfo.sections = bfd_malloc (amt);
+ finfo.sections = (asection **) bfd_malloc (amt);
if (finfo.sections == NULL)
goto error_return;
}
if (max_sym_shndx_count != 0)
{
amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx);
- finfo.locsym_shndx = bfd_malloc (amt);
+ finfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
if (finfo.locsym_shndx == NULL)
goto error_return;
}
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;
}
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);
!= SHT_STRTAB)
|| strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
{
+ /* FIXME: octets_per_byte. */
if (! bfd_set_section_contents (abfd, o->output_section,
o->contents,
(file_ptr) o->output_offset,
if (attr_section)
{
- bfd_byte *contents = bfd_malloc (attr_size);
+ bfd_byte *contents = (bfd_byte *) bfd_malloc (attr_size);
if (contents == NULL)
return FALSE; /* Bail out and fail. */
bfd_elf_set_obj_attr_contents (abfd, contents, attr_size);
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;
}
&& !h->root.u.def.section->gc_mark
&& !(h->root.u.def.section->owner->flags & DYNAMIC))
{
- struct elf_gc_sweep_symbol_info *inf = data;
+ struct elf_gc_sweep_symbol_info *inf =
+ (struct elf_gc_sweep_symbol_info *) data;
(*inf->hide_symbol) (inf->info, h, TRUE);
}
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;
}
win:
if (!child->vtable)
{
- child->vtable = bfd_zalloc (abfd, sizeof (*child->vtable));
+ child->vtable = (struct elf_link_virtual_table_entry *)
+ bfd_zalloc (abfd, sizeof (*child->vtable));
if (!child->vtable)
return FALSE;
}
if (!h->vtable)
{
- h->vtable = bfd_zalloc (abfd, sizeof (*h->vtable));
+ h->vtable = (struct elf_link_virtual_table_entry *)
+ bfd_zalloc (abfd, sizeof (*h->vtable));
if (!h->vtable)
return FALSE;
}
if (ptr)
{
- ptr = bfd_realloc (ptr - 1, bytes);
+ ptr = (bfd_boolean *) bfd_realloc (ptr - 1, bytes);
if (ptr != NULL)
{
}
}
else
- ptr = bfd_zmalloc (bytes);
+ ptr = (bfd_boolean *) bfd_zmalloc (bytes);
if (ptr == NULL)
return FALSE;
static bfd_boolean
elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg)
{
- struct alloc_got_off_arg *gofarg = arg;
+ struct alloc_got_off_arg *gofarg = (struct alloc_got_off_arg *) arg;
bfd *obfd = gofarg->info->output_bfd;
const struct elf_backend_data *bed = get_elf_backend_data (obfd);
bfd_boolean
bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
{
- struct elf_reloc_cookie *rcookie = cookie;
+ struct elf_reloc_cookie *rcookie = (struct elf_reloc_cookie *) cookie;
if (rcookie->bad_symtab)
rcookie->rel = rcookie->rels;
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;
+}