summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/bfd/elfcode.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/bfd/elfcode.h')
-rw-r--r--contrib/binutils/bfd/elfcode.h211
1 files changed, 96 insertions, 115 deletions
diff --git a/contrib/binutils/bfd/elfcode.h b/contrib/binutils/bfd/elfcode.h
index 203323c..4f54cd3 100644
--- a/contrib/binutils/bfd/elfcode.h
+++ b/contrib/binutils/bfd/elfcode.h
@@ -1,6 +1,6 @@
/* ELF executable support for BFD.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001 Free Software Foundation, Inc.
+ 2001, 2002 Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
in "UNIX System V Release 4, Programmers Guide: ANSI C and
@@ -203,12 +203,14 @@ static char *elf_symbol_flags PARAMS ((flagword));
format. */
void
-elf_swap_symbol_in (abfd, src, shndx, dst)
+elf_swap_symbol_in (abfd, psrc, pshn, dst)
bfd *abfd;
- const Elf_External_Sym *src;
- const Elf_External_Sym_Shndx *shndx;
+ const PTR psrc;
+ const PTR pshn;
Elf_Internal_Sym *dst;
{
+ const Elf_External_Sym *src = (const Elf_External_Sym *) psrc;
+ const Elf_External_Sym_Shndx *shndx = (const Elf_External_Sym_Shndx *) pshn;
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
dst->st_name = H_GET_32 (abfd, src->st_name);
@@ -557,9 +559,9 @@ elf_object_p (abfd)
section header table (FIXME: See comments re sections at top of this
file). */
- if ((elf_file_p (&x_ehdr) == false) ||
- (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) ||
- (x_ehdr.e_ident[EI_CLASS] != ELFCLASS))
+ if (! elf_file_p (&x_ehdr)
+ || x_ehdr.e_ident[EI_VERSION] != EV_CURRENT
+ || x_ehdr.e_ident[EI_CLASS] != ELFCLASS)
goto got_wrong_format_error;
/* Check that file's byte order matches xvec's */
@@ -622,6 +624,10 @@ elf_object_p (abfd)
if (i_ehdrp->e_shentsize != sizeof (x_shdr) && i_ehdrp->e_shnum != 0)
goto got_wrong_format_error;
+ /* Further sanity check. */
+ if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0)
+ goto got_wrong_format_error;
+
ebd = get_elf_backend_data (abfd);
/* Check that the ELF e_machine field matches what this particular
@@ -675,25 +681,28 @@ elf_object_p (abfd)
/* Remember the entry point specified in the ELF file header. */
bfd_set_start_address (abfd, i_ehdrp->e_entry);
- /* Seek to the section header table in the file. */
- if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0)
- goto got_no_match;
+ if (i_ehdrp->e_shoff != 0)
+ {
+ /* Seek to the section header table in the file. */
+ if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0)
+ goto got_no_match;
- /* Read the first section header at index 0, and convert to internal
- form. */
- if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd)
- != sizeof (x_shdr))
- goto got_no_match;
- elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
+ /* Read the first section header at index 0, and convert to internal
+ form. */
+ if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd)
+ != sizeof (x_shdr))
+ goto got_no_match;
+ elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
- /* If the section count is zero, the actual count is in the first
- section header. */
- if (i_ehdrp->e_shnum == SHN_UNDEF)
- i_ehdrp->e_shnum = i_shdr.sh_size;
+ /* If the section count is zero, the actual count is in the first
+ section header. */
+ if (i_ehdrp->e_shnum == SHN_UNDEF)
+ i_ehdrp->e_shnum = i_shdr.sh_size;
- /* And similarly for the string table index. */
- if (i_ehdrp->e_shstrndx == SHN_XINDEX)
- i_ehdrp->e_shstrndx = i_shdr.sh_link;
+ /* And similarly for the string table index. */
+ if (i_ehdrp->e_shstrndx == SHN_XINDEX)
+ i_ehdrp->e_shstrndx = i_shdr.sh_link;
+ }
/* Allocate space for a copy of the section header table in
internal form. */
@@ -749,7 +758,7 @@ elf_object_p (abfd)
}
}
- if (i_ehdrp->e_shstrndx)
+ if (i_ehdrp->e_shstrndx && i_ehdrp->e_shoff)
{
if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx))
goto got_no_match;
@@ -787,7 +796,7 @@ elf_object_p (abfd)
bfd_section_from_shdr with it (since this particular strtab is
used to find all of the ELF section names.) */
- if (i_ehdrp->e_shstrndx != 0)
+ if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff)
{
unsigned int num_sec;
@@ -812,7 +821,7 @@ elf_object_p (abfd)
information. */
if (ebd->elf_backend_object_p)
{
- if ((*ebd->elf_backend_object_p) (abfd) == false)
+ if (! (*ebd->elf_backend_object_p) (abfd))
goto got_wrong_format_error;
}
@@ -1124,10 +1133,12 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
unsigned 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_Sym_Shndx *x_shndx = NULL;
- Elf_External_Versym *x_versymp = NULL;
+ Elf_Internal_Sym *isym;
+ Elf_Internal_Sym *isymend;
+ Elf_Internal_Sym *isymbuf = NULL;
+ Elf_External_Versym *xver;
+ Elf_External_Versym *xverbuf = NULL;
+ struct elf_backend_data *ebd;
bfd_size_type amt;
/* Read each raw ELF symbol, converting from external ELF form to
@@ -1142,24 +1153,8 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
if (! dynamic)
{
- Elf_Internal_Shdr *shndx_hdr;
-
hdr = &elf_tdata (abfd)->symtab_hdr;
- shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
verhdr = NULL;
-
- /* If we have a SHT_SYMTAB_SHNDX section for the symbol table,
- read the raw contents. */
- if (elf_elfsections (abfd) != NULL
- && elf_elfsections (abfd)[shndx_hdr->sh_link] == hdr)
- {
- amt = shndx_hdr->sh_size;
- x_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
- if (x_shndx == NULL
- || bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread ((PTR) x_shndx, amt, abfd) != amt)
- goto error_return;
- }
}
else
{
@@ -1178,39 +1173,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
}
}
- if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
- goto error_return;
-
+ ebd = get_elf_backend_data (abfd);
symcount = hdr->sh_size / sizeof (Elf_External_Sym);
-
if (symcount == 0)
sym = symbase = NULL;
else
{
- unsigned long i;
-
- if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
- goto error_return;
+ isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0,
+ NULL, NULL, NULL);
+ if (isymbuf == NULL)
+ return -1;
amt = symcount;
amt *= sizeof (elf_symbol_type);
symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
if (symbase == (elf_symbol_type *) NULL)
goto error_return;
- sym = symbase;
-
- /* Temporarily allocate room for the raw ELF symbols. */
- amt = symcount;
- amt *= sizeof (Elf_External_Sym);
- x_symp = (Elf_External_Sym *) bfd_malloc (amt);
- if (x_symp == NULL)
- goto error_return;
-
- if (bfd_bread ((PTR) x_symp, amt, abfd) != amt)
- goto error_return;
/* Read the raw ELF version symbol information. */
-
if (verhdr != NULL
&& verhdr->sh_size / sizeof (Elf_External_Versym) != symcount)
{
@@ -1230,41 +1210,40 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
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)
+ xverbuf = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
+ if (xverbuf == NULL && verhdr->sh_size != 0)
goto error_return;
- if (bfd_bread ((PTR) x_versymp, verhdr->sh_size, abfd)
+ if (bfd_bread ((PTR) xverbuf, verhdr->sh_size, abfd)
!= verhdr->sh_size)
goto error_return;
}
/* Skip first symbol, which is a null dummy. */
- for (i = 1; i < symcount; i++)
+ xver = xverbuf;
+ if (xver != NULL)
+ ++xver;
+ isymend = isymbuf + symcount;
+ for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++)
{
- elf_swap_symbol_in (abfd, x_symp + i,
- x_shndx + (x_shndx != NULL ? i : 0), &i_sym);
- memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym));
-#ifdef ELF_KEEP_EXTSYM
- memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym));
-#endif
+ memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym));
sym->symbol.the_bfd = abfd;
sym->symbol.name = bfd_elf_string_from_elf_section (abfd,
hdr->sh_link,
- i_sym.st_name);
+ isym->st_name);
- sym->symbol.value = i_sym.st_value;
+ sym->symbol.value = isym->st_value;
- if (i_sym.st_shndx == SHN_UNDEF)
+ if (isym->st_shndx == SHN_UNDEF)
{
sym->symbol.section = bfd_und_section_ptr;
}
- else if (i_sym.st_shndx < SHN_LORESERVE
- || i_sym.st_shndx > SHN_HIRESERVE)
+ else if (isym->st_shndx < SHN_LORESERVE
+ || isym->st_shndx > SHN_HIRESERVE)
{
sym->symbol.section = section_from_elf_index (abfd,
- i_sym.st_shndx);
+ isym->st_shndx);
if (sym->symbol.section == NULL)
{
/* This symbol is in a section for which we did not
@@ -1273,18 +1252,18 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
sym->symbol.section = bfd_abs_section_ptr;
}
}
- else if (i_sym.st_shndx == SHN_ABS)
+ else if (isym->st_shndx == SHN_ABS)
{
sym->symbol.section = bfd_abs_section_ptr;
}
- else if (i_sym.st_shndx == SHN_COMMON)
+ else if (isym->st_shndx == SHN_COMMON)
{
sym->symbol.section = bfd_com_section_ptr;
/* Elf puts the alignment into the `value' field, and
the size into the `size' field. BFD wants to see the
size in the value field, and doesn't care (at the
moment) about the alignment. */
- sym->symbol.value = i_sym.st_size;
+ sym->symbol.value = isym->st_size;
}
else
sym->symbol.section = bfd_abs_section_ptr;
@@ -1294,14 +1273,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
sym->symbol.value -= sym->symbol.section->vma;
- switch (ELF_ST_BIND (i_sym.st_info))
+ switch (ELF_ST_BIND (isym->st_info))
{
case STB_LOCAL:
sym->symbol.flags |= BSF_LOCAL;
break;
case STB_GLOBAL:
- if (i_sym.st_shndx != SHN_UNDEF
- && i_sym.st_shndx != SHN_COMMON)
+ if (isym->st_shndx != SHN_UNDEF && isym->st_shndx != SHN_COMMON)
sym->symbol.flags |= BSF_GLOBAL;
break;
case STB_WEAK:
@@ -1309,7 +1287,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
break;
}
- switch (ELF_ST_TYPE (i_sym.st_info))
+ switch (ELF_ST_TYPE (isym->st_info))
{
case STT_SECTION:
sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING;
@@ -1328,31 +1306,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
if (dynamic)
sym->symbol.flags |= BSF_DYNAMIC;
- if (x_versymp != NULL)
+ if (xver != NULL)
{
Elf_Internal_Versym iversym;
- _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym);
+ _bfd_elf_swap_versym_in (abfd, xver, &iversym);
sym->version = iversym.vs_vers;
+ xver++;
}
/* Do some backend-specific processing on this symbol. */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- if (ebd->elf_backend_symbol_processing)
- (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
- }
-
- sym++;
+ if (ebd->elf_backend_symbol_processing)
+ (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
}
}
/* Do some backend-specific processing on this symbol table. */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- if (ebd->elf_backend_symbol_table_processing)
- (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
- }
+ if (ebd->elf_backend_symbol_table_processing)
+ (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
/* We rely on the zalloc to clear out the final symbol entry. */
@@ -1372,21 +1343,17 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
*symptrs = 0; /* Final null pointer */
}
- if (x_shndx != NULL)
- free (x_shndx);
- if (x_versymp != NULL)
- free (x_versymp);
- if (x_symp != NULL)
- free (x_symp);
+ if (xverbuf != NULL)
+ free (xverbuf);
+ if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf)
+ free (isymbuf);
return symcount;
error_return:
- if (x_shndx != NULL)
- free (x_shndx);
- if (x_versymp != NULL)
- free (x_versymp);
- if (x_symp != NULL)
- free (x_symp);
+ if (xverbuf != NULL)
+ free (xverbuf);
+ if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf)
+ free (isymbuf);
return -1;
}
@@ -1410,6 +1377,7 @@ elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count,
arelent *relent;
unsigned int i;
int entsize;
+ unsigned int symcount;
allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
if (allocated == NULL)
@@ -1426,6 +1394,11 @@ elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count,
BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
|| entsize == sizeof (Elf_External_Rela));
+ if (dynamic)
+ symcount = bfd_get_dynamic_symcount (abfd);
+ else
+ symcount = bfd_get_symcount (abfd);
+
for (i = 0, relent = relents;
i < reloc_count;
i++, relent++, native_relocs += entsize)
@@ -1454,6 +1427,13 @@ elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count,
if (ELF_R_SYM (rela.r_info) == 0)
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ else if (ELF_R_SYM (rela.r_info) > symcount)
+ {
+ (*_bfd_error_handler)
+ (_("%s(%s): relocation %d has invalid symbol index %ld"),
+ abfd->filename, asect->name, i, ELF_R_SYM (rela.r_info));
+ relent->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ }
else
{
asymbol **ps, *s;
@@ -1695,6 +1675,7 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = {
elf_write_out_phdrs,
elf_write_shdrs_and_ehdr,
elf_write_relocs,
+ elf_swap_symbol_in,
elf_swap_symbol_out,
elf_slurp_reloc_table,
elf_slurp_symbol_table,
OpenPOWER on IntegriCloud