h = (struct elf_link_hash_entry *) bh;
h->def_regular = 1;
h->type = STT_OBJECT;
+ h->other = STV_HIDDEN;
if (! info->executable
&& ! bfd_elf_link_record_dynamic_symbol (info, h))
flags = bed->dynamic_sec_flags;
pltflags = flags;
- pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
+ /* We do not clear SEC_ALLOC here because we still want the OS to
+ allocate space for the section; it's just that there's nothing
+ to read in from the object file. */
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
+ else
+ pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
int bind;
bfd *oldbfd;
bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
- bfd_boolean newweak, oldweak;
+ bfd_boolean newweak, oldweak, old_asneeded;
*skip = FALSE;
*override = FALSE;
else
olddef = TRUE;
+ /* If the old definition came from an as-needed dynamic library which
+ wasn't found to be needed, treat the sym as undefined. */
+ old_asneeded = FALSE;
+ if (newdyn
+ && olddyn
+ && (elf_dyn_lib_class (oldbfd) & DYN_AS_NEEDED) != 0)
+ old_asneeded = TRUE;
+
/* Check TLS symbol. */
if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)
&& ELF_ST_TYPE (sym->st_info) != h->type)
if (olddyn
&& olddef
+ && !old_asneeded
&& h->root.type == bfd_link_hash_defined
&& h->def_dynamic
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
if (newdyn
&& newdef
- && (olddef
+ && ((olddef && !old_asneeded)
|| (h->root.type == bfd_link_hash_common
&& (newweak
|| ELF_ST_TYPE (sym->st_info) == STT_FUNC))))
symbol is a function or is weak. */
flip = NULL;
- if (! newdyn
+ if ((!newdyn || old_asneeded)
&& (newdef
|| (bfd_is_com_section (sec)
&& (oldweak
_bfd_elf_swap_verdef_in (output_bfd, (Elf_External_Verdef *) p,
&def);
p += sizeof (Elf_External_Verdef);
+ if (def.vd_aux != sizeof (Elf_External_Verdef))
+ continue;
for (i = 0; i < def.vd_cnt; ++i)
{
_bfd_elf_swap_verdaux_in (output_bfd,
if (dynamic)
{
/* Read in any version definitions. */
- if (! _bfd_elf_slurp_version_tables (abfd))
+ if (!_bfd_elf_slurp_version_tables (abfd,
+ info->default_imported_symver))
goto error_free_sym;
/* Read in the symbol versions, but don't bother to convert them
sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (sec == NULL)
sec = bfd_abs_section_ptr;
+ else if (sec->kept_section)
+ {
+ /* Symbols from discarded section are undefined. */
+ sec = bfd_und_section_ptr;
+ isym->st_shndx = SHN_UNDEF;
+ }
else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
value -= sec->vma;
}
unsigned int vernum = 0;
bfd_boolean skip;
- if (ever != NULL)
+ if (ever == NULL)
{
- _bfd_elf_swap_versym_in (abfd, ever, &iver);
- vernum = iver.vs_vers & VERSYM_VERSION;
-
- /* If this is a hidden symbol, or if it is not version
- 1, we append the version name to the symbol name.
- However, we do not modify a non-hidden absolute
- symbol, because it might be the version symbol
- itself. FIXME: What if it isn't? */
- if ((iver.vs_vers & VERSYM_HIDDEN) != 0
- || (vernum > 1 && ! bfd_is_abs_section (sec)))
+ if (info->default_imported_symver)
+ /* Use the default symbol version created earlier. */
+ iver.vs_vers = elf_tdata (abfd)->cverdefs;
+ else
+ iver.vs_vers = 0;
+ }
+ else
+ _bfd_elf_swap_versym_in (abfd, ever, &iver);
+
+ vernum = iver.vs_vers & VERSYM_VERSION;
+
+ /* If this is a hidden symbol, or if it is not version
+ 1, we append the version name to the symbol name.
+ However, we do not modify a non-hidden absolute
+ symbol, because it might be the version symbol
+ itself. FIXME: What if it isn't? */
+ if ((iver.vs_vers & VERSYM_HIDDEN) != 0
+ || (vernum > 1 && ! bfd_is_abs_section (sec)))
+ {
+ const char *verstr;
+ size_t namelen, verlen, newlen;
+ char *newname, *p;
+
+ if (isym->st_shndx != SHN_UNDEF)
{
- const char *verstr;
- size_t namelen, verlen, newlen;
- char *newname, *p;
+ if (vernum > elf_tdata (abfd)->cverdefs)
+ verstr = NULL;
+ else if (vernum > 1)
+ verstr =
+ elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+ else
+ verstr = "";
- if (isym->st_shndx != SHN_UNDEF)
+ if (verstr == NULL)
{
- if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
- {
- (*_bfd_error_handler)
- (_("%B: %s: invalid version %u (max %d)"),
- abfd, name, vernum,
- elf_tdata (abfd)->dynverdef_hdr.sh_info);
- bfd_set_error (bfd_error_bad_value);
- goto error_free_vers;
- }
- else if (vernum > 1)
- verstr =
- elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
- else
- verstr = "";
+ (*_bfd_error_handler)
+ (_("%B: %s: invalid version %u (max %d)"),
+ abfd, name, vernum,
+ elf_tdata (abfd)->cverdefs);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_free_vers;
}
- else
+ }
+ else
+ {
+ /* We cannot simply test for the number of
+ entries in the VERNEED section since the
+ numbers for the needed versions do not start
+ at 0. */
+ Elf_Internal_Verneed *t;
+
+ verstr = NULL;
+ for (t = elf_tdata (abfd)->verref;
+ t != NULL;
+ t = t->vn_nextref)
{
- /* We cannot simply test for the number of
- entries in the VERNEED section since the
- numbers for the needed versions do not start
- at 0. */
- Elf_Internal_Verneed *t;
-
- verstr = NULL;
- for (t = elf_tdata (abfd)->verref;
- t != NULL;
- t = t->vn_nextref)
- {
- Elf_Internal_Vernaux *a;
+ Elf_Internal_Vernaux *a;
- for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ {
+ if (a->vna_other == vernum)
{
- if (a->vna_other == vernum)
- {
- verstr = a->vna_nodename;
- break;
- }
+ verstr = a->vna_nodename;
+ break;
}
- if (a != NULL)
- break;
- }
- if (verstr == NULL)
- {
- (*_bfd_error_handler)
- (_("%B: %s: invalid needed version %d"),
- abfd, name, vernum);
- bfd_set_error (bfd_error_bad_value);
- goto error_free_vers;
}
+ if (a != NULL)
+ break;
+ }
+ if (verstr == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%B: %s: invalid needed version %d"),
+ abfd, name, vernum);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_free_vers;
}
+ }
- namelen = strlen (name);
- verlen = strlen (verstr);
- newlen = namelen + verlen + 2;
- if ((iver.vs_vers & VERSYM_HIDDEN) == 0
- && isym->st_shndx != SHN_UNDEF)
- ++newlen;
+ namelen = strlen (name);
+ verlen = strlen (verstr);
+ newlen = namelen + verlen + 2;
+ if ((iver.vs_vers & VERSYM_HIDDEN) == 0
+ && isym->st_shndx != SHN_UNDEF)
+ ++newlen;
- newname = bfd_alloc (abfd, newlen);
- if (newname == NULL)
- goto error_free_vers;
- memcpy (newname, name, namelen);
- p = newname + namelen;
- *p++ = ELF_VER_CHR;
- /* If this is a defined non-hidden version symbol,
- we add another @ to the name. This indicates the
- default version of the symbol. */
- if ((iver.vs_vers & VERSYM_HIDDEN) == 0
- && isym->st_shndx != SHN_UNDEF)
- *p++ = ELF_VER_CHR;
- memcpy (p, verstr, verlen + 1);
+ newname = bfd_alloc (abfd, newlen);
+ if (newname == NULL)
+ goto error_free_vers;
+ memcpy (newname, name, namelen);
+ p = newname + namelen;
+ *p++ = ELF_VER_CHR;
+ /* If this is a defined non-hidden version symbol,
+ we add another @ to the name. This indicates the
+ default version of the symbol. */
+ if ((iver.vs_vers & VERSYM_HIDDEN) == 0
+ && isym->st_shndx != SHN_UNDEF)
+ *p++ = ELF_VER_CHR;
+ memcpy (p, verstr, verlen + 1);
- name = newname;
- }
+ name = newname;
}
if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
(*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
dynamic);
+ /* If this symbol has default visibility and the user has requested
+ we not re-export it, then mark it as hidden. */
+ if (definition && !dynamic
+ && (abfd->no_export
+ || (abfd->my_archive && abfd->my_archive->no_export))
+ && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
+ isym->st_other = STV_HIDDEN | (isym->st_other & ~ ELF_ST_VISIBILITY (-1));
+
if (isym->st_other != 0 && !dynamic)
{
unsigned char hvis, symvis, other, nvis;
goto error_free_vers;
}
+ elf_dyn_lib_class (abfd) &= ~DYN_AS_NEEDED;
+
add_needed = TRUE;
ret = elf_add_dt_needed_tag (info, soname, add_needed);
if (ret < 0)
if (verdefs != NULL && verdefs->vernum == 0)
verdefs = verdefs->next;
- if (verdefs == NULL)
+ if (verdefs == NULL && !info->create_default_symver)
_bfd_strip_section_from_output (info, s);
else
{
bfd_byte *p;
Elf_Internal_Verdef def;
Elf_Internal_Verdaux defaux;
+ struct bfd_link_hash_entry *bh;
+ struct elf_link_hash_entry *h;
+ const char *name;
cdefs = 0;
size = 0;
size += sizeof (Elf_External_Verdaux);
++cdefs;
+ /* Make space for the default version. */
+ if (info->create_default_symver)
+ {
+ size += sizeof (Elf_External_Verdef);
+ ++cdefs;
+ }
+
for (t = verdefs; t != NULL; t = t->next)
{
struct bfd_elf_version_deps *n;
def.vd_flags = VER_FLG_BASE;
def.vd_ndx = 1;
def.vd_cnt = 1;
- def.vd_aux = sizeof (Elf_External_Verdef);
- def.vd_next = (sizeof (Elf_External_Verdef)
- + sizeof (Elf_External_Verdaux));
+ if (info->create_default_symver)
+ {
+ def.vd_aux = 2 * sizeof (Elf_External_Verdef);
+ def.vd_next = sizeof (Elf_External_Verdef);
+ }
+ else
+ {
+ def.vd_aux = sizeof (Elf_External_Verdef);
+ def.vd_next = (sizeof (Elf_External_Verdef)
+ + sizeof (Elf_External_Verdaux));
+ }
if (soname_indx != (bfd_size_type) -1)
{
soname_indx);
def.vd_hash = bfd_elf_hash (soname);
defaux.vda_name = soname_indx;
+ name = soname;
}
else
{
- const char *name;
bfd_size_type indx;
name = basename (output_bfd->filename);
_bfd_elf_swap_verdef_out (output_bfd, &def,
(Elf_External_Verdef *) p);
p += sizeof (Elf_External_Verdef);
+ if (info->create_default_symver)
+ {
+ /* Add a symbol representing this version. */
+ bh = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, dynobj, name, BSF_GLOBAL, bfd_abs_section_ptr,
+ 0, NULL, FALSE,
+ get_elf_backend_data (dynobj)->collect, &bh)))
+ return FALSE;
+ h = (struct elf_link_hash_entry *) bh;
+ h->non_elf = 0;
+ h->def_regular = 1;
+ h->type = STT_OBJECT;
+ h->verinfo.vertree = NULL;
+
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+
+ /* Create a duplicate of the base version with the same
+ aux block, but different flags. */
+ def.vd_flags = 0;
+ def.vd_ndx = 2;
+ def.vd_aux = sizeof (Elf_External_Verdef);
+ if (verdefs)
+ def.vd_next = (sizeof (Elf_External_Verdef)
+ + sizeof (Elf_External_Verdaux));
+ else
+ def.vd_next = 0;
+ _bfd_elf_swap_verdef_out (output_bfd, &def,
+ (Elf_External_Verdef *) p);
+ p += sizeof (Elf_External_Verdef);
+ }
_bfd_elf_swap_verdaux_out (output_bfd, &defaux,
(Elf_External_Verdaux *) p);
p += sizeof (Elf_External_Verdaux);
{
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)
&& t->locals.list == NULL
&& ! t->used)
def.vd_flags |= VER_FLG_WEAK;
- def.vd_ndx = t->vernum + 1;
+ def.vd_ndx = t->vernum + (info->create_default_symver ? 2 : 1);
def.vd_cnt = cdeps + 1;
def.vd_hash = bfd_elf_hash (t->name);
def.vd_aux = sizeof (Elf_External_Verdef);
s = bfd_get_section_by_name (dynobj, ".gnu.version");
BFD_ASSERT (s != NULL);
if (dynsymcount == 0
- || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
+ || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL
+ && !info->create_default_symver))
{
_bfd_strip_section_from_output (info, s);
/* The DYNSYMCOUNT might have changed if we were going to
iversym.vs_vers = 1;
else
iversym.vs_vers = h->verinfo.vertree->vernum + 1;
+ if (finfo->info->create_default_symver)
+ iversym.vs_vers++;
}
if (h->hidden)
{
Elf_Internal_Sym *sym = isymbuf + r_symndx;
ps = &finfo->sections[r_symndx];
- sym_name = bfd_elf_local_sym_name (input_bfd, sym);
+ sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym);
}
/* Complain if the definition comes from a
else
sym_name = link_order->u.reloc.p->u.name;
if (! ((*info->callbacks->reloc_overflow)
- (info, sym_name, howto->name, addend, NULL, NULL, 0)))
+ (info, NULL, sym_name, howto->name, addend, NULL,
+ NULL, (bfd_vma) 0)))
{
free (buf);
return FALSE;