/* 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;
+ if (elf_dynversym (abfd) == 0)
+ verhdr = NULL;
+ else
+ 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 (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 && verhdr->sh_size != 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;