/* ELF linker support.
- Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
bfd *oldbfd;
boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
- /* This code is for coping with dynamic objects, and is only useful
- if we are doing an ELF link. */
- if (info->hash->creator != abfd->xvec)
- return true;
-
*override = false;
- *type_change_ok = false;
- *size_change_ok = false;
sec = *psec;
bind = ELF_ST_BIND (sym->st_info);
return false;
*sym_hash = h;
+ /* This code is for coping with dynamic objects, and is only useful
+ if we are doing an ELF link. */
+ if (info->hash->creator != abfd->xvec)
+ return true;
+
/* For merging, we only care about real symbols. */
while (h->root.type == bfd_link_hash_indirect
if (info->hash->creator->flavour == bfd_target_elf_flavour)
{
Elf_Internal_Versym iver;
- int vernum;
+ unsigned int vernum = 0;
boolean override;
if (ever != NULL)
if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
{
(*_bfd_error_handler)
- ("%s: %s: invalid version %d (max %d)",
+ (_("%s: %s: invalid version %u (max %d)"),
abfd->filename, name, vernum,
elf_tdata (abfd)->dynverdef_hdr.sh_info);
bfd_set_error (bfd_error_bad_value);
if (verstr == NULL)
{
(*_bfd_error_handler)
- ("%s: %s: invalid needed version %d",
+ (_("%s: %s: invalid needed version %d"),
abfd->filename, name, vernum);
bfd_set_error (bfd_error_bad_value);
goto error_return;
if (h->root.type == bfd_link_hash_common)
old_alignment = h->root.u.c.p->alignment_power;
- if (ever != NULL
+ if (elf_tdata (abfd)->verdef != NULL
&& ! override
&& vernum > 1
- && (h->verinfo.verdef == NULL || definition))
+ && definition)
h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
}
{
if (h->size != 0 && h->size != sym.st_size && ! size_change_ok)
(*_bfd_error_handler)
- ("Warning: size of symbol `%s' changed from %lu to %lu in %s",
+ (_("Warning: size of symbol `%s' changed from %lu to %lu in %s"),
name, (unsigned long) h->size, (unsigned long) sym.st_size,
bfd_get_filename (abfd));
&& h->type != ELF_ST_TYPE (sym.st_info)
&& ! type_change_ok)
(*_bfd_error_handler)
- ("Warning: type of symbol `%s' changed from %d to %d in %s",
+ (_("Warning: type of symbol `%s' changed from %d to %d in %s"),
name, h->type, ELF_ST_TYPE (sym.st_info),
bfd_get_filename (abfd));
purposes of the merge, act as though we were
defining the symbol we just defined, although we
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, &hi, &override,
&type_change_ok, &size_change_ok))
strcpy (shortname + (p - name), p + 1);
/* 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, &hi, &override,
&type_change_ok, &size_change_ok))
don't expect to see the type of override we
do in the case above. */
(*_bfd_error_handler)
- ("%s: warning: unexpected redefinition of `%s'",
+ (_("%s: warning: unexpected redefinition of `%s'"),
bfd_get_filename (abfd), shortname);
}
else
s = bfd_make_section (abfd, ".gnu.version_d");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, 2))
+ || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
return false;
s = bfd_make_section (abfd, ".gnu.version");
s = bfd_make_section (abfd, ".gnu.version_r");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, 2))
+ || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
return false;
s = bfd_make_section (abfd, ".dynsym");
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
h->root.type = bfd_link_hash_undefined;
+ /* If this symbol is not being provided by the linker script, and it is
+ currently defined by a dynamic object, but not by a regular object,
+ then clear out any version information because the symbol will not be
+ associated with the dynamic object any more. */
+ if (!provide
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ h->verinfo.verdef = NULL;
+
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
*sinterpptr = NULL;
- soname_indx = -1;
+ soname_indx = (bfd_size_type) -1;
if (info->hash->creator->flavour != bfd_target_elf_flavour)
return true;
def.vd_next = (sizeof (Elf_External_Verdef)
+ sizeof (Elf_External_Verdaux));
- if (soname_indx != -1)
+ if (soname_indx != (bfd_size_type) -1)
{
def.vd_hash = bfd_elf_hash ((const unsigned char *) soname);
defaux.vda_name = soname_indx;
for (n = t->deps; n != NULL; n = n->next)
{
- defaux.vda_name = n->version_needed->name_indx;
+ if (n->version_needed == NULL)
+ {
+ /* This can happen if there was an error in the
+ version script. */
+ defaux.vda_name = 0;
+ }
+ else
+ defaux.vda_name = n->version_needed->name_indx;
if (n->next == NULL)
defaux.vda_next = 0;
else
{
if (strcmp (t->name, p) == 0)
{
+ int len;
+ char *alc;
+ struct bfd_elf_version_expr *d;
+
+ len = p - h->root.root.string;
+ alc = bfd_alloc (sinfo->output_bfd, len);
+ if (alc == NULL)
+ return false;
+ strncpy (alc, h->root.root.string, len - 1);
+ alc[len - 1] = '\0';
+ if (alc[len - 2] == ELF_VER_CHR)
+ alc[len - 2] = '\0';
+
h->verinfo.vertree = t;
t->used = true;
+ d = NULL;
+
+ if (t->globals != NULL)
+ {
+ for (d = t->globals; d != NULL; d = d->next)
+ {
+ if ((d->match[0] == '*' && d->match[1] == '\0')
+ || fnmatch (d->match, alc, 0) == 0)
+ break;
+ }
+ }
/* See if there is anything to force this symbol to
local scope. */
- if (t->locals != NULL)
+ if (d == NULL && t->locals != NULL)
{
- int len;
- char *alc;
- struct bfd_elf_version_expr *d;
-
- len = p - h->root.root.string;
- alc = bfd_alloc (sinfo->output_bfd, len);
- if (alc == NULL)
- return false;
- strncpy (alc, h->root.root.string, len - 1);
- alc[len - 1] = '\0';
- if (alc[len - 2] == ELF_VER_CHR)
- alc[len - 2] = '\0';
-
for (d = t->locals; d != NULL; d = d->next)
{
if ((d->match[0] == '*' && d->match[1] == '\0')
break;
}
}
-
- bfd_release (sinfo->output_bfd, alc);
}
+ bfd_release (sinfo->output_bfd, alc);
break;
}
}
/* We could not find the version for a symbol when
generating a shared archive. Return an error. */
(*_bfd_error_handler)
- ("%s: undefined version name %s",
+ (_("%s: undefined versioned symbol name %s"),
bfd_get_filename (sinfo->output_bfd), h->root.root.string);
bfd_set_error (bfd_error_bad_value);
sinfo->failed = true;
|| (elf_bad_symtab (input_bfd)
&& finfo->sections[r_symndx] == NULL))
{
+ struct elf_link_hash_entry *rh;
long indx;
/* This is a reloc against a global symbol. We
for this symbol. The symbol index is then
set at the end of elf_bfd_final_link. */
indx = r_symndx - extsymoff;
- *rel_hash = elf_sym_hashes (input_bfd)[indx];
+ rh = elf_sym_hashes (input_bfd)[indx];
+ while (rh->root.type == bfd_link_hash_indirect
+ || rh->root.type == bfd_link_hash_warning)
+ rh = (struct elf_link_hash_entry *) rh->root.u.i.link;
/* Setting the index to -2 tells
elf_link_output_extsym that this symbol is
used by a reloc. */
- BFD_ASSERT ((*rel_hash)->indx < 0);
- (*rel_hash)->indx = -2;
+ BFD_ASSERT (rh->indx < 0);
+ rh->indx = -2;
+
+ *rel_hash = rh;
continue;
}
/* Allocate a table to hold the local symbols if first time */
if (!ptr)
{
- int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
+ unsigned int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
register unsigned int i;
ptr = (elf_linker_section_pointers_t **)