+Wed Mar 12 21:36:05 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * elflink.h (elf_link_add_object_symbols): Use extsymoff when
+ setting ever. Sanity check the version number. Sort out copying
+ flags and other information when adding an indirect symbol.
+ (NAME(bfd_elf,size_dynamic_sections)): Preserve any dynamic
+ symbols added by the backend. Clear the entire contents of the
+ versym section.
+ (elf_export_symbol): Ignore indirect symbols.
+ (elf_link_output_extsym): Accept a section without an owner in an
+ assert.
+ * elfcode.h (elf_slurp_symbol_table): Add a sanity check on the
+ version count. Correct the allocation of x_versymp.
+
+ * elf32-mips.c (mips_elf_add_symbol_hook): Don't set the owner of
+ the magic sections used for SHN_MIPS_TEXT and SHN_MIPS_DATA.
+ Don't return bfd_und_section_ptr when info->shared.
+ (mips_elf_final_link): Set the alignment of .rtproc to 4, not 12.
+ (mips_elf_create_dynamic_sections): Correct type: ^= for &=.
+ (mips_elf_check_relocs): Resolve an indirect symbol in
+ sym_hashes.
+ (mips_elf_finish_dynamic_symbol): Don't change SHN_ABS into
+ SHN_MIPS_TEXT or SHN_MIPS_DATA.
+
+ * elf.c (bfd_elf_print_symbol): Tweak version output slightly.
+
+Tue Mar 11 01:38:36 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ From Eric Youngdale <eric@andante.jic.com>:
+ * elf-bfd.h (ELF_LINK_FORCED_LOCAL): Define.
+ * elf.c (bfd_elf_print_symbol): Correct errors in last change.
+ * elflink.h (elf_link_add_object_symbols): Handle cases in which a
+ versioned symbol appears in both a regular and a shared object.
+ (elf_link_assign_sym_version): Set ELF_LINK_FORCED_LOCAL when
+ appropriate. Improve error message.
+ (struct elf_outext_info): Rename from elf_finfo_failed. Change
+ all uses. Add localsyms field.
+ (elf_bfd_final_link): When generating a shared library, call
+ elf_link_output_extsym to output all local symbols.
+ (elf_link_output_extsym): Handle symbols which were forced to
+ become local.
+
Sun Mar 9 23:08:49 1997 Ian Lance Taylor <ian@cygnus.com>
From Eric Youngdale <eric@andante.jic.com>:
/* ELF executable support for BFD.
- Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Copyright 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
in "UNIX System V Release 4, Programmers Guide: ANSI C and
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
+#include "fnmatch.h"
/* Renaming structures, typedefs, macros and functions to be size-specific. */
#define Elf_External_Ehdr NAME(Elf,External_Ehdr)
struct elf_backend_data *ebd;
struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
struct elf_obj_tdata *new_tdata = NULL;
+ asection *s;
/* Read in the ELF header in external format. */
goto got_wrong_format_error;
}
+ /* If we have created any reloc sections that are associated with
+ debugging sections, mark the reloc sections as debugging as well. */
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((elf_section_data (s)->this_hdr.sh_type == SHT_REL
+ || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)
+ && elf_section_data (s)->this_hdr.sh_info > 0)
+ {
+ unsigned long targ_index;
+ asection *targ_sec;
+
+ targ_index = elf_section_data (s)->this_hdr.sh_info;
+ targ_sec = bfd_section_from_elf_index (abfd, targ_index);
+ if (targ_sec != NULL
+ && (targ_sec->flags & SEC_DEBUGGING) != 0)
+ s->flags |= SEC_DEBUGGING;
+ }
+ }
+
return (abfd->xvec);
got_wrong_format_error:
boolean dynamic;
{
Elf_Internal_Shdr *hdr;
+ Elf_Internal_Shdr *verhdr;
long symcount; /* Number of external ELF symbols */
elf_symbol_type *sym; /* Pointer to current bfd symbol */
elf_symbol_type *symbase; /* Buffer for generated bfd symbols */
Elf_Internal_Sym i_sym;
Elf_External_Sym *x_symp = NULL;
+ Elf_External_Versym *x_versymp = NULL;
/* Read each raw ELF symbol, converting from external ELF form to
internal ELF form, and then using the information to create a
space left over at the end. When we have all the symbols, we
build the caller's pointer vector. */
- if (dynamic)
- hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ if (! dynamic)
+ {
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ verhdr = NULL;
+ }
else
- hdr = &elf_tdata (abfd)->symtab_hdr;
+ {
+ hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ verhdr = &elf_tdata (abfd)->dynversym_hdr;
+ if ((elf_tdata (abfd)->dynverdef_section != 0
+ && elf_tdata (abfd)->verdef == NULL)
+ || (elf_tdata (abfd)->dynverref_section != 0
+ && elf_tdata (abfd)->verref == NULL))
+ {
+ if (! _bfd_elf_slurp_version_tables (abfd))
+ return -1;
+ }
+ }
+
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
return -1;
if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd)
!= symcount * sizeof (Elf_External_Sym))
goto error_return;
+
+ /* Read the raw ELF version symbol information. */
+
+ if (elf_dynversym (abfd) != 0
+ && verhdr != NULL
+ && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount)
+ {
+ (*_bfd_error_handler)
+ ("%s: version count (%ld) does not match symbol count (%ld)",
+ abfd->filename,
+ (long) (verhdr->sh_size / sizeof (Elf_External_Versym)),
+ symcount);
+
+ /* Slurp in the symbols without the version information,
+ since that is more helpful than just quitting. */
+ verhdr = NULL;
+ }
+
+ if (verhdr != NULL)
+ {
+ if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
+ goto error_return;
+
+ x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
+ if (x_versymp == NULL && symcount != 0)
+ goto error_return;
+
+ if (bfd_read ((PTR) x_versymp, 1, verhdr->sh_size, abfd)
+ != verhdr->sh_size)
+ goto error_return;
+ }
+
/* Skip first symbol, which is a null dummy. */
for (i = 1; i < symcount; i++)
{
if (dynamic)
sym->symbol.flags |= BSF_DYNAMIC;
+ if (x_versymp != NULL)
+ {
+ Elf_Internal_Versym iversym;
+
+ _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym);
+ sym->version = iversym.vs_vers;
+ }
+
/* Do some backend-specific processing on this symbol. */
{
struct elf_backend_data *ebd = get_elf_backend_data (abfd);
*symptrs = 0; /* Final null pointer */
}
+ if (x_versymp != NULL)
+ free (x_versymp);
if (x_symp != NULL)
free (x_symp);
return symcount;
error_return:
+ if (x_versymp != NULL)
+ free (x_versymp);
if (x_symp != NULL)
free (x_symp);
return -1;
weaks = NULL;
- ever = extversym != NULL ? extversym + hdr->sh_info : NULL;
+ ever = extversym != NULL ? extversym + extsymoff : NULL;
esymend = buf + extsymcount;
for (esym = buf;
esym < esymend;
int namelen, newlen;
char *newname, *p;
- if (vernum > 1)
+ if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
+ {
+ (*_bfd_error_handler)
+ ("%s: %s: invalid version %d (max %d)",
+ abfd->filename, name, vernum,
+ elf_tdata (abfd)->dynverdef_hdr.sh_info);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ else if (vernum > 1)
verstr = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
else
verstr = "";
if (hi->root.type == bfd_link_hash_indirect)
{
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
- if (dynamic)
- hi->elf_link_hash_flags |=
- ELF_LINK_HASH_DEF_DYNAMIC;
- /* We don't set DEF_REGULAR because we don't
- the symbol to get exported even if we are
- exporting all defined symbols. FIXME:
- What a hack. */
- /* FIXME: Do we need to copy any flags from
- H to HI? */
+
+ /* If the symbol became indirect, then we
+ assume that we have not seen a definition
+ before. */
+ BFD_ASSERT ((hi->elf_link_hash_flags
+ & (ELF_LINK_HASH_DEF_DYNAMIC
+ | ELF_LINK_HASH_DEF_REGULAR))
+ == 0);
+
+ /* Copy down any references that we may have
+ already seen to the symbol which just
+ became indirect. */
+ h->elf_link_hash_flags |=
+ (hi->elf_link_hash_flags
+ & (ELF_LINK_HASH_REF_DYNAMIC
+ | ELF_LINK_HASH_REF_REGULAR));
+
+ /* Copy over the global table offset entry.
+ This may have been already set up by a
+ check_relocs routine. */
+ if (h->got_offset == (bfd_vma) -1)
+ {
+ h->got_offset = hi->got_offset;
+ hi->got_offset = (bfd_vma) -1;
+ }
+ BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
+
+ if (h->dynindx == -1)
+ {
+ h->dynindx = hi->dynindx;
+ h->dynstr_index = hi->dynstr_index;
+ hi->dynindx = -1;
+ hi->dynstr_index = 0;
+ }
+ BFD_ASSERT (hi->dynindx == -1);
+
+ /* FIXME: There may be other information to
+ copy over for particular targets. */
+
+ /* See if the new flags lead us to realize
+ that the symbol must be dynamic. */
+ if (! dynsym)
+ {
+ if (! dynamic)
+ {
+ if (info->shared
+ || ((hi->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_DYNAMIC)
+ != 0))
+ dynsym = true;
+ }
+ else
+ {
+ if ((hi->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_REGULAR) != 0)
+ dynsym = true;
+ }
+ }
}
}
if (hi->root.type == bfd_link_hash_indirect)
{
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
- if (dynamic)
- hi->elf_link_hash_flags |=
- ELF_LINK_HASH_DEF_DYNAMIC;
- /* We don't set DEF_REGULAR because we don't
- the symbol to get exported even if we are
- exporting all defined symbols. FIXME:
- What a hack. */
- /* FIXME: Do we need to copy any flags from
- H to HI? */
+
+ /* If the symbol became indirect, then we
+ assume that we have not seen a definition
+ before. */
+ BFD_ASSERT ((hi->elf_link_hash_flags
+ & (ELF_LINK_HASH_DEF_DYNAMIC
+ | ELF_LINK_HASH_DEF_REGULAR))
+ == 0);
+
+ /* Copy down any references that we may have
+ already seen to the symbol which just
+ became indirect. */
+ h->elf_link_hash_flags |=
+ (hi->elf_link_hash_flags
+ & (ELF_LINK_HASH_REF_DYNAMIC
+ | ELF_LINK_HASH_REF_REGULAR));
+
+ /* Copy over the global table offset entry.
+ This may have been already set up by a
+ check_relocs routine. */
+ if (h->got_offset == (bfd_vma) -1)
+ {
+ h->got_offset = hi->got_offset;
+ hi->got_offset = (bfd_vma) -1;
+ }
+ BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
+
+ if (h->dynindx == -1)
+ {
+ h->dynindx = hi->dynindx;
+ h->dynstr_index = hi->dynstr_index;
+ hi->dynindx = -1;
+ hi->dynstr_index = 0;
+ }
+ BFD_ASSERT (hi->dynindx == -1);
+
+ /* FIXME: There may be other information to
+ copy over for particular targets. */
+
+ /* See if the new flags lead us to realize
+ that the symbol must be dynamic. */
+ if (! dynsym)
+ {
+ if (! dynamic)
+ {
+ if (info->shared
+ || ((hi->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_DYNAMIC)
+ != 0))
+ dynsym = true;
+ }
+ else
+ {
+ if ((hi->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_REGULAR) != 0)
+ dynsym = true;
+ }
+ }
}
}
}
bfd_size_type soname_indx;
bfd *dynobj;
struct elf_backend_data *bed;
+ bfd_size_type old_dynsymcount;
*sinterpptr = NULL;
/* The backend must work out the sizes of all the other dynamic
sections. */
+ old_dynsymcount = elf_hash_table (info)->dynsymcount;
if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
return false;
if (sinfo.removed_dynamic)
{
/* Some dynamic symbols were changed to be local
- symbols. In this case, we renumber all of the
- dynamic symbols, so that we don't have a hole.
- FIXME: The names of the removed symbols will still be
- in the dynamic string table, wasting space. */
- elf_hash_table (info)->dynsymcount = 1;
+ symbols. In this case, we renumber all of the
+ dynamic symbols, so that we don't have a hole. If
+ the backend changed dynsymcount, then assume that the
+ new symbols are at the start. This is the case on
+ the MIPS. FIXME: The names of the removed symbols
+ will still be in the dynamic string table, wasting
+ space. */
+ elf_hash_table (info)->dynsymcount =
+ 1 + (elf_hash_table (info)->dynsymcount - old_dynsymcount);
elf_link_hash_traverse (elf_hash_table (info),
elf_link_renumber_dynsyms,
(PTR) info);
}
else
{
- Elf_Internal_Versym intversym;
-
s->_raw_size = dynsymcount * sizeof (Elf_External_Versym);
- s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->_raw_size);
if (s->contents == NULL)
return false;
- intversym.vs_vers = 0;
- _bfd_elf_swap_versym_out (output_bfd, &intversym,
- (Elf_External_Versym *) s->contents);
-
if (! elf_add_dynamic_entry (info, DT_VERSYM, 0))
return false;
}
bfd *dynobj;
struct elf_backend_data *bed;
- /* Ignore indirect symbols. There are added by the versioning code. */
+ /* Ignore indirect symbols. These are added by the versioning code. */
if (h->root.type == bfd_link_hash_indirect)
return true;
{
struct elf_info_failed *eif = (struct elf_info_failed *) data;
+ /* Ignore indirect symbols. These are added by the versioning code. */
+ if (h->root.type == bfd_link_hash_indirect)
+ return true;
+
if (h->dynindx == -1
&& (h->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0)
}
else
{
- BFD_ASSERT ((input_sec->owner->flags & DYNAMIC) != 0);
+ BFD_ASSERT (input_sec->owner == NULL
+ || (input_sec->owner->flags & DYNAMIC) != 0);
sym.st_shndx = SHN_UNDEF;
input_sec = bfd_und_section_ptr;
}