blob: cb4de50ac9ae6723488cbdfbc4343b33d7c96727 [file] [log] [blame]
/* ELF executable support for BFD.
Copyright (C) 1993-2016 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
SECTION
ELF backends
BFD support for ELF formats is being worked on.
Currently, the best supported back ends are for sparc and i386
(running svr4 or Solaris 2).
Documentation of the internals of the support code still needs
to be written. The code is changing quickly enough that we
haven't bothered yet. */
/* For sparc64-cross-sparc32. */
#define _SYSCALL32
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#define ARCH_SIZE 0
#include "elf-bfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "elf-linux-core.h"
#ifdef CORE_HEADER
#include CORE_HEADER
#endif
static int elf_sort_sections (const void *, const void *);
static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
static bfd_boolean prep_headers (bfd *);
static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ;
static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
file_ptr offset);
/* Swap version information in and out. The version information is
currently size independent. If that ever changes, this code will
need to move into elfcode.h. */
/* Swap in a Verdef structure. */
void
_bfd_elf_swap_verdef_in (bfd *abfd,
const Elf_External_Verdef *src,
Elf_Internal_Verdef *dst)
{
dst->vd_version = H_GET_16 (abfd, src->vd_version);
dst->vd_flags = H_GET_16 (abfd, src->vd_flags);
dst->vd_ndx = H_GET_16 (abfd, src->vd_ndx);
dst->vd_cnt = H_GET_16 (abfd, src->vd_cnt);
dst->vd_hash = H_GET_32 (abfd, src->vd_hash);
dst->vd_aux = H_GET_32 (abfd, src->vd_aux);
dst->vd_next = H_GET_32 (abfd, src->vd_next);
}
/* Swap out a Verdef structure. */
void
_bfd_elf_swap_verdef_out (bfd *abfd,
const Elf_Internal_Verdef *src,
Elf_External_Verdef *dst)
{
H_PUT_16 (abfd, src->vd_version, dst->vd_version);
H_PUT_16 (abfd, src->vd_flags, dst->vd_flags);
H_PUT_16 (abfd, src->vd_ndx, dst->vd_ndx);
H_PUT_16 (abfd, src->vd_cnt, dst->vd_cnt);
H_PUT_32 (abfd, src->vd_hash, dst->vd_hash);
H_PUT_32 (abfd, src->vd_aux, dst->vd_aux);
H_PUT_32 (abfd, src->vd_next, dst->vd_next);
}
/* Swap in a Verdaux structure. */
void
_bfd_elf_swap_verdaux_in (bfd *abfd,
const Elf_External_Verdaux *src,
Elf_Internal_Verdaux *dst)
{
dst->vda_name = H_GET_32 (abfd, src->vda_name);
dst->vda_next = H_GET_32 (abfd, src->vda_next);
}
/* Swap out a Verdaux structure. */
void
_bfd_elf_swap_verdaux_out (bfd *abfd,
const Elf_Internal_Verdaux *src,
Elf_External_Verdaux *dst)
{
H_PUT_32 (abfd, src->vda_name, dst->vda_name);
H_PUT_32 (abfd, src->vda_next, dst->vda_next);
}
/* Swap in a Verneed structure. */
void
_bfd_elf_swap_verneed_in (bfd *abfd,
const Elf_External_Verneed *src,
Elf_Internal_Verneed *dst)
{
dst->vn_version = H_GET_16 (abfd, src->vn_version);
dst->vn_cnt = H_GET_16 (abfd, src->vn_cnt);
dst->vn_file = H_GET_32 (abfd, src->vn_file);
dst->vn_aux = H_GET_32 (abfd, src->vn_aux);
dst->vn_next = H_GET_32 (abfd, src->vn_next);
}
/* Swap out a Verneed structure. */
void
_bfd_elf_swap_verneed_out (bfd *abfd,
const Elf_Internal_Verneed *src,
Elf_External_Verneed *dst)
{
H_PUT_16 (abfd, src->vn_version, dst->vn_version);
H_PUT_16 (abfd, src->vn_cnt, dst->vn_cnt);
H_PUT_32 (abfd, src->vn_file, dst->vn_file);
H_PUT_32 (abfd, src->vn_aux, dst->vn_aux);
H_PUT_32 (abfd, src->vn_next, dst->vn_next);
}
/* Swap in a Vernaux structure. */
void
_bfd_elf_swap_vernaux_in (bfd *abfd,
const Elf_External_Vernaux *src,
Elf_Internal_Vernaux *dst)
{
dst->vna_hash = H_GET_32 (abfd, src->vna_hash);
dst->vna_flags = H_GET_16 (abfd, src->vna_flags);
dst->vna_other = H_GET_16 (abfd, src->vna_other);
dst->vna_name = H_GET_32 (abfd, src->vna_name);
dst->vna_next = H_GET_32 (abfd, src->vna_next);
}
/* Swap out a Vernaux structure. */
void
_bfd_elf_swap_vernaux_out (bfd *abfd,
const Elf_Internal_Vernaux *src,
Elf_External_Vernaux *dst)
{
H_PUT_32 (abfd, src->vna_hash, dst->vna_hash);
H_PUT_16 (abfd, src->vna_flags, dst->vna_flags);
H_PUT_16 (abfd, src->vna_other, dst->vna_other);
H_PUT_32 (abfd, src->vna_name, dst->vna_name);
H_PUT_32 (abfd, src->vna_next, dst->vna_next);
}
/* Swap in a Versym structure. */
void
_bfd_elf_swap_versym_in (bfd *abfd,
const Elf_External_Versym *src,
Elf_Internal_Versym *dst)
{
dst->vs_vers = H_GET_16 (abfd, src->vs_vers);
}
/* Swap out a Versym structure. */
void
_bfd_elf_swap_versym_out (bfd *abfd,
const Elf_Internal_Versym *src,
Elf_External_Versym *dst)
{
H_PUT_16 (abfd, src->vs_vers, dst->vs_vers);
}
/* Standard ELF hash function. Do not change this function; you will
cause invalid hash tables to be generated. */
unsigned long
bfd_elf_hash (const char *namearg)
{
const unsigned char *name = (const unsigned char *) namearg;
unsigned long h = 0;
unsigned long g;
int ch;
while ((ch = *name++) != '\0')
{
h = (h << 4) + ch;
if ((g = (h & 0xf0000000)) != 0)
{
h ^= g >> 24;
/* The ELF ABI says `h &= ~g', but this is equivalent in
this case and on some machines one insn instead of two. */
h ^= g;
}
}
return h & 0xffffffff;
}
/* DT_GNU_HASH hash function. Do not change this function; you will
cause invalid hash tables to be generated. */
unsigned long
bfd_elf_gnu_hash (const char *namearg)
{
const unsigned char *name = (const unsigned char *) namearg;
unsigned long h = 5381;
unsigned char ch;
while ((ch = *name++) != '\0')
h = (h << 5) + h + ch;
return h & 0xffffffff;
}
/* Create a tdata field OBJECT_SIZE bytes in length, zeroed out and with
the object_id field of an elf_obj_tdata field set to OBJECT_ID. */
bfd_boolean
bfd_elf_allocate_object (bfd *abfd,
size_t object_size,
enum elf_target_id object_id)
{
BFD_ASSERT (object_size >= sizeof (struct elf_obj_tdata));
abfd->tdata.any = bfd_zalloc (abfd, object_size);
if (abfd->tdata.any == NULL)
return FALSE;
elf_object_id (abfd) = object_id;
if (abfd->direction != read_direction)
{
struct output_elf_obj_tdata *o = bfd_zalloc (abfd, sizeof *o);
if (o == NULL)
return FALSE;
elf_tdata (abfd)->o = o;
elf_program_header_size (abfd) = (bfd_size_type) -1;
}
return TRUE;
}
bfd_boolean
bfd_elf_make_object (bfd *abfd)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
bed->target_id);
}
bfd_boolean
bfd_elf_mkcorefile (bfd *abfd)
{
/* I think this can be done just like an object file. */
if (!abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd))
return FALSE;
elf_tdata (abfd)->core = bfd_zalloc (abfd, sizeof (*elf_tdata (abfd)->core));
return elf_tdata (abfd)->core != NULL;
}
static char *
bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
{
Elf_Internal_Shdr **i_shdrp;
bfd_byte *shstrtab = NULL;
file_ptr offset;
bfd_size_type shstrtabsize;
i_shdrp = elf_elfsections (abfd);
if (i_shdrp == 0
|| shindex >= elf_numsections (abfd)
|| i_shdrp[shindex] == 0)
return NULL;
shstrtab = i_shdrp[shindex]->contents;
if (shstrtab == NULL)
{
/* No cached one, attempt to read, and cache what we read. */
offset = i_shdrp[shindex]->sh_offset;
shstrtabsize = i_shdrp[shindex]->sh_size;
/* Allocate and clear an extra byte at the end, to prevent crashes
in case the string table is not terminated. */
if (shstrtabsize + 1 <= 1
|| bfd_seek (abfd, offset, SEEK_SET) != 0
|| (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
shstrtab = NULL;
else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_file_truncated);
bfd_release (abfd, shstrtab);
shstrtab = NULL;
/* Once we've failed to read it, make sure we don't keep
trying. Otherwise, we'll keep allocating space for
the string table over and over. */
i_shdrp[shindex]->sh_size = 0;
}
else
shstrtab[shstrtabsize] = '\0';
i_shdrp[shindex]->contents = shstrtab;
}
return (char *) shstrtab;
}
char *
bfd_elf_string_from_elf_section (bfd *abfd,
unsigned int shindex,
unsigned int strindex)
{
Elf_Internal_Shdr *hdr;
if (strindex == 0)
return "";
if (elf_elfsections (abfd) == NULL || shindex >= elf_numsections (abfd))
return NULL;
hdr = elf_elfsections (abfd)[shindex];
if (hdr->contents == NULL)
{
if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
{
/* PR 17512: file: f057ec89. */
_bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
abfd, shindex);
return NULL;
}
if (bfd_elf_get_str_section (abfd, shindex) == NULL)
return NULL;
}
if (strindex >= hdr->sh_size)
{
unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx;
(*_bfd_error_handler)
(_("%B: invalid string offset %u >= %lu for section `%s'"),
abfd, strindex, (unsigned long) hdr->sh_size,
(shindex == shstrndx && strindex == hdr->sh_name
? ".shstrtab"
: bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
return NULL;
}
return ((char *) hdr->contents) + strindex;
}
/* Read and convert symbols to internal format.
SYMCOUNT specifies the number of symbols to read, starting from
symbol SYMOFFSET. If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF
are non-NULL, they are used to store the internal symbols, external
symbols, and symbol section index extensions, respectively.
Returns a pointer to the internal symbol buffer (malloced if necessary)
or NULL if there were no symbols or some kind of problem. */
Elf_Internal_Sym *
bfd_elf_get_elf_syms (bfd *ibfd,
Elf_Internal_Shdr *symtab_hdr,
size_t symcount,
size_t symoffset,
Elf_Internal_Sym *intsym_buf,
void *extsym_buf,
Elf_External_Sym_Shndx *extshndx_buf)
{
Elf_Internal_Shdr *shndx_hdr;
void *alloc_ext;
const bfd_byte *esym;
Elf_External_Sym_Shndx *alloc_extshndx;
Elf_External_Sym_Shndx *shndx;
Elf_Internal_Sym *alloc_intsym;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
const struct elf_backend_data *bed;
size_t extsym_size;
bfd_size_type amt;
file_ptr pos;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
abort ();
if (symcount == 0)
return intsym_buf;
/* Normal syms might have section extension entries. */
shndx_hdr = NULL;
if (elf_symtab_shndx_list (ibfd) != NULL)
{
elf_section_list * entry;
Elf_Internal_Shdr **sections = elf_elfsections (ibfd);
/* Find an index section that is linked to this symtab section. */
for (entry = elf_symtab_shndx_list (ibfd); entry != NULL; entry = entry->next)
{
/* PR 20063. */
if (entry->hdr.sh_link >= elf_numsections (ibfd))
continue;
if (sections[entry->hdr.sh_link] == symtab_hdr)
{
shndx_hdr = & entry->hdr;
break;
};
}
if (shndx_hdr == NULL)
{
if (symtab_hdr == & elf_symtab_hdr (ibfd))
/* Not really accurate, but this was how the old code used to work. */
shndx_hdr = & elf_symtab_shndx_list (ibfd)->hdr;
/* Otherwise we do nothing. The assumption is that
the index table will not be needed. */
}
}
/* Read the symbols. */
alloc_ext = NULL;
alloc_extshndx = NULL;
alloc_intsym = NULL;
bed = get_elf_backend_data (ibfd);
extsym_size = bed->s->sizeof_sym;
amt = (bfd_size_type) symcount * extsym_size;
pos = symtab_hdr->sh_offset + symoffset * extsym_size;
if (extsym_buf == NULL)
{
alloc_ext = bfd_malloc2 (symcount, extsym_size);
extsym_buf = alloc_ext;
}
if (extsym_buf == NULL
|| bfd_seek (ibfd, pos, SEEK_SET) != 0
|| bfd_bread (extsym_buf, amt, ibfd) != amt)
{
intsym_buf = NULL;
goto out;
}
if (shndx_hdr == NULL || shndx_hdr->sh_size == 0)
extshndx_buf = NULL;
else
{
amt = (bfd_size_type) symcount * sizeof (Elf_External_Sym_Shndx);
pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
if (extshndx_buf == NULL)
{
alloc_extshndx = (Elf_External_Sym_Shndx *)
bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx));
extshndx_buf = alloc_extshndx;
}
if (extshndx_buf == NULL
|| bfd_seek (ibfd, pos, SEEK_SET) != 0
|| bfd_bread (extshndx_buf, amt, ibfd) != amt)
{
intsym_buf = NULL;
goto out;
}
}
if (intsym_buf == NULL)
{
alloc_intsym = (Elf_Internal_Sym *)
bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
intsym_buf = alloc_intsym;
if (intsym_buf == NULL)
goto out;
}
/* Convert the symbols to internal form. */
isymend = intsym_buf + symcount;
for (esym = (const bfd_byte *) extsym_buf, isym = intsym_buf,
shndx = extshndx_buf;
isym < isymend;
esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
{
symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
(*_bfd_error_handler) (_("%B symbol number %lu references "
"nonexistent SHT_SYMTAB_SHNDX section"),
ibfd, (unsigned long) symoffset);
if (alloc_intsym != NULL)
free (alloc_intsym);
intsym_buf = NULL;
goto out;
}
out:
if (alloc_ext != NULL)
free (alloc_ext);
if (alloc_extshndx != NULL)
free (alloc_extshndx);
return intsym_buf;
}
/* Look up a symbol name. */
const char *
bfd_elf_sym_name (bfd *abfd,
Elf_Internal_Shdr *symtab_hdr,
Elf_Internal_Sym *isym,
asection *sym_sec)
{
const char *name;
unsigned int iname = isym->st_name;
unsigned int shindex = symtab_hdr->sh_link;
if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION
/* Check for a bogus st_shndx to avoid crashing. */
&& isym->st_shndx < elf_numsections (abfd))
{
iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
shindex = elf_elfheader (abfd)->e_shstrndx;
}
name = bfd_elf_string_from_elf_section (abfd, shindex, iname);
if (name == NULL)
name = "(null)";
else if (sym_sec && *name == '\0')
name = bfd_section_name (abfd, sym_sec);
return name;
}
/* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
sections. The first element is the flags, the rest are section
pointers. */
typedef union elf_internal_group {
Elf_Internal_Shdr *shdr;
unsigned int flags;
} Elf_Internal_Group;
/* Return the name of the group signature symbol. Why isn't the
signature just a string? */
static const char *
group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
{
Elf_Internal_Shdr *hdr;
unsigned char esym[sizeof (Elf64_External_Sym)];
Elf_External_Sym_Shndx eshndx;
Elf_Internal_Sym isym;
/* First we need to ensure the symbol table is available. Make sure
that it is a symbol table section. */
if (ghdr->sh_link >= elf_numsections (abfd))
return NULL;
hdr = elf_elfsections (abfd) [ghdr->sh_link];
if (hdr->sh_type != SHT_SYMTAB
|| ! bfd_section_from_shdr (abfd, ghdr->sh_link))
return NULL;
/* Go read the symbol. */
hdr = &elf_tdata (abfd)->symtab_hdr;
if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info,
&isym, esym, &eshndx) == NULL)
return NULL;
return bfd_elf_sym_name (abfd, hdr, &isym, NULL);
}
/* Set next_in_group list pointer, and group name for NEWSECT. */
static bfd_boolean
setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
{
unsigned int num_group = elf_tdata (abfd)->num_group;
/* If num_group is zero, read in all SHT_GROUP sections. The count
is set to -1 if there are no SHT_GROUP sections. */
if (num_group == 0)
{
unsigned int i, shnum;
/* First count the number of groups. If we have a SHT_GROUP
section with just a flag word (ie. sh_size is 4), ignore it. */
shnum = elf_numsections (abfd);
num_group = 0;
#define IS_VALID_GROUP_SECTION_HEADER(shdr, minsize) \
( (shdr)->sh_type == SHT_GROUP \
&& (shdr)->sh_size >= minsize \
&& (shdr)->sh_entsize == GRP_ENTRY_SIZE \
&& ((shdr)->sh_size % GRP_ENTRY_SIZE) == 0)
for (i = 0; i < shnum; i++)
{
Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE))
num_group += 1;
}
if (num_group == 0)
{
num_group = (unsigned) -1;
elf_tdata (abfd)->num_group = num_group;
}
else
{
/* We keep a list of elf section headers for group sections,
so we can find them quickly. */
bfd_size_type amt;
elf_tdata (abfd)->num_group = num_group;
elf_tdata (abfd)->group_sect_ptr = (Elf_Internal_Shdr **)
bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
if (elf_tdata (abfd)->group_sect_ptr == NULL)
return FALSE;
num_group = 0;
for (i = 0; i < shnum; i++)
{
Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE))
{
unsigned char *src;
Elf_Internal_Group *dest;
/* Add to list of sections. */
elf_tdata (abfd)->group_sect_ptr[num_group] = shdr;
num_group += 1;
/* Read the raw contents. */
BFD_ASSERT (sizeof (*dest) >= 4);
amt = shdr->sh_size * sizeof (*dest) / 4;
shdr->contents = (unsigned char *)
bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
/* PR binutils/4110: Handle corrupt group headers. */
if (shdr->contents == NULL)
{
_bfd_error_handler
(_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
continue;
}
memset (shdr->contents, 0, amt);
if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
|| (bfd_bread (shdr->contents, shdr->sh_size, abfd)
!= shdr->sh_size))
{
_bfd_error_handler
(_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
/* PR 17510: If the group contents are even partially
corrupt, do not allow any of the contents to be used. */
memset (shdr->contents, 0, amt);
continue;
}
/* Translate raw contents, a flag word followed by an
array of elf section indices all in target byte order,
to the flag word followed by an array of elf section
pointers. */
src = shdr->contents + shdr->sh_size;
dest = (Elf_Internal_Group *) (shdr->contents + amt);
while (1)
{
unsigned int idx;
src -= 4;
--dest;
idx = H_GET_32 (abfd, src);
if (src == shdr->contents)
{
dest->flags = idx;
if (shdr->bfd_section != NULL && (idx & GRP_COMDAT))
shdr->bfd_section->flags
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
break;
}
if (idx >= shnum)
{
((*_bfd_error_handler)
(_("%B: invalid SHT_GROUP entry"), abfd));
idx = 0;
}
dest->shdr = elf_elfsections (abfd)[idx];
}
}
}
/* PR 17510: Corrupt binaries might contain invalid groups. */
if (num_group != (unsigned) elf_tdata (abfd)->num_group)
{
elf_tdata (abfd)->num_group = num_group;
/* If all groups are invalid then fail. */
if (num_group == 0)
{
elf_tdata (abfd)->group_sect_ptr = NULL;
elf_tdata (abfd)->num_group = num_group = -1;
(*_bfd_error_handler) (_("%B: no valid group sections found"), abfd);
bfd_set_error (bfd_error_bad_value);
}
}
}
}
if (num_group != (unsigned) -1)
{
unsigned int i;
for (i = 0; i < num_group; i++)
{
Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
unsigned int n_elt = shdr->sh_size / 4;
/* Look through this group's sections to see if current
section is a member. */
while (--n_elt != 0)
if ((++idx)->shdr == hdr)
{
asection *s = NULL;
/* We are a member of this group. Go looking through
other members to see if any others are linked via
next_in_group. */
idx = (Elf_Internal_Group *) shdr->contents;
n_elt = shdr->sh_size / 4;
while (--n_elt != 0)
if ((s = (++idx)->shdr->bfd_section) != NULL
&& elf_next_in_group (s) != NULL)
break;
if (n_elt != 0)
{
/* Snarf the group name from other member, and
insert current section in circular list. */
elf_group_name (newsect) = elf_group_name (s);
elf_next_in_group (newsect) = elf_next_in_group (s);
elf_next_in_group (s) = newsect;
}
else
{
const char *gname;
gname = group_signature (abfd, shdr);
if (gname == NULL)
return FALSE;
elf_group_name (newsect) = gname;
/* Start a circular list with one element. */
elf_next_in_group (newsect) = newsect;
}
/* If the group section has been created, point to the
new member. */
if (shdr->bfd_section != NULL)
elf_next_in_group (shdr->bfd_section) = newsect;
i = num_group - 1;
break;
}
}
}
if (elf_group_name (newsect) == NULL)
{
(*_bfd_error_handler) (_("%B: no group info for section %A"),
abfd, newsect);
return FALSE;
}
return TRUE;
}
bfd_boolean
_bfd_elf_setup_sections (bfd *abfd)
{
unsigned int i;
unsigned int num_group = elf_tdata (abfd)->num_group;
bfd_boolean result = TRUE;
asection *s;
/* Process SHF_LINK_ORDER. */
for (s = abfd->sections; s != NULL; s = s->next)
{
Elf_Internal_Shdr *this_hdr = &elf_section_data (s)->this_hdr;
if ((this_hdr->sh_flags & SHF_LINK_ORDER) != 0)
{
unsigned int elfsec = this_hdr->sh_link;
/* FIXME: The old Intel compiler and old strip/objcopy may
not set the sh_link or sh_info fields. Hence we could
get the situation where elfsec is 0. */
if (elfsec == 0)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (bed->link_order_error_handler)
bed->link_order_error_handler
(_("%B: warning: sh_link not set for section `%A'"),
abfd, s);
}
else
{
asection *linksec = NULL;
if (elfsec < elf_numsections (abfd))
{
this_hdr = elf_elfsections (abfd)[elfsec];
linksec = this_hdr->bfd_section;
}
/* PR 1991, 2008:
Some strip/objcopy may leave an incorrect value in
sh_link. We don't want to proceed. */
if (linksec == NULL)
{
(*_bfd_error_handler)
(_("%B: sh_link [%d] in section `%A' is incorrect"),
s->owner, s, elfsec);
result = FALSE;
}
elf_linked_to_section (s) = linksec;
}
}
}
/* Process section groups. */
if (num_group == (unsigned) -1)
return result;
for (i = 0; i < num_group; i++)
{
Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
Elf_Internal_Group *idx;
unsigned int n_elt;
/* PR binutils/18758: Beware of corrupt binaries with invalid group data. */
if (shdr == NULL || shdr->bfd_section == NULL || shdr->contents == NULL)
{
(*_bfd_error_handler)
(_("%B: section group entry number %u is corrupt"),
abfd, i);
result = FALSE;
continue;
}
idx = (Elf_Internal_Group *) shdr->contents;
n_elt = shdr->sh_size / 4;
while (--n_elt != 0)
if ((++idx)->shdr->bfd_section)
elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
else if (idx->shdr->sh_type == SHT_RELA
|| idx->shdr->sh_type == SHT_REL)
/* We won't include relocation sections in section groups in
output object files. We adjust the group section size here
so that relocatable link will work correctly when
relocation sections are in section group in input object
files. */
shdr->bfd_section->size -= 4;
else
{
/* There are some unknown sections in the group. */
(*_bfd_error_handler)
(_("%B: unknown [%d] section `%s' in group [%s]"),
abfd,
(unsigned int) idx->shdr->sh_type,
bfd_elf_string_from_elf_section (abfd,
(elf_elfheader (abfd)
->e_shstrndx),
idx->shdr->sh_name),
shdr->bfd_section->name);
result = FALSE;
}
}
return result;
}
bfd_boolean
bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
{
return elf_next_in_group (sec) != NULL;
}
static char *
convert_debug_to_zdebug (bfd *abfd, const char *name)
{
unsigned int len = strlen (name);
char *new_name = bfd_alloc (abfd, len + 2);
if (new_name == NULL)
return NULL;
new_name[0] = '.';
new_name[1] = 'z';
memcpy (new_name + 2, name + 1, len);
return new_name;
}
static char *
convert_zdebug_to_debug (bfd *abfd, const char *name)
{
unsigned int len = strlen (name);
char *new_name = bfd_alloc (abfd, len);
if (new_name == NULL)
return NULL;
new_name[0] = '.';
memcpy (new_name + 1, name + 2, len - 1);
return new_name;
}
/* Make a BFD section from an ELF section. We store a pointer to the
BFD section in the bfd_section field of the header. */
bfd_boolean
_bfd_elf_make_section_from_shdr (bfd *abfd,
Elf_Internal_Shdr *hdr,
const char *name,
int shindex)
{
asection *newsect;
flagword flags;
const struct elf_backend_data *bed;
if (hdr->bfd_section != NULL)
return TRUE;
newsect = bfd_make_section_anyway (abfd, name);
if (newsect == NULL)
return FALSE;
hdr->bfd_section = newsect;
elf_section_data (newsect)->this_hdr = *hdr;
elf_section_data (newsect)->this_idx = shindex;
/* Always use the real type/flags. */
elf_section_type (newsect) = hdr->sh_type;
elf_section_flags (newsect) = hdr->sh_flags;
newsect->filepos = hdr->sh_offset;
if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr)
|| ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
|| ! bfd_set_section_alignment (abfd, newsect,
bfd_log2 (hdr->sh_addralign)))
return FALSE;
flags = SEC_NO_FLAGS;
if (hdr->sh_type != SHT_NOBITS)
flags |= SEC_HAS_CONTENTS;
if (hdr->sh_type == SHT_GROUP)
flags |= SEC_GROUP | SEC_EXCLUDE;
if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
flags |= SEC_ALLOC;
if (hdr->sh_type != SHT_NOBITS)
flags |= SEC_LOAD;
}
if ((hdr->sh_flags & SHF_WRITE) == 0)
flags |= SEC_READONLY;
if ((hdr->sh_flags & SHF_EXECINSTR) != 0)
flags |= SEC_CODE;
else if ((flags & SEC_LOAD) != 0)
flags |= SEC_DATA;
if ((hdr->sh_flags & SHF_MERGE) != 0)
{
flags |= SEC_MERGE;
newsect->entsize = hdr->sh_entsize;
}
if ((hdr->sh_flags & SHF_STRINGS) != 0)
flags |= SEC_STRINGS;
if (hdr->sh_flags & SHF_GROUP)
if (!setup_group (abfd, hdr, newsect))
return FALSE;
if ((hdr->sh_flags & SHF_TLS) != 0)
flags |= SEC_THREAD_LOCAL;
if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
flags |= SEC_EXCLUDE;
if ((flags & SEC_ALLOC) == 0)
{
/* The debugging sections appear to be recognized only by name,
not any sort of flag. Their SEC_ALLOC bits are cleared. */
if (name [0] == '.')
{
const char *p;
int n;
if (name[1] == 'd')
p = ".debug", n = 6;
else if (name[1] == 'g' && name[2] == 'n')
p = ".gnu.linkonce.wi.", n = 17;
else if (name[1] == 'g' && name[2] == 'd')
p = ".gdb_index", n = 11; /* yes we really do mean 11. */
else if (name[1] == 'l')
p = ".line", n = 5;
else if (name[1] == 's')
p = ".stab", n = 5;
else if (name[1] == 'z')
p = ".zdebug", n = 7;
else
p = NULL, n = 0;
if (p != NULL && strncmp (name, p, n) == 0)
flags |= SEC_DEBUGGING;
}
}
/* As a GNU extension, if the name begins with .gnu.linkonce, we
only link a single copy of the section. This is used to support
g++. g++ will emit each template expansion in its own section.
The symbols will be defined as weak, so that multiple definitions
are permitted. The GNU linker extension is to actually discard
all but one of the sections. */
if (CONST_STRNEQ (name, ".gnu.linkonce")
&& elf_next_in_group (newsect) == NULL)
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_section_flags)
if (! bed->elf_backend_section_flags (&flags, hdr))
return FALSE;
if (! bfd_set_section_flags (abfd, newsect, flags))
return FALSE;
/* We do not parse the PT_NOTE segments as we are interested even in the
separate debug info files which may have the segments offsets corrupted.
PT_NOTEs from the core files are currently not parsed using BFD. */
if (hdr->sh_type == SHT_NOTE)
{
bfd_byte *contents;
if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
return FALSE;
elf_parse_notes (abfd, (char *) contents, hdr->sh_size, -1);
free (contents);
}
if ((flags & SEC_ALLOC) != 0)
{
Elf_Internal_Phdr *phdr;
unsigned int i, nload;
/* Some ELF linkers produce binaries with all the program header
p_paddr fields zero. If we have such a binary with more than
one PT_LOAD header, then leave the section lma equal to vma
so that we don't create sections with overlapping lma. */
phdr = elf_tdata (abfd)->phdr;
for (nload = 0, i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
if (phdr->p_paddr != 0)
break;
else if (phdr->p_type == PT_LOAD && phdr->p_memsz != 0)
++nload;
if (i >= elf_elfheader (abfd)->e_phnum && nload > 1)
return TRUE;
phdr = elf_tdata (abfd)->phdr;
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
{
if (((phdr->p_type == PT_LOAD
&& (hdr->sh_flags & SHF_TLS) == 0)
|| phdr->p_type == PT_TLS)
&& ELF_SECTION_IN_SEGMENT (hdr, phdr))
{
if ((flags & SEC_LOAD) == 0)
newsect->lma = (phdr->p_paddr
+ hdr->sh_addr - phdr->p_vaddr);
else
/* We used to use the same adjustment for SEC_LOAD
sections, but that doesn't work if the segment
is packed with code from multiple VMAs.
Instead we calculate the section LMA based on
the segment LMA. It is assumed that the
segment will contain sections with contiguous
LMAs, even if the VMAs are not. */
newsect->lma = (phdr->p_paddr
+ hdr->sh_offset - phdr->p_offset);
/* With contiguous segments, we can't tell from file
offsets whether a section with zero size should
be placed at the end of one segment or the
beginning of the next. Decide based on vaddr. */
if (hdr->sh_addr >= phdr->p_vaddr
&& (hdr->sh_addr + hdr->sh_size
<= phdr->p_vaddr + phdr->p_memsz))
break;
}
}
}
/* Compress/decompress DWARF debug sections with names: .debug_* and
.zdebug_*, after the section flags is set. */
if ((flags & SEC_DEBUGGING)
&& ((name[1] == 'd' && name[6] == '_')
|| (name[1] == 'z' && name[7] == '_')))
{
enum { nothing, compress, decompress } action = nothing;
int compression_header_size;
bfd_size_type uncompressed_size;
bfd_boolean compressed
= bfd_is_section_compressed_with_header (abfd, newsect,
&compression_header_size,
&uncompressed_size);
if (compressed)
{
/* Compressed section. Check if we should decompress. */
if ((abfd->flags & BFD_DECOMPRESS))
action = decompress;
}
/* Compress the uncompressed section or convert from/to .zdebug*
section. Check if we should compress. */
if (action == nothing)
{
if (newsect->size != 0
&& (abfd->flags & BFD_COMPRESS)
&& compression_header_size >= 0
&& uncompressed_size > 0
&& (!compressed
|| ((compression_header_size > 0)
!= ((abfd->flags & BFD_COMPRESS_GABI) != 0))))
action = compress;
else
return TRUE;
}
if (action == compress)
{
if (!bfd_init_section_compress_status (abfd, newsect))
{
(*_bfd_error_handler)
(_("%B: unable to initialize compress status for section %s"),
abfd, name);
return FALSE;
}
}
else
{
if (!bfd_init_section_decompress_status (abfd, newsect))
{
(*_bfd_error_handler)
(_("%B: unable to initialize decompress status for section %s"),
abfd, name);
return FALSE;
}
}
if (abfd->is_linker_input)
{
if (name[1] == 'z'
&& (action == decompress
|| (action == compress
&& (abfd->flags & BFD_COMPRESS_GABI) != 0)))
{
/* Convert section name from .zdebug_* to .debug_* so
that linker will consider this section as a debug
section. */
char *new_name = convert_zdebug_to_debug (abfd, name);
if (new_name == NULL)
return FALSE;
bfd_rename_section (abfd, newsect, new_name);
}
}
else
/* For objdump, don't rename the section. For objcopy, delay
section rename to elf_fake_sections. */
newsect->flags |= SEC_ELF_RENAME;
}
return TRUE;
}
const char *const bfd_elf_section_type_names[] =
{
"SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB",
"SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE",
"SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
};
/* ELF relocs are against symbols. If we are producing relocatable
output, and the reloc is against an external symbol, and nothing
has given us any additional addend, the resulting reloc will also
be against the same symbol. In such a case, we don't want to
change anything about the way the reloc is handled, since it will
all be done at final link time. Rather than put special case code
into bfd_perform_relocation, all the reloc types use this howto
function. It just short circuits the reloc if producing
relocatable output against an external symbol. */
bfd_reloc_status_type
bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
arelent *reloc_entry,
asymbol *symbol,
void *data ATTRIBUTE_UNUSED,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
{
if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
|| reloc_entry->addend == 0))
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
return bfd_reloc_continue;
}
/* Returns TRUE if section A matches section B.
Names, addresses and links may be different, but everything else
should be the same. */
static bfd_boolean
section_match (const Elf_Internal_Shdr * a,
const Elf_Internal_Shdr * b)
{
return
a->sh_type == b->sh_type
&& (a->sh_flags & ~ SHF_INFO_LINK)
== (b->sh_flags & ~ SHF_INFO_LINK)
&& a->sh_addralign == b->sh_addralign
&& a->sh_size == b->sh_size
&& a->sh_entsize == b->sh_entsize
/* FIXME: Check sh_addr ? */
;
}
/* Find a section in OBFD that has the same characteristics
as IHEADER. Return the index of this section or SHN_UNDEF if
none can be found. Check's section HINT first, as this is likely
to be the correct section. */
static unsigned int
find_link (const bfd * obfd, const Elf_Internal_Shdr * iheader, const unsigned int hint)
{
Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
unsigned int i;
if (section_match (oheaders[hint], iheader))
return hint;
for (i = 1; i < elf_numsections (obfd); i++)
{
Elf_Internal_Shdr * oheader = oheaders[i];
if (section_match (oheader, iheader))
/* FIXME: Do we care if there is a potential for
multiple matches ? */
return i;
}
return SHN_UNDEF;
}
/* PR 19938: Attempt to set the ELF section header fields of an OS or
Processor specific section, based upon a matching input section.
Returns TRUE upon success, FALSE otherwise. */
static bfd_boolean
copy_special_section_fields (const bfd *ibfd,
bfd *obfd,
const Elf_Internal_Shdr *iheader,
Elf_Internal_Shdr *oheader,
const unsigned int secnum)
{
const struct elf_backend_data *bed = get_elf_backend_data (obfd);
const Elf_Internal_Shdr **iheaders = (const Elf_Internal_Shdr **) elf_elfsections (ibfd);
bfd_boolean changed = FALSE;
unsigned int sh_link;
if (oheader->sh_type == SHT_NOBITS)
{
/* This is a feature for objcopy --only-keep-debug:
When a section's type is changed to NOBITS, we preserve
the sh_link and sh_info fields so that they can be
matched up with the original.
Note: Strictly speaking these assignments are wrong.
The sh_link and sh_info fields should point to the
relevent sections in the output BFD, which may not be in
the same location as they were in the input BFD. But
the whole point of this action is to preserve the
original values of the sh_link and sh_info fields, so
that they can be matched up with the section headers in
the original file. So strictly speaking we may be
creating an invalid ELF file, but it is only for a file
that just contains debug info and only for sections
without any contents. */
if (oheader->sh_link == 0)
oheader->sh_link = iheader->sh_link;
if (oheader->sh_info == 0)
oheader->sh_info = iheader->sh_info;
return TRUE;
}
/* Allow the target a chance to decide how these fields should be set. */
if (bed->elf_backend_copy_special_section_fields != NULL
&& bed->elf_backend_copy_special_section_fields
(ibfd, obfd, iheader, oheader))
return TRUE;
/* We have an iheader which might match oheader, and which has non-zero
sh_info and/or sh_link fields. Attempt to follow those links and find
the section in the output bfd which corresponds to the linked section
in the input bfd. */
if (iheader->sh_link != SHN_UNDEF)
{
sh_link = find_link (obfd, iheaders[iheader->sh_link], iheader->sh_link);
if (sh_link != SHN_UNDEF)
{
oheader->sh_link = sh_link;
changed = TRUE;
}
else
/* FIXME: Should we install iheader->sh_link
if we could not find a match ? */
(* _bfd_error_handler)
(_("%B: Failed to find link section for section %d"), obfd, secnum);
}
if (iheader->sh_info)
{
/* The sh_info field can hold arbitrary information, but if the
SHF_LINK_INFO flag is set then it should be interpreted as a
section index. */
if (iheader->sh_flags & SHF_INFO_LINK)
{
sh_link = find_link (obfd, iheaders[iheader->sh_info],
iheader->sh_info);
if (sh_link != SHN_UNDEF)
oheader->sh_flags |= SHF_INFO_LINK;
}
else
/* No idea what it means - just copy it. */
sh_link = iheader->sh_info;
if (sh_link != SHN_UNDEF)
{
oheader->sh_info = sh_link;
changed = TRUE;
}
else
(* _bfd_error_handler)
(_("%B: Failed to find info section for section %d"), obfd, secnum);
}
return changed;
}
/* Copy the program header and other data from one object module to
another. */
bfd_boolean
_bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
const Elf_Internal_Shdr **iheaders = (const Elf_Internal_Shdr **) elf_elfsections (ibfd);
Elf_Internal_Shdr **oheaders = elf_elfsections (obfd);
const struct elf_backend_data *bed;
unsigned int i;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
if (!elf_flags_init (obfd))
{
elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
elf_flags_init (obfd) = TRUE;
}
elf_gp (obfd) = elf_gp (ibfd);
/* Also copy the EI_OSABI field. */
elf_elfheader (obfd)->e_ident[EI_OSABI] =
elf_elfheader (ibfd)->e_ident[EI_OSABI];
/* If set, copy the EI_ABIVERSION field. */
if (elf_elfheader (ibfd)->e_ident[EI_ABIVERSION])
elf_elfheader (obfd)->e_ident[EI_ABIVERSION]
= elf_elfheader (ibfd)->e_ident[EI_ABIVERSION];
/* Copy object attributes. */
_bfd_elf_copy_obj_attributes (ibfd, obfd);
if (iheaders == NULL || oheaders == NULL)
return TRUE;
bed = get_elf_backend_data (obfd);
/* Possibly copy other fields in the section header. */
for (i = 1; i < elf_numsections (obfd); i++)
{
unsigned int j;
Elf_Internal_Shdr * oheader = oheaders[i];
/* Ignore ordinary sections. SHT_NOBITS sections are considered however
because of a special case need for generating separate debug info
files. See below for more details. */
if (oheader == NULL
|| (oheader->sh_type != SHT_NOBITS
&& oheader->sh_type < SHT_LOOS))
continue;
/* Ignore empty sections, and sections whose
fields have already been initialised. */
if (oheader->sh_size == 0
|| (oheader->sh_info != 0 && oheader->sh_link != 0))
continue;
/* Scan for the matching section in the input bfd.
First we try for a direct mapping between the input and output sections. */
for (j = 1; j < elf_numsections (ibfd); j++)
{
const Elf_Internal_Shdr * iheader = iheaders[j];
if (iheader == NULL)
continue;
if (oheader->bfd_section != NULL
&& iheader->bfd_section != NULL
&& iheader->bfd_section->output_section != NULL
&& iheader->bfd_section->output_section == oheader->bfd_section)
{
/* We have found a connection from the input section to the
output section. Attempt to copy the header fields. If
this fails then do not try any further sections - there
should only be a one-to-one mapping between input and output. */
if (! copy_special_section_fields (ibfd, obfd, iheader, oheader, i))
j = elf_numsections (ibfd);
break;
}
}
if (j < elf_numsections (ibfd))
continue;
/* That failed. So try to deduce the corresponding input section.
Unfortunately we cannot compare names as the output string table
is empty, so instead we check size, address and type. */
for (j = 1; j < elf_numsections (ibfd); j++)
{
const Elf_Internal_Shdr * iheader = iheaders[j];
if (iheader == NULL)
continue;
/* Try matching fields in the input section's header.
Since --only-keep-debug turns all non-debug sections into
SHT_NOBITS sections, the output SHT_NOBITS type matches any
input type. */
if ((oheader->sh_type == SHT_NOBITS
|| iheader->sh_type == oheader->sh_type)
&& (iheader->sh_flags & ~ SHF_INFO_LINK)
== (oheader->sh_flags & ~ SHF_INFO_LINK)
&& iheader->sh_addralign == oheader->sh_addralign
&& iheader->sh_entsize == oheader->sh_entsize
&& iheader->sh_size == oheader->sh_size
&& iheader->sh_addr == oheader->sh_addr
&& (iheader->sh_info != oheader->sh_info
|| iheader->sh_link != oheader->sh_link))
{
if (copy_special_section_fields (ibfd, obfd, iheader, oheader, i))
break;
}
}
if (j == elf_numsections (ibfd) && oheader->sh_type >= SHT_LOOS)
{
/* Final attempt. Call the backend copy function
with a NULL input section. */
if (bed->elf_backend_copy_special_section_fields != NULL)
bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
}
}
return TRUE;
}
static const char *
get_segment_type (unsigned int p_type)
{
const char *pt;
switch (p_type)
{
case PT_NULL: pt = "NULL"; break;
case PT_LOAD: pt = "LOAD"; break;
case PT_DYNAMIC: pt = "DYNAMIC"; break;
case PT_INTERP: pt = "INTERP"; break;
case PT_NOTE: pt = "NOTE"; break;
case PT_SHLIB: pt = "SHLIB"; break;
case PT_PHDR: pt = "PHDR"; break;
case PT_TLS: pt = "TLS"; break;
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
case PT_GNU_STACK: pt = "STACK"; break;
case PT_GNU_RELRO: pt = "RELRO"; break;
default: pt = NULL; break;
}
return pt;
}
/* Print out the program headers. */
bfd_boolean
_bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
{
FILE *f = (FILE *) farg;
Elf_Internal_Phdr *p;
asection *s;
bfd_byte *dynbuf = NULL;
p = elf_tdata (abfd)->phdr;
if (p != NULL)
{
unsigned int i, c;
fprintf (f, _("\nProgram Header:\n"));
c = elf_elfheader (abfd)->e_phnum;
for (i = 0; i < c; i++, p++)
{
const char *pt = get_segment_type (p->p_type);
char buf[20];
if (pt == NULL)
{
sprintf (buf, "0x%lx", p->p_type);
pt = buf;
}
fprintf (f, "%8s off 0x", pt);
bfd_fprintf_vma (abfd, f, p->p_offset);
fprintf (f, " vaddr 0x");
bfd_fprintf_vma (abfd, f, p->p_vaddr);
fprintf (f, " paddr 0x");
bfd_fprintf_vma (abfd, f, p->p_paddr);
fprintf (f, " align 2**%u\n", bfd_log2 (p->p_align));
fprintf (f, " filesz 0x");
bfd_fprintf_vma (abfd, f, p->p_filesz);
fprintf (f, " memsz 0x");
bfd_fprintf_vma (abfd, f, p->p_memsz);
fprintf (f, " flags %c%c%c",
(p->p_flags & PF_R) != 0 ? 'r' : '-',
(p->p_flags & PF_W) != 0 ? 'w' : '-',
(p->p_flags & PF_X) != 0 ? 'x' : '-');
if ((p->p_flags &~ (unsigned) (PF_R | PF_W | PF_X)) != 0)
fprintf (f, " %lx", p->p_flags &~ (unsigned) (PF_R | PF_W | PF_X));
fprintf (f, "\n");
}
}
s = bfd_get_section_by_name (abfd, ".dynamic");
if (s != NULL)
{
unsigned int elfsec;
unsigned long shlink;
bfd_byte *extdyn, *extdynend;
size_t extdynsize;
void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
fprintf (f, _("\nDynamic Section:\n"));
if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
if (elfsec == SHN_BAD)
goto error_return;
shlink = elf_elfsections (abfd)[elfsec]->sh_link;
extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
extdyn = dynbuf;
/* PR 17512: file: 6f427532. */
if (s->size < extdynsize)
goto error_return;
extdynend = extdyn + s->size;
/* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
Fix range check. */
for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
const char *name = "";
char ab[20];
bfd_boolean stringp;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
(*swap_dyn_in) (abfd, extdyn, &dyn);
if (dyn.d_tag == DT_NULL)
break;
stringp = FALSE;
switch (dyn.d_tag)
{
default:
if (bed->elf_backend_get_target_dtag)
name = (*bed->elf_backend_get_target_dtag) (dyn.d_tag);
if (!strcmp (name, ""))
{
sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
name = ab;
}
break;
case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
case DT_PLTRELSZ: name = "PLTRELSZ"; break;
case DT_PLTGOT: name = "PLTGOT"; break;
case DT_HASH: name = "HASH"; break;
case DT_STRTAB: name = "STRTAB"; break;
case DT_SYMTAB: name = "SYMTAB"; break;
case DT_RELA: name = "RELA"; break;
case DT_RELASZ: name = "RELASZ"; break;
case DT_RELAENT: name = "RELAENT"; break;
case DT_STRSZ: name = "STRSZ"; break;
case DT_SYMENT: name = "SYMENT"; break;
case DT_INIT: name = "INIT"; break;
case DT_FINI: name = "FINI"; break;
case DT_SONAME: name = "SONAME"; stringp = TRUE; break;
case DT_RPATH: name = "RPATH"; stringp = TRUE; break;
case DT_SYMBOLIC: name = "SYMBOLIC"; break;
case DT_REL: name = "REL"; break;
case DT_RELSZ: name = "RELSZ"; break;
case DT_RELENT: name = "RELENT"; break;
case DT_PLTREL: name = "PLTREL"; break;
case DT_DEBUG: name = "DEBUG"; break;
case DT_TEXTREL: name = "TEXTREL"; break;
case DT_JMPREL: name = "JMPREL"; break;
case DT_BIND_NOW: name = "BIND_NOW"; break;
case DT_INIT_ARRAY: name = "INIT_ARRAY"; break;
case DT_FINI_ARRAY: name = "FINI_ARRAY"; break;
case DT_INIT_ARRAYSZ: name = "INIT_ARRAYSZ"; break;
case DT_FINI_ARRAYSZ: name = "FINI_ARRAYSZ"; break;
case DT_RUNPATH: name = "RUNPATH"; stringp = TRUE; break;
case DT_FLAGS: name = "FLAGS"; break;
case DT_PREINIT_ARRAY: name = "PREINIT_ARRAY"; break;
case DT_PREINIT_ARRAYSZ: name = "PREINIT_ARRAYSZ"; break;
case DT_CHECKSUM: name = "CHECKSUM"; break;
case DT_PLTPADSZ: name = "PLTPADSZ"; break;
case DT_MOVEENT: name = "MOVEENT"; break;
case DT_MOVESZ: name = "MOVESZ"; break;
case DT_FEATURE: name = "FEATURE"; break;
case DT_POSFLAG_1: name = "POSFLAG_1"; break;
case DT_SYMINSZ: name = "SYMINSZ"; break;
case DT_SYMINENT: name = "SYMINENT"; break;
case DT_CONFIG: name = "CONFIG"; stringp = TRUE; break;
case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = TRUE; break;
case DT_AUDIT: name = "AUDIT"; stringp = TRUE; break;
case DT_PLTPAD: name = "PLTPAD"; break;
case DT_MOVETAB: name = "MOVETAB"; break;
case DT_SYMINFO: name = "SYMINFO"; break;
case DT_RELACOUNT: name = "RELACOUNT"; break;
case DT_RELCOUNT: name = "RELCOUNT"; break;
case DT_FLAGS_1: name = "FLAGS_1"; break;
case DT_VERSYM: name = "VERSYM"; break;
case DT_VERDEF: name = "VERDEF"; break;
case DT_VERDEFNUM: name = "VERDEFNUM"; break;
case DT_VERNEED: name = "VERNEED"; break;
case DT_VERNEEDNUM: name = "VERNEEDNUM"; break;
case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
case DT_USED: name = "USED"; break;
case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
case DT_GNU_HASH: name = "GNU_HASH"; break;
}
fprintf (f, " %-20s ", name);
if (! stringp)
{
fprintf (f, "0x");
bfd_fprintf_vma (abfd, f, dyn.d_un.d_val);
}
else
{
const char *string;
unsigned int tagv = dyn.d_un.d_val;
string = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
if (string == NULL)
goto error_return;
fprintf (f, "%s", string);
}
fprintf (f, "\n");
}
free (dynbuf);
dynbuf = NULL;
}
if ((elf_dynverdef (abfd) != 0 && elf_tdata (abfd)->verdef == NULL)
|| (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL))
{
if (! _bfd_elf_slurp_version_tables (abfd, FALSE))
return FALSE;
}
if (elf_dynverdef (abfd) != 0)
{
Elf_Internal_Verdef *t;
fprintf (f, _("\nVersion definitions:\n"));
for (t = elf_tdata (abfd)->verdef; t != NULL; t = t->vd_nextdef)
{
fprintf (f, "%d 0x%2.2x 0x%8.8lx %s\n", t->vd_ndx,
t->vd_flags, t->vd_hash,
t->vd_nodename ? t->vd_nodename : "<corrupt>");
if (t->vd_auxptr != NULL && t->vd_auxptr->vda_nextptr != NULL)
{
Elf_Internal_Verdaux *a;
fprintf (f, "\t");
for (a = t->vd_auxptr->vda_nextptr;
a != NULL;
a = a->vda_nextptr)
fprintf (f, "%s ",
a->vda_nodename ? a->vda_nodename : "<corrupt>");
fprintf (f, "\n");
}
}
}
if (elf_dynverref (abfd) != 0)
{
Elf_Internal_Verneed *t;
fprintf (f, _("\nVersion References:\n"));
for (t = elf_tdata (abfd)->verref; t != NULL; t = t->vn_nextref)
{
Elf_Internal_Vernaux *a;
fprintf (f, _(" required from %s:\n"),
t->vn_filename ? t->vn_filename : "<corrupt>");
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
fprintf (f, " 0x%8.8lx 0x%2.2x %2.2d %s\n", a->vna_hash,
a->vna_flags, a->vna_other,
a->vna_nodename ? a->vna_nodename : "<corrupt>");
}
}
return TRUE;
error_return:
if (dynbuf != NULL)
free (dynbuf);
return FALSE;
}
/* Get version string. */
const char *
_bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
bfd_boolean *hidden)
{
const char *version_string = NULL;
if (elf_dynversym (abfd) != 0
&& (elf_dynverdef (abfd) != 0 || elf_dynverref (abfd) != 0))
{
unsigned int vernum = ((elf_symbol_type *) symbol)->version;
*hidden = (vernum & VERSYM_HIDDEN) != 0;
vernum &= VERSYM_VERSION;
if (vernum == 0)
version_string = "";
else if (vernum == 1)
version_string = "Base";
else if (vernum <= elf_tdata (abfd)->cverdefs)
version_string =
elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
else
{
Elf_Internal_Verneed *t;
version_string = "";
for (t = elf_tdata (abfd)->verref;
t != NULL;
t = t->vn_nextref)
{
Elf_Internal_Vernaux *a;
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
{
if (a->vna_other == vernum)
{
version_string = a->vna_nodename;
break;
}
}
}
}
}
return version_string;
}
/* Display ELF-specific fields of a symbol. */
void
bfd_elf_print_symbol (bfd *abfd,
void *filep,
asymbol *symbol,
bfd_print_symbol_type how)
{
FILE *file = (FILE *) filep;
switch (how)
{
case bfd_print_symbol_name:
fprintf (file, "%s", symbol->name);
break;
case bfd_print_symbol_more:
fprintf (file, "elf ");
bfd_fprintf_vma (abfd, file, symbol->value);
fprintf (file, " %lx", (unsigned long) symbol->flags);
break;
case bfd_print_symbol_all:
{
const char *section_name;
const char *name = NULL;
const struct elf_backend_data *bed;
unsigned char st_other;
bfd_vma val;
const char *version_string;
bfd_boolean hidden;
section_name = symbol->section ? symbol->section->name : "(*none*)";
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_print_symbol_all)
name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
if (name == NULL)
{
name = symbol->name;
bfd_print_symbol_vandf (abfd, file, symbol);
}
fprintf (file, " %s\t", section_name);
/* Print the "other" value for a symbol. For common symbols,
we've already printed the size; now print the alignment.
For other symbols, we have no specified alignment, and
we've printed the address; now print the size. */
if (symbol->section && bfd_is_com_section (symbol->section))
val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
else
val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_size;
bfd_fprintf_vma (abfd, file, val);
/* If we have version information, print it. */
version_string = _bfd_elf_get_symbol_version_string (abfd,
symbol,
&hidden);
if (version_string)
{
if (!hidden)
fprintf (file, " %-11s", version_string);
else
{
int i;
fprintf (file, " (%s)", version_string);
for (i = 10 - strlen (version_string); i > 0; --i)
putc (' ', file);
}
}
/* If the st_other field is not zero, print it. */
st_other = ((elf_symbol_type *) symbol)->internal_elf_sym.st_other;
switch (st_other)
{
case 0: break;
case STV_INTERNAL: fprintf (file, " .internal"); break;
case STV_HIDDEN: fprintf (file, " .hidden"); break;
case STV_PROTECTED: fprintf (file, " .protected"); break;
default:
/* Some other non-defined flags are also present, so print
everything hex. */
fprintf (file, " 0x%02x", (unsigned int) st_other);
}
fprintf (file, " %s", name);
}
break;
}
}
/* ELF .o/exec file reading */
/* Create a new bfd section from an ELF section header. */
bfd_boolean
bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
{
Elf_Internal_Shdr *hdr;
Elf_Internal_Ehdr *ehdr;
const struct elf_backend_data *bed;
const char *name;
bfd_boolean ret = TRUE;
static bfd_boolean * sections_being_created = NULL;
static bfd * sections_being_created_abfd = NULL;
static unsigned int nesting = 0;
if (shindex >= elf_numsections (abfd))
return FALSE;
if (++ nesting > 3)
{
/* PR17512: A corrupt ELF binary might contain a recursive group of
sections, with each the string indicies pointing to the next in the
loop. Detect this here, by refusing to load a section that we are
already in the process of loading. We only trigger this test if
we have nested at least three sections deep as normal ELF binaries
can expect to recurse at least once.
FIXME: It would be better if this array was attached to the bfd,
rather than being held in a static pointer. */
if (sections_being_created_abfd != abfd)
sections_being_created = NULL;
if (sections_being_created == NULL)
{
/* FIXME: It would be more efficient to attach this array to the bfd somehow. */
sections_being_created = (bfd_boolean *)
bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean));
sections_being_created_abfd = abfd;
}
if (sections_being_created [shindex])
{
(*_bfd_error_handler)
(_("%B: warning: loop in section dependencies detected"), abfd);
return FALSE;
}
sections_being_created [shindex] = TRUE;
}
hdr = elf_elfsections (abfd)[shindex];
ehdr = elf_elfheader (abfd);
name = bfd_elf_string_from_elf_section (abfd, ehdr->e_shstrndx,
hdr->sh_name);
if (name == NULL)
goto fail;
bed = get_elf_backend_data (abfd);
switch (hdr->sh_type)
{
case SHT_NULL:
/* Inactive section. Throw it away. */
goto success;
case SHT_PROGBITS: /* Normal section with contents. */
case SHT_NOBITS: /* .bss section. */
case SHT_HASH: /* .hash section. */
case SHT_NOTE: /* .note section. */
case SHT_INIT_ARRAY: /* .init_array section. */
case SHT_FINI_ARRAY: /* .fini_array section. */
case SHT_PREINIT_ARRAY: /* .preinit_array section. */
case SHT_GNU_LIBLIST: /* .gnu.liblist section. */
case SHT_GNU_HASH: /* .gnu.hash section. */
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
goto success;
case SHT_DYNAMIC: /* Dynamic linking information. */
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
goto fail;
if (hdr->sh_link > elf_numsections (abfd))
{
/* PR 10478: Accept Solaris binaries with a sh_link
field set to SHN_BEFORE or SHN_AFTER. */
switch (bfd_get_arch (abfd))
{
case bfd_arch_i386:
case bfd_arch_sparc:
if (hdr->sh_link == (SHN_LORESERVE & 0xffff) /* SHN_BEFORE */
|| hdr->sh_link == ((SHN_LORESERVE + 1) & 0xffff) /* SHN_AFTER */)
break;
/* Otherwise fall through. */
default:
goto fail;
}
}
else if (elf_elfsections (abfd)[hdr->sh_link] == NULL)
goto fail;
else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
{
Elf_Internal_Shdr *dynsymhdr;
/* The shared libraries distributed with hpux11 have a bogus
sh_link field for the ".dynamic" section. Find the
string table for the ".dynsym" section instead. */
if (elf_dynsymtab (abfd) != 0)
{
dynsymhdr = elf_elfsections (abfd)[elf_dynsymtab (abfd)];
hdr->sh_link = dynsymhdr->sh_link;
}
else
{
unsigned int i, num_sec;
num_sec = elf_numsections (abfd);
for (i = 1; i < num_sec; i++)
{
dynsymhdr = elf_elfsections (abfd)[i];
if (dynsymhdr->sh_type == SHT_DYNSYM)
{
hdr->sh_link = dynsymhdr->sh_link;
break;
}
}
}
}
goto success;
case SHT_SYMTAB: /* A symbol table. */
if (elf_onesymtab (abfd) == shindex)
goto success;
if (hdr->sh_entsize != bed->s->sizeof_sym)
goto fail;
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
{
if (hdr->sh_size != 0)
goto fail;
/* Some assemblers erroneously set sh_info to one with a
zero sh_size. ld sees this as a global symbol count
of (unsigned) -1. Fix it here. */
hdr->sh_info = 0;
goto success;
}
/* PR 18854: A binary might contain more than one symbol table.
Unusual, but possible. Warn, but continue. */
if (elf_onesymtab (abfd) != 0)
{
(*_bfd_error_handler)
(_("%B: warning: multiple symbol tables detected - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
elf_onesymtab (abfd) = shindex;
elf_symtab_hdr (abfd) = *hdr;
elf_elfsections (abfd)[shindex] = hdr = & elf_symtab_hdr (abfd);
abfd->flags |= HAS_SYMS;
/* Sometimes a shared object will map in the symbol table. If
SHF_ALLOC is set, and this is a shared object, then we also
treat this section as a BFD section. We can not base the
decision purely on SHF_ALLOC, because that flag is sometimes
set in a relocatable object file, which would confuse the
linker. */
if ((hdr->sh_flags & SHF_ALLOC) != 0
&& (abfd->flags & DYNAMIC) != 0
&& ! _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex))
goto fail;
/* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
can't read symbols without that section loaded as well. It
is most likely specified by the next section header. */
{
elf_section_list * entry;
unsigned int i, num_sec;
for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
if (entry->hdr.sh_link == shindex)
goto success;
num_sec = elf_numsections (abfd);
for (i = shindex + 1; i < num_sec; i++)
{
Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
if (hdr2->sh_type == SHT_SYMTAB_SHNDX
&& hdr2->sh_link == shindex)
break;
}
if (i == num_sec)
for (i = 1; i < shindex; i++)
{
Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
if (hdr2->sh_type == SHT_SYMTAB_SHNDX
&& hdr2->sh_link == shindex)
break;
}
if (i != shindex)
ret = bfd_section_from_shdr (abfd, i);
/* else FIXME: we have failed to find the symbol table - should we issue an error ? */
goto success;
}
case SHT_DYNSYM: /* A dynamic symbol table. */
if (elf_dynsymtab (abfd) == shindex)
goto success;
if (hdr->sh_entsize != bed->s->sizeof_sym)
goto fail;
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
{
if (hdr->sh_size != 0)
goto fail;
/* Some linkers erroneously set sh_info to one with a
zero sh_size. ld sees this as a global symbol count
of (unsigned) -1. Fix it here. */
hdr->sh_info = 0;
goto success;
}
/* PR 18854: A binary might contain more than one dynamic symbol table.
Unusual, but possible. Warn, but continue. */
if (elf_dynsymtab (abfd) != 0)
{
(*_bfd_error_handler)
(_("%B: warning: multiple dynamic symbol tables detected - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
elf_dynsymtab (abfd) = shindex;
elf_tdata (abfd)->dynsymtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynsymtab_hdr;
abfd->flags |= HAS_SYMS;
/* Besides being a symbol table, we also treat this as a regular
section, so that objcopy can handle it. */
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
goto success;
case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections. */
{
elf_section_list * entry;
for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
if (entry->ndx == shindex)
goto success;
entry = bfd_alloc (abfd, sizeof * entry);
if (entry == NULL)
goto fail;
entry->ndx = shindex;
entry->hdr = * hdr;
entry->next = elf_symtab_shndx_list (abfd);
elf_symtab_shndx_list (abfd) = entry;
elf_elfsections (abfd)[shindex] = & entry->hdr;
goto success;
}
case SHT_STRTAB: /* A string table. */
if (hdr->bfd_section != NULL)
goto success;
if (ehdr->e_shstrndx == shindex)
{
elf_tdata (abfd)->shstrtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
goto success;
}
if (elf_elfsections (abfd)[elf_onesymtab (abfd)]->sh_link == shindex)
{
symtab_strtab:
elf_tdata (abfd)->strtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr;
goto success;
}
if (elf_elfsections (abfd)[elf_dynsymtab (abfd)]->sh_link == shindex)
{
dynsymtab_strtab:
elf_tdata (abfd)->dynstrtab_hdr = *hdr;
hdr = &elf_tdata (abfd)->dynstrtab_hdr;
elf_elfsections (abfd)[shindex] = hdr;
/* We also treat this as a regular section, so that objcopy
can handle it. */
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
goto success;
}
/* If the string table isn't one of the above, then treat it as a
regular section. We need to scan all the headers to be sure,
just in case this strtab section appeared before the above. */
if (elf_onesymtab (abfd) == 0 || elf_dynsymtab (abfd) == 0)
{
unsigned int i, num_sec;
num_sec = elf_numsections (abfd);
for (i = 1; i < num_sec; i++)
{
Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
if (hdr2->sh_link == shindex)
{
/* Prevent endless recursion on broken objects. */
if (i == shindex)
goto fail;
if (! bfd_section_from_shdr (abfd, i))
goto fail;
if (elf_onesymtab (abfd) == i)
goto symtab_strtab;
if (elf_dynsymtab (abfd) == i)
goto dynsymtab_strtab;
}
}
}
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
goto success;
case SHT_REL:
case SHT_RELA:
/* *These* do a lot of work -- but build no sections! */
{
asection *target_sect;
Elf_Internal_Shdr *hdr2, **p_hdr;
unsigned int num_sec = elf_numsections (abfd);
struct bfd_elf_section_data *esdt;
if (hdr->sh_entsize
!= (bfd_size_type) (hdr->sh_type == SHT_REL
? bed->s->sizeof_rel : bed->s->sizeof_rela))
goto fail;
/* Check for a bogus link to avoid crashing. */
if (hdr->sh_link >= num_sec)
{
((*_bfd_error_handler)
(_("%B: invalid link %lu for reloc section %s (index %u)"),
abfd, hdr->sh_link, name, shindex));
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
goto success;
}
/* For some incomprehensible reason Oracle distributes
libraries for Solaris in which some of the objects have
bogus sh_link fields. It would be nice if we could just
reject them, but, unfortunately, some people need to use
them. We scan through the section headers; if we find only
one suitable symbol table, we clobber the sh_link to point
to it. I hope this doesn't break anything.
Don't do it on executable nor shared library. */
if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0
&& elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB
&& elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_DYNSYM)
{
unsigned int scan;
int found;
found = 0;
for (scan = 1; scan < num_sec; scan++)
{
if (elf_elfsections (abfd)[scan]->sh_type == SHT_SYMTAB
|| elf_elfsections (abfd)[scan]->sh_type == SHT_DYNSYM)
{
if (found != 0)
{
found = 0;
break;
}
found = scan;
}
}
if (found != 0)
hdr->sh_link = found;
}
/* Get the symbol table. */
if ((elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
|| elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_DYNSYM)
&& ! bfd_section_from_shdr (abfd, hdr->sh_link))
goto fail;
/* If this reloc section does not use the main symbol table we
don't treat it as a reloc section. BFD can't adequately
represent such a section, so at least for now, we don't
try. We just present it as a normal section. We also
can't use it as a reloc section if it points to the null
section, an invalid section, another reloc section, or its
sh_link points to the null section. */
if (hdr->sh_link != elf_onesymtab (abfd)
|| hdr->sh_link == SHN_UNDEF
|| hdr->sh_info == SHN_UNDEF
|| hdr->sh_info >= num_sec
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA)
{
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
goto success;
}
if (! bfd_section_from_shdr (abfd, hdr->sh_info))
goto fail;
target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
if (target_sect == NULL)
goto fail;
esdt = elf_section_data (target_sect);
if (hdr->sh_type == SHT_RELA)
p_hdr = &esdt->rela.hdr;
else
p_hdr = &esdt->rel.hdr;
/* PR 17512: file: 0b4f81b7. */
if (*p_hdr != NULL)
goto fail;
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2));
if (hdr2 == NULL)
goto fail;
*hdr2 = *hdr;
*p_hdr = hdr2;
elf_elfsections (abfd)[shindex] = hdr2;
target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
target_sect->flags |= SEC_RELOC;
target_sect->relocation = NULL;
target_sect->rel_filepos = hdr->sh_offset;
/* In the section to which the relocations apply, mark whether
its relocations are of the REL or RELA variety. */
if (hdr->sh_size != 0)
{
if (hdr->sh_type == SHT_RELA)
target_sect->use_rela_p = 1;
}
abfd->flags |= HAS_RELOC;
goto success;
}
case SHT_GNU_verdef:
elf_dynverdef (abfd) = shindex;
elf_tdata (abfd)->dynverdef_hdr = *hdr;
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
goto success;
case SHT_GNU_versym:
if (hdr->sh_entsize != sizeof (Elf_External_Versym))
goto fail;
elf_dynversym (abfd) = shindex;
elf_tdata (abfd)->dynversym_hdr = *hdr;
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
goto success;
case SHT_GNU_verneed:
elf_dynverref (abfd) = shindex;
elf_tdata (abfd)->dynverref_hdr = *hdr;
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
goto success;
case SHT_SHLIB:
goto success;
case SHT_GROUP:
if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE))
goto fail;
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
goto fail;
if (hdr->contents != NULL)
{
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
unsigned int n_elt = hdr->sh_size / sizeof (* idx);
asection *s;
if (n_elt == 0)
goto fail;
if (idx->flags & GRP_COMDAT)
hdr->bfd_section->flags
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
/* We try to keep the same section order as it comes in. */
idx += n_elt;
while (--n_elt != 0)
{
--idx;
if (idx->shdr != NULL
&& (s = idx->shdr->bfd_section) != NULL
&& elf_next_in_group (s) != NULL)
{
elf_next_in_group (hdr->bfd_section) = s;
break;
}
}
}
goto success;
default:
/* Possibly an attributes section. */
if (hdr->sh_type == SHT_GNU_ATTRIBUTES
|| hdr->sh_type == bed->obj_attrs_section_type)
{
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
goto fail;
_bfd_elf_parse_attributes (abfd, hdr);
goto success;
}
/* Check for any processor-specific section types. */
if (bed->elf_backend_section_from_shdr (abfd, hdr, name, shindex))
goto success;
if (hdr->sh_type >= SHT_LOUSER && hdr->sh_type <= SHT_HIUSER)
{
if ((hdr->sh_flags & SHF_ALLOC) != 0)
/* FIXME: How to properly handle allocated section reserved
for applications? */
(*_bfd_error_handler)
(_("%B: don't know how to handle allocated, application "
"specific section `%s' [0x%8x]"),
abfd, name, hdr->sh_type);
else
{
/* Allow sections reserved for applications. */
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
goto success;
}
}
else if (hdr->sh_type >= SHT_LOPROC
&& hdr->sh_type <= SHT_HIPROC)
/* FIXME: We should handle this section. */
(*_bfd_error_handler)
(_("%B: don't know how to handle processor specific section "
"`%s' [0x%8x]"),
abfd, name, hdr->sh_type);
else if (hdr->sh_type >= SHT_LOOS && hdr->sh_type <= SHT_HIOS)
{
/* Unrecognised OS-specific sections. */
if ((hdr->sh_flags & SHF_OS_NONCONFORMING) != 0)
/* SHF_OS_NONCONFORMING indicates that special knowledge is
required to correctly process the section and the file should
be rejected with an error message. */
(*_bfd_error_handler)
(_("%B: don't know how to handle OS specific section "
"`%s' [0x%8x]"),
abfd, name, hdr->sh_type);
else
{
/* Otherwise it should be processed. */
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
goto success;
}
}
else
/* FIXME: We should handle this section. */
(*_bfd_error_handler)
(_("%B: don't know how to handle section `%s' [0x%8x]"),
abfd, name, hdr->sh_type);
goto fail;
}
fail:
ret = FALSE;
success:
if (sections_being_created && sections_being_created_abfd == abfd)
sections_being_created [shindex] = FALSE;
if (-- nesting == 0)
{
sections_being_created = NULL;
sections_being_created_abfd = abfd;
}
return ret;
}
/* Return the local symbol specified by ABFD, R_SYMNDX. */
Elf_Internal_Sym *
bfd_sym_from_r_symndx (struct sym_cache *cache,
bfd *abfd,
unsigned long r_symndx)
{
unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
if (cache->abfd != abfd || cache->indx[ent] != r_symndx)
{
Elf_Internal_Shdr *symtab_hdr;
unsigned char esym[sizeof (Elf64_External_Sym)];
Elf_External_Sym_Shndx eshndx;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
&cache->sym[ent], esym, &eshndx) == NULL)
return NULL;
if (cache->abfd != abfd)
{
memset (cache->indx, -1, sizeof (cache->indx));
cache->abfd = abfd;
}
cache->indx[ent] = r_symndx;
}
return &cache->sym[ent];
}
/* Given an ELF section number, retrieve the corresponding BFD
section. */
asection *
bfd_section_from_elf_index (bfd *abfd, unsigned int sec_index)
{
if (sec_index >= elf_numsections (abfd))
return NULL;
return elf_elfsections (abfd)[sec_index]->bfd_section;
}
static const struct bfd_elf_special_section special_sections_b[] =
{
{ STRING_COMMA_LEN (".bss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_c[] =
{
{ STRING_COMMA_LEN (".comment"), 0, SHT_PROGBITS, 0 },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_d[] =
{
{ STRING_COMMA_LEN (".data"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".data1"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
/* There are more DWARF sections than these, but they needn't be added here
unless you have to cope with broken compilers that don't emit section
attributes or you want to help the user writing assembler. */
{ STRING_COMMA_LEN (".debug"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".debug_line"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".debug_info"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".debug_abbrev"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".debug_aranges"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".dynamic"), 0, SHT_DYNAMIC, SHF_ALLOC },
{ STRING_COMMA_LEN (".dynstr"), 0, SHT_STRTAB, SHF_ALLOC },
{ STRING_COMMA_LEN (".dynsym"), 0, SHT_DYNSYM, SHF_ALLOC },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_f[] =
{
{ STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
{ STRING_COMMA_LEN (".fini_array"), 0, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_g[] =
{
{ STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.lto_"), -1, SHT_PROGBITS, SHF_EXCLUDE },
{ STRING_COMMA_LEN (".got"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.version"), 0, SHT_GNU_versym, 0 },
{ STRING_COMMA_LEN (".gnu.version_d"), 0, SHT_GNU_verdef, 0 },
{ STRING_COMMA_LEN (".gnu.version_r"), 0, SHT_GNU_verneed, 0 },
{ STRING_COMMA_LEN (".gnu.liblist"), 0, SHT_GNU_LIBLIST, SHF_ALLOC },
{ STRING_COMMA_LEN (".gnu.conflict"), 0, SHT_RELA, SHF_ALLOC },
{ STRING_COMMA_LEN (".gnu.hash"), 0, SHT_GNU_HASH, SHF_ALLOC },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_h[] =
{
{ STRING_COMMA_LEN (".hash"), 0, SHT_HASH, SHF_ALLOC },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_i[] =
{
{ STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
{ STRING_COMMA_LEN (".init_array"), 0, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".interp"), 0, SHT_PROGBITS, 0 },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_l[] =
{
{ STRING_COMMA_LEN (".line"), 0, SHT_PROGBITS, 0 },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_n[] =
{
{ STRING_COMMA_LEN (".note.GNU-stack"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".note"), -1, SHT_NOTE, 0 },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_p[] =
{
{ STRING_COMMA_LEN (".preinit_array"), 0, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_r[] =
{
{ STRING_COMMA_LEN (".rodata"), -2, SHT_PROGBITS, SHF_ALLOC },
{ STRING_COMMA_LEN (".rodata1"), 0, SHT_PROGBITS, SHF_ALLOC },
{ STRING_COMMA_LEN (".rela"), -1, SHT_RELA, 0 },
{ STRING_COMMA_LEN (".rel"), -1, SHT_REL, 0 },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_s[] =
{
{ STRING_COMMA_LEN (".shstrtab"), 0, SHT_STRTAB, 0 },
{ STRING_COMMA_LEN (".strtab"), 0, SHT_STRTAB, 0 },
{ STRING_COMMA_LEN (".symtab"), 0, SHT_SYMTAB, 0 },
/* See struct bfd_elf_special_section declaration for the semantics of
this special case where .prefix_length != strlen (.prefix). */
{ ".stabstr", 5, 3, SHT_STRTAB, 0 },
{ NULL, 0, 0, 0, 0</