/* This function is called to create an indirect symbol from the
default for the symbol with the default version if needed. The
- symbol is described by H, NAME, SYM, SEC, VALUE, and OVERRIDE. We
+ symbol is described by H, NAME, SYM, PSEC, VALUE, and OVERRIDE. We
set DYNSYM if the new indirect symbol is dynamic. DT_NEEDED
indicates if it comes from a DT_NEEDED entry of a shared object. */
static boolean
-elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
+elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
dynsym, override, dt_needed)
bfd *abfd;
struct bfd_link_info *info;
struct elf_link_hash_entry *h;
const char *name;
Elf_Internal_Sym *sym;
- asection **sec;
+ asection **psec;
bfd_vma *value;
boolean *dynsym;
boolean override;
boolean size_change_ok;
char *shortname;
struct elf_link_hash_entry *hi;
+ struct bfd_link_hash_entry *bh;
struct elf_backend_data *bed;
boolean collect;
boolean dynamic;
char *p;
size_t len, shortlen;
+ asection *sec;
/* If this symbol has a version, and it is the default version, we
create an indirect symbol from the default name to the fully
actually going to define an indirect symbol. */
type_change_ok = false;
size_change_ok = false;
- if (! elf_merge_symbol (abfd, info, shortname, sym, sec, value,
+ sec = *psec;
+ if (! elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
&hi, &override, &type_change_ok,
&size_change_ok, dt_needed))
return false;
if (! override)
{
+ bh = &hi->root;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT, bfd_ind_section_ptr,
- (bfd_vma) 0, name, false, collect,
- (struct bfd_link_hash_entry **) &hi)))
+ (bfd_vma) 0, name, false, collect, &bh)))
return false;
+ hi = (struct elf_link_hash_entry *) bh;
}
else
{
| ELF_LINK_HASH_DEF_REGULAR)) == 0);
ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
- (*bed->elf_backend_copy_indirect_symbol) (ht, hi);
+ (*bed->elf_backend_copy_indirect_symbol) (bed, ht, hi);
/* See if the new flags lead us to realize that the symbol must
be dynamic. */
/* Once again, merge with any existing symbol. */
type_change_ok = false;
size_change_ok = false;
- if (! elf_merge_symbol (abfd, info, shortname, sym, sec, value,
+ sec = *psec;
+ if (! elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
&hi, &override, &type_change_ok,
&size_change_ok, dt_needed))
return false;
if (override)
{
/* Here SHORTNAME is a versioned name, so we don't expect to see
- the type of override we do in the case above. */
- (*_bfd_error_handler)
- (_("%s: warning: unexpected redefinition of `%s'"),
- bfd_archive_filename (abfd), shortname);
+ the type of override we do in the case above unless it is
+ overridden by a versioned definiton. */
+ if (hi->root.type != bfd_link_hash_defined
+ && hi->root.type != bfd_link_hash_defweak)
+ (*_bfd_error_handler)
+ (_("%s: warning: unexpected redefinition of indirect versioned symbol `%s'"),
+ bfd_archive_filename (abfd), shortname);
}
else
{
+ bh = &hi->root;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT,
- bfd_ind_section_ptr, (bfd_vma) 0, name, false,
- collect, (struct bfd_link_hash_entry **) &hi)))
+ bfd_ind_section_ptr, (bfd_vma) 0, name, false, collect, &bh)))
return false;
+ hi = (struct elf_link_hash_entry *) bh;
/* If there is a duplicate definition somewhere, then HI may not
point to an indirect symbol. We will have reported an error
& (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_DEF_REGULAR)) == 0);
- (*bed->elf_backend_copy_indirect_symbol) (h, hi);
+ (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
/* See if the new flags lead us to realize that the symbol
must be dynamic. */
flagword flags;
register asection *s;
struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh;
struct elf_backend_data *bed;
if (! is_elf_hash_table (info))
creating a .dynamic section. We don't want to define it if there
is no .dynamic section, since on some ELF platforms the start up
code examines it to decide how to initialize the process. */
- h = NULL;
+ bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, "_DYNAMIC", BSF_GLOBAL, s, (bfd_vma) 0,
- (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
+ (const char *) 0, 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->type = STT_OBJECT;
return true;
}
-
-/* Record a new local dynamic symbol. */
-
-boolean
-elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
- struct bfd_link_info *info;
- bfd *input_bfd;
- long input_indx;
-{
- struct elf_link_local_dynamic_entry *entry;
- struct elf_link_hash_table *eht;
- struct elf_strtab_hash *dynstr;
- Elf_External_Sym esym;
- Elf_External_Sym_Shndx eshndx;
- Elf_External_Sym_Shndx *shndx;
- unsigned long dynstr_index;
- char *name;
- file_ptr pos;
- bfd_size_type amt;
-
- if (! is_elf_hash_table (info))
- return false;
-
- /* See if the entry exists already. */
- for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
- if (entry->input_bfd == input_bfd && entry->input_indx == input_indx)
- return true;
-
- entry = (struct elf_link_local_dynamic_entry *)
- bfd_alloc (input_bfd, (bfd_size_type) sizeof (*entry));
- if (entry == NULL)
- return false;
-
- /* Go find the symbol, so that we can find it's name. */
- amt = sizeof (Elf_External_Sym);
- pos = elf_tdata (input_bfd)->symtab_hdr.sh_offset + input_indx * amt;
- if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
- || bfd_bread ((PTR) &esym, amt, input_bfd) != amt)
- return false;
- shndx = NULL;
- if (elf_tdata (input_bfd)->symtab_shndx_hdr.sh_size != 0)
- {
- amt = sizeof (Elf_External_Sym_Shndx);
- pos = elf_tdata (input_bfd)->symtab_shndx_hdr.sh_offset;
- pos += input_indx * amt;
- shndx = &eshndx;
- if (bfd_seek (input_bfd, pos, SEEK_SET) != 0
- || bfd_bread ((PTR) shndx, amt, input_bfd) != amt)
- return false;
- }
- elf_swap_symbol_in (input_bfd, (const PTR) &esym, (const PTR) shndx,
- &entry->isym);
-
- name = (bfd_elf_string_from_elf_section
- (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link,
- entry->isym.st_name));
-
- dynstr = elf_hash_table (info)->dynstr;
- if (dynstr == NULL)
- {
- /* Create a strtab to hold the dynamic symbol names. */
- elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init ();
- if (dynstr == NULL)
- return false;
- }
-
- dynstr_index = _bfd_elf_strtab_add (dynstr, name, false);
- if (dynstr_index == (unsigned long) -1)
- return false;
- entry->isym.st_name = dynstr_index;
-
- eht = elf_hash_table (info);
-
- entry->next = eht->dynlocal;
- eht->dynlocal = entry;
- entry->input_bfd = input_bfd;
- entry->input_indx = input_indx;
- eht->dynsymcount++;
-
- /* Whatever binding the symbol had before, it's now local. */
- entry->isym.st_info
- = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info));
-
- /* The dynindx will be set at the end of size_dynamic_sections. */
-
- return true;
-}
\f
/* Read and swap the relocs from the section indicated by SHDR. This
may be either a REL or a RELA section. The relocations are
struct elf_info_failed eif;
struct elf_link_hash_entry *h;
asection *dynstr;
+ struct bfd_elf_version_tree *t;
+ struct bfd_elf_version_expr *d;
+ boolean all_defined;
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (*sinterpptr != NULL || info->shared);
return false;
}
+ /* Make all global versions with definiton. */
+ for (t = verdefs; t != NULL; t = t->next)
+ for (d = t->globals; d != NULL; d = d->next)
+ if (!d->symver && strchr (d->pattern, '*') == NULL)
+ {
+ const char *verstr, *name;
+ size_t namelen, verlen, newlen;
+ char *newname, *p;
+ struct elf_link_hash_entry *newh;
+
+ name = d->pattern;
+ namelen = strlen (name);
+ verstr = t->name;
+ verlen = strlen (verstr);
+ newlen = namelen + verlen + 3;
+
+ newname = (char *) bfd_malloc ((bfd_size_type) newlen);
+ if (newname == NULL)
+ return false;
+ memcpy (newname, name, namelen);
+
+ /* Check the hidden versioned definition. */
+ p = newname + namelen;
+ *p++ = ELF_VER_CHR;
+ memcpy (p, verstr, verlen + 1);
+ newh = elf_link_hash_lookup (elf_hash_table (info),
+ newname, false, false,
+ false);
+ if (newh == NULL
+ || (newh->root.type != bfd_link_hash_defined
+ && newh->root.type != bfd_link_hash_defweak))
+ {
+ /* Check the default versioned definition. */
+ *p++ = ELF_VER_CHR;
+ memcpy (p, verstr, verlen + 1);
+ newh = elf_link_hash_lookup (elf_hash_table (info),
+ newname, false, false,
+ false);
+ }
+ free (newname);
+
+ /* 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->root.type == bfd_link_hash_defined
+ || newh->root.type == bfd_link_hash_defweak))
+ d->symver = 1;
+ }
+
/* Attach all the symbols to their version information. */
asvinfo.output_bfd = output_bfd;
asvinfo.info = info;
if (asvinfo.failed)
return false;
+ if (!info->allow_undefined_version)
+ {
+ /* Check if all global versions have a definiton. */
+ all_defined = true;
+ for (t = verdefs; t != NULL; t = t->next)
+ for (d = t->globals; d != NULL; d = d->next)
+ if (!d->symver && !d->script
+ && strchr (d->pattern, '*') == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%s: undefined version: %s"),
+ d->pattern, t->name);
+ all_defined = false;
+ }
+
+ if (!all_defined)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ }
+
/* Find all symbols which were defined in a dynamic object and make
the backend pick a reasonable value for them. */
elf_link_hash_traverse (elf_hash_table (info),
unsigned int cdeps;
struct bfd_elf_version_deps *n;
struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh;
cdeps = 0;
for (n = t->deps; n != NULL; n = n->next)
++cdeps;
/* Add a symbol representing this version. */
- h = NULL;
+ bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, dynobj, t->name, BSF_GLOBAL, bfd_abs_section_ptr,
(bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (dynobj)->collect,
- (struct bfd_link_hash_entry **) &h)))
+ 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->type = STT_OBJECT;
{
struct elf_link_hash_entry *weakdef;
+ weakdef = h->weakdef;
+ if (h->root.type == bfd_link_hash_indirect)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
BFD_ASSERT (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak);
- weakdef = h->weakdef;
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);
struct elf_backend_data *bed;
bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
- (*bed->elf_backend_copy_indirect_symbol) (weakdef, h);
+ (*bed->elf_backend_copy_indirect_symbol) (bed, weakdef, h);
}
}
(_("%s: undefined versioned symbol name %s"),
bfd_get_filename (sinfo->output_bfd), h->root.root.string);
bfd_set_error (bfd_error_bad_value);
- error_return:
sinfo->failed = true;
return false;
}
{
if (t->globals != NULL)
{
+ boolean matched;
+
+ matched = false;
for (d = t->globals; d != NULL; d = d->next)
{
if ((*d->match) (d, h->root.root.string))
{
- h->verinfo.vertree = t;
- local_ver = NULL;
- break;
+ if (d->symver)
+ matched = true;
+ else
+ {
+ /* There is a version without definition. Make
+ the symbol the default definition for this
+ version. */
+ h->verinfo.vertree = t;
+ local_ver = NULL;
+ d->script = 1;
+ break;
+ }
}
}
if (d != NULL)
break;
+ else if (matched)
+ /* There is no undefined version for this symbol. Hide the
+ default one. */
+ (*bed->elf_backend_hide_symbol) (info, h, true);
}
if (t->locals != NULL)
(*bed->elf_backend_hide_symbol) (info, h, true);
}
}
-
- /* We need to check if a hidden versioned definition should
- hide the default one. */
- if (h->dynindx != -1 && h->verinfo.vertree != NULL)
- {
- const char *verstr, *name;
- size_t namelen, verlen, newlen;
- char *newname;
- struct elf_link_hash_entry *newh;
-
- name = h->root.root.string;
- namelen = strlen (name);
- verstr = h->verinfo.vertree->name;
- verlen = strlen (verstr);
- newlen = namelen + verlen + 2;
-
- newname = (char *) bfd_malloc ((bfd_size_type) newlen);
- if (newname == NULL)
- goto error_return;
- memcpy (newname, name, namelen);
-
- /* Check the hidden versioned definition. */
- p = newname + namelen;
- *p++ = ELF_VER_CHR;
- memcpy (p, verstr, verlen + 1);
- newh = elf_link_hash_lookup (elf_hash_table (info), newname,
- false, false, false);
-
- if (newh
- && (newh->root.type == bfd_link_hash_defined
- || newh->root.type == bfd_link_hash_defweak))
- /* We found a hidden versioned definition. Hide the
- default one. */
- (*bed->elf_backend_hide_symbol) (info, h, true);
-
- free (newname);
- }
}
return true;
/* If we're stripping it, then it was just a dynamic symbol, and
there's nothing else to do. */
- if (strip)
+ if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
return true;
h->indx = bfd_get_symcount (finfo->output_bfd);
|| h->root.type == bfd_link_hash_defweak)
&& elf_discarded_section (h->root.u.def.section))
{
-#if BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0)
{
-#if BFD_VERSION_DATE > 20021005
- (*finfo->info->callbacks->warning)
- (finfo->info,
- _("warning: relocation against removed section; zeroing"),
- NULL, input_bfd, o, rel->r_offset);
-#endif
BFD_ASSERT (r_symndx != 0);
memset (rel, 0, sizeof (*rel));
}
else
-#endif
{
if (! ((*finfo->info->callbacks->undefined_symbol)
(finfo->info, h->root.root.string,
if (sec != NULL && elf_discarded_section (sec))
{
-#if BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0
|| (sec->flags & SEC_LINK_ONCE) != 0)
{
-#if BFD_VERSION_DATE > 20021005
- (*finfo->info->callbacks->warning)
- (finfo->info,
- _("warning: relocation against removed section"),
- NULL, input_bfd, o, rel->r_offset);
-#endif
BFD_ASSERT (r_symndx != 0);
rel->r_info
= ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
rel->r_addend = 0;
}
else
-#endif
{
boolean ok;
const char *msg
if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, ehdr,
elf_reloc_symbol_deleted_p,
&cookie))
- ret = true;
+ {
+ /* Relocs have been edited. Ensure edited version is
+ used later in relocate_section. */
+ elf_section_data (eh)->relocs = cookie.rels;
+ ret = true;
+ }
if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels)
free (cookie.rels);
}