blob: e8e37eaa95b792a5c060ff05a444cefaebf92535 [file] [log] [blame]
/* ELF executable support for BFD.
Copyright (C) 1993-2021 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 <limits.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 bool assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
static bool swap_out_syms (bfd *, struct elf_strtab_hash **, int,
struct bfd_link_info *);
static bool elf_parse_notes (bfd *abfd, char *buf, size_t size,
file_ptr offset, size_t align);
/* 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. */
bool
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;
}
bool
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);
}
bool
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;
}
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_alloc_and_read (abfd, shstrtabsize + 1,
shstrtabsize)) == 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. */
/* xgettext:c-format */
_bfd_error_handler (_("%pB: 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;
}
else
{
/* PR 24273: The string section's contents may have already
been loaded elsewhere, eg because a corrupt file has the
string section index in the ELF header pointing at a group
section. So be paranoid, and test that the last byte of
the section is zero. */
if (hdr->sh_size == 0 || hdr->contents[hdr->sh_size - 1] != 0)
return NULL;
}
if (strindex >= hdr->sh_size)
{
unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx;
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: invalid string offset %u >= %" PRIu64 " for section `%s'"),
abfd, strindex, (uint64_t) 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;
size_t 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;
if (_bfd_mul_overflow (symcount, extsym_size, &amt))
{
bfd_set_error (bfd_error_file_too_big);
intsym_buf = NULL;
goto out;
}
pos = symtab_hdr->sh_offset + symoffset * extsym_size;
if (extsym_buf == NULL)
{
alloc_ext = bfd_malloc (amt);
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
{
if (_bfd_mul_overflow (symcount, sizeof (Elf_External_Sym_Shndx), &amt))
{
bfd_set_error (bfd_error_file_too_big);
intsym_buf = NULL;
goto out;
}
pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
if (extshndx_buf == NULL)
{
alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
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)
{
if (_bfd_mul_overflow (symcount, sizeof (Elf_Internal_Sym), &amt))
{
bfd_set_error (bfd_error_file_too_big);
goto out;
}
alloc_intsym = (Elf_Internal_Sym *) bfd_malloc (amt);
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;
/* xgettext:c-format */
_bfd_error_handler (_("%pB symbol number %lu references"
" nonexistent SHT_SYMTAB_SHNDX section"),
ibfd, (unsigned long) symoffset);
free (alloc_intsym);
intsym_buf = NULL;
goto out;
}
out:
free (alloc_ext);
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 (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 bool
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;
elf_tdata (abfd)->group_sect_ptr = NULL;
}
else
{
/* We keep a list of elf section headers for group sections,
so we can find them quickly. */
size_t amt;
elf_tdata (abfd)->num_group = num_group;
amt = num_group * sizeof (Elf_Internal_Shdr *);
elf_tdata (abfd)->group_sect_ptr
= (Elf_Internal_Shdr **) bfd_zalloc (abfd, amt);
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;
/* Make sure the group section has a BFD section
attached to it. */
if (!bfd_section_from_shdr (abfd, i))
return false;
/* 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 && sizeof (*dest) % 4 == 0);
shdr->contents = NULL;
if (_bfd_mul_overflow (shdr->sh_size,
sizeof (*dest) / 4, &amt)
|| bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
|| !(shdr->contents
= _bfd_alloc_and_read (abfd, amt, shdr->sh_size)))
{
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: invalid size field in group section"
" header: %#" PRIx64 ""),
abfd, (uint64_t) shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
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->shdr = NULL;
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)
{
dest->shdr = elf_elfsections (abfd)[idx];
/* PR binutils/23199: All sections in a
section group should be marked with
SHF_GROUP. But some tools generate
broken objects without SHF_GROUP. Fix
them up here. */
dest->shdr->sh_flags |= SHF_GROUP;
}
if (idx >= shnum
|| dest->shdr->sh_type == SHT_GROUP)
{
_bfd_error_handler
(_("%pB: invalid entry in SHT_GROUP section [%u]"),
abfd, i);
dest->shdr = NULL;
}
}
}
}
/* 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
(_("%pB: no valid group sections found"), abfd);
bfd_set_error (bfd_error_bad_value);
}
}
}
}
if (num_group != (unsigned) -1)
{
unsigned int search_offset = elf_tdata (abfd)->group_search_offset;
unsigned int j;
for (j = 0; j < num_group; j++)
{
/* Begin search from previous found group. */
unsigned i = (j + search_offset) % num_group;
Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
Elf_Internal_Group *idx;
bfd_size_type n_elt;
if (shdr == NULL)
continue;
idx = (Elf_Internal_Group *) shdr->contents;
if (idx == NULL || shdr->sh_size < 4)
{
/* See PR 21957 for a reproducer. */
/* xgettext:c-format */
_bfd_error_handler (_("%pB: group section '%pA' has no contents"),
abfd, shdr->bfd_section);
elf_tdata (abfd)->group_sect_ptr[i] = NULL;
bfd_set_error (bfd_error_bad_value);
return false;
}
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 ((++idx)->shdr != NULL
&& (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;
elf_tdata (abfd)->group_search_offset = i;
j = num_group - 1;
break;
}
}
}
if (elf_group_name (newsect) == NULL)
{
/* xgettext:c-format */
_bfd_error_handler (_("%pB: no group info for section '%pA'"),
abfd, newsect);
return false;
}
return true;
}
bool
_bfd_elf_setup_sections (bfd *abfd)
{
unsigned int i;
unsigned int num_group = elf_tdata (abfd)->num_group;
bool 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;
/* An sh_link value of 0 is now allowed. It indicates that linked
to section has already been discarded, but that the current
section has been retained for some other reason. This linking
section is still a candidate for later garbage collection
however. */
if (elfsec == 0)
{
elf_linked_to_section (s) = NULL;
}
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
/* xgettext:c-format */
(_("%pB: sh_link [%d] in section `%pA' is incorrect"),
s->owner, elfsec, s);
result = false;
}
elf_linked_to_section (s) = linksec;
}
}
else if (this_hdr->sh_type == SHT_GROUP
&& elf_next_in_group (s) == NULL)
{
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: SHT_GROUP section [index %d] has no SHF_GROUP sections"),
abfd, elf_section_data (s)->this_idx);
result = false;
}
}
/* 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
/* xgettext:c-format */
(_("%pB: 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)
{
++ idx;
if (idx->shdr == NULL)
continue;
else 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)
{
/* There are some unknown sections in the group. */
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: unknown type [%#x] section `%s' in group [%pA]"),
abfd,
idx->shdr->sh_type,
bfd_elf_string_from_elf_section (abfd,
(elf_elfheader (abfd)
->e_shstrndx),
idx->shdr->sh_name),
shdr->bfd_section);
result = false;
}
}
}
return result;
}
bool
bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
{
return elf_next_in_group (sec) != NULL;
}
const char *
bfd_elf_group_name (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
{
if (elf_sec_group (sec) != NULL)
return elf_group_name (sec);
return 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;
}
/* This a copy of lto_section defined in GCC (lto-streamer.h). */
struct lto_section
{
int16_t major_version;
int16_t minor_version;
unsigned char slim_object;
/* Flags is a private field that is not defined publicly. */
uint16_t flags;
};
/* Make a BFD section from an ELF section. We store a pointer to the
BFD section in the bfd_section field of the header. */
bool
_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;
unsigned int opb = bfd_octets_per_byte (abfd, NULL);
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;
flags = SEC_NO_FLAGS;
if (hdr->sh_type != SHT_NOBITS)
flags |= SEC_HAS_CONTENTS;
if (hdr->sh_type == SHT_GROUP)
flags |= SEC_GROUP;
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;
switch (elf_elfheader (abfd)->e_ident[EI_OSABI])
{
/* FIXME: We should not recognize SHF_GNU_MBIND for ELFOSABI_NONE,
but binutils as of 2019-07-23 did not set the EI_OSABI header
byte. */
case ELFOSABI_GNU:
case ELFOSABI_FREEBSD:
if ((hdr->sh_flags & SHF_GNU_RETAIN) != 0)
elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_retain;
/* Fall through */
case ELFOSABI_NONE:
if ((hdr->sh_flags & SHF_GNU_MBIND) != 0)
elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_mbind;
break;
}
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] == '.')
{
if (startswith (name, ".debug")
|| startswith (name, ".gnu.debuglto_.debug_")
|| startswith (name, ".gnu.linkonce.wi.")
|| startswith (name, ".zdebug"))
flags |= SEC_DEBUGGING | SEC_ELF_OCTETS;
else if (startswith (name, GNU_BUILD_ATTRS_SECTION_NAME)
|| startswith (name, ".note.gnu"))
{
flags |= SEC_ELF_OCTETS;
opb = 1;
}
else if (startswith (name, ".line")
|| startswith (name, ".stab")
|| strcmp (name, ".gdb_index") == 0)
flags |= SEC_DEBUGGING;
}
}
if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb)
|| !bfd_set_section_size (newsect, hdr->sh_size)
|| !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign)))
return false;
/* 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 (startswith (name, ".gnu.linkonce")
&& elf_next_in_group (newsect) == NULL)
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
if (!bfd_set_section_flags (newsect, flags))
return false;
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_section_flags)
if (!bed->elf_backend_section_flags (hdr))
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,
hdr->sh_offset, hdr->sh_addralign);
free (contents);
}
if ((newsect->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 ((newsect->flags & SEC_LOAD) == 0)
newsect->lma = (phdr->p_paddr
+ hdr->sh_addr - phdr->p_vaddr) / opb;
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) / opb;
/* 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 ((newsect->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;
unsigned int uncompressed_align_power;
bool compressed
= bfd_is_section_compressed_with_header (abfd, newsect,
&compression_header_size,
&uncompressed_size,
&uncompressed_align_power);
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
/* xgettext:c-format */
(_("%pB: unable to initialize compress status for section %s"),
abfd, name);
return false;
}
}
else
{
if (!bfd_init_section_decompress_status (abfd, newsect))
{
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: 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 (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;
}
/* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
section. */
if (startswith (name, ".gnu.lto_.lto."))
{
struct lto_section lsection;
if (bfd_get_section_contents (abfd, newsect, &lsection, 0,
sizeof (struct lto_section)))
abfd->lto_slim_object = lsection.slim_object;
}
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, or should call this function for relocatable output. */
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;
}
/* In some cases the relocation should be treated as output section
relative, as when linking ELF DWARF into PE COFF. Many ELF
targets lack section relative relocations and instead use
ordinary absolute relocations for references between DWARF
sections. That is arguably a bug in those targets but it happens
to work for the usual case of linking to non-loaded ELF debug
sections with VMAs forced to zero. PE COFF on the other hand
doesn't allow a section VMA of zero. */
if (output_bfd == NULL
&& !reloc_entry->howto->pc_relative
&& (symbol->section->flags & SEC_DEBUGGING) != 0
&& (input_section->flags & SEC_DEBUGGING) != 0)
reloc_entry->addend -= symbol->section->output_section->vma;
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 bool
section_match (const Elf_Internal_Shdr * a,
const Elf_Internal_Shdr * b)
{
if (a->sh_type != b->sh_type
|| ((a->sh_flags ^ b->sh_flags) & ~SHF_INFO_LINK) != 0
|| a->sh_addralign != b->sh_addralign
|| a->sh_entsize != b->sh_entsize)
return false;
if (a->sh_type == SHT_SYMTAB
|| a->sh_type == SHT_STRTAB)
return true;
return a->sh_size == b->sh_size;
}
/* 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;
BFD_ASSERT (iheader != NULL);
/* See PR 20922 for a reproducer of the NULL test. */
if (hint < elf_numsections (obfd)
&& oheaders[hint] != NULL
&& section_match (oheaders[hint], iheader))
return hint;
for (i = 1; i < elf_numsections (obfd); i++)
{
Elf_Internal_Shdr * oheader = oheaders[i];
if (oheader == NULL)
continue;
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 bool
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);
bool 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 (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)
{
/* See PR 20931 for a reproducer. */
if (iheader->sh_link >= elf_numsections (ibfd))
{
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: invalid sh_link field (%d) in section number %d"),
ibfd, iheader->sh_link, secnum);
return false;
}
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
/* xgettext:c-format */
(_("%pB: 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
/* xgettext:c-format */
(_("%pB: 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. */
bool
_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. */
(void) 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. */
bool
_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];
bool 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, "%#" BFD_VMA_FMT "x", 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:
free (dynbuf);
return false;
}
/* Get version name. If BASE_P is TRUE, return "Base" for VER_FLG_BASE
and return symbol version for symbol version itself. */
const char *
_bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
bool base_p,
bool *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
&& (vernum > elf_tdata (abfd)->cverdefs
|| (elf_tdata (abfd)->verdef[0].vd_flags
== VER_FLG_BASE)))
version_string = base_p ? "Base" : "";
else if (vernum <= elf_tdata (abfd)->cverdefs)
{
const char *nodename
= elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
version_string = "";
if (base_p
|| nodename == NULL
|| symbol->name == NULL
|| strcmp (symbol->name, nodename) != 0)
version_string = nodename;
}
else
{
Elf_Internal_Verneed *t;
version_string = _("<corrupt>");
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)
{
*hidden = true;
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, " %x", 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;
bool 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,
true,
&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. */
bool
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;
bool ret = true;
if (shindex >= elf_numsections (abfd))
return false;
/* PR17512: A corrupt ELF binary might contain a loop of sections via
sh_link or sh_info. Detect this here, by refusing to load a
section that we are already in the process of loading. */
if (elf_tdata (abfd)->being_created[shindex])
{
_bfd_error_handler
(_("%pB: warning: loop in section dependencies detected"), abfd);
return false;
}
elf_tdata (abfd)->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
/* xgettext:c-format */
(_("%pB: 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
/* xgettext:c-format */
(_("%pB: 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
/* xgettext:c-format */
(_("%pB: invalid link %u 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 is an alloc section in an executable or shared
library, or the 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 (((abfd->flags & (DYNAMIC | EXEC_P)) != 0
&& (hdr->sh_flags & SHF_ALLOC) != 0)
|| hdr->sh_link == SHN_UNDEF
|| hdr->sh_link != elf_onesymtab (abfd)
|| 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.
Also see PR 24456, for a file which deliberately has two reloc
sections. */
if (*p_hdr != NULL)
{
if (!bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
{
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: warning: secondary relocation section '%s' "
"for section %pA found - ignoring"),
abfd, name, target_sect);
}
else
esdt->has_secondary_relocs = true;
goto success;
}
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)
* bed->s->int_rels_per_ext_rel);
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;
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
/* xgettext:c-format */
(_("%pB: unknown type [%#x] section `%s'"),
abfd, hdr->sh_type, name);
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
/* xgettext:c-format */
(_("%pB: unknown type [%#x] section `%s'"),
abfd, hdr->sh_type, name);
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
/* xgettext:c-format */
(_("%pB: unknown type [%#x] section `%s'"),
abfd, hdr->sh_type, name);
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
/* xgettext:c-format */
(_("%pB: unknown type [%#x] section `%s'"),
abfd, hdr->sh_type, name);
goto fail;
}
fail:
ret = false;
success:
elf_tdata (abfd)->being_created[shindex] = false;
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 },
{ STRING_COMMA_LEN (".ctf"), 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"), -2, 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.linkonce.n"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.linkonce.p"), -2, SHT_PROGBITS, 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"), -2, 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 (".noinit"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ 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 (".persistent.bss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".persistent"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".preinit_array"), -2, 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 }
};
static const struct bfd_elf_special_section special_sections_t[] =
{
{ STRING_COMMA_LEN (".text"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
{ STRING_COMMA_LEN (".tbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
{ STRING_COMMA_LEN (".tdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_z[] =
{
{ STRING_COMMA_LEN (".zdebug_line"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".zdebug_info"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".zdebug_abbrev"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".zdebug_aranges"), 0, SHT_PROGBITS, 0 },
{ NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section * const special_sections[] =
{
special_sections_b, /* 'b' */
special_sections_c, /* 'c' */
special_sections_d, /* 'd' */
NULL, /* 'e' */
special_sections_f, /* 'f' */
special_sections_g, /* 'g' */
special_sections_h, /* 'h' */
special_sections_i, /* 'i' */
NULL, /* 'j' */
NULL, /* 'k' */
special_sections_l, /* 'l' */
NULL, /* 'm' */
special_sections_n, /* 'n' */
NULL, /* 'o' */
special_sections_p, /* 'p' */
NULL, /* 'q' */
special_sections_r, /* 'r' */
special_sections_s, /* 's' */
special_sections_t, /* 't' */
NULL, /* 'u' */
NULL, /* 'v' */
NULL, /* 'w' */
NULL, /* 'x' */
NULL, /* 'y' */
special_sections_z /* 'z' */
};
const struct bfd_elf_special_section *
_bfd_elf_get_special_section (const char *name,
const struct bfd_elf_special_section *spec,
unsigned int rela)
{
int i;
int len;
len = strlen (name);
for (i = 0; spec[i].prefix != NULL; i++)
{
int suffix_len;
int prefix_len = spec[i].prefix_length;
if (len < prefix_len)
continue;
if (memcmp (name, spec[i].prefix, prefix_len) != 0)
continue;
suffix_len = spec[i].suffix_length;
if (suffix_len <= 0)
{
if (name[prefix_len] != 0)
{
if (suffix_len == 0)
continue;
if (name[prefix_len] != '.'
&& (suffix_len == -2
|| (rela && spec[i].type == SHT_REL)))
continue;
}
}
else
{
if (len < prefix_len + suffix_len)
continue;
if (memcmp (name + len - suffix_len,
spec[i].prefix + prefix_len,
suffix_len) != 0)
continue;
}
return &spec[i];
}
return NULL;
}
const struct bfd_elf_special_section *
_bfd_elf_get_sec_type_attr (bfd *abfd, asection *sec)
{
int i;
const struct bfd_elf_special_section *spec;
const struct elf_backend_data *bed;
/* See if this is one of the special sections. */
if (sec->name == NULL)
return NULL;
bed = get_elf_backend_data (abfd);
spec = bed->special_sections;
if (spec)
{
spec = _bfd_elf_get_special_section (sec->name,
bed->special_sections,
sec->use_rela_p);
if (spec != NULL)
return spec;
}
if (sec->name[0] != '.')
return NULL;
i = sec->name[1] - 'b';
if (i < 0 || i > 'z' - 'b')
return NULL;
spec = special_sections[i];
if (spec == NULL)
return NULL;
return _bfd_elf_get_special_section (sec->name, spec, sec->use_rela_p);
}
bool
_bfd_elf_new_section_hook (bfd *abfd, asection *sec)
{
struct bfd_elf_section_data *sdata;
const struct elf_backend_data *bed;
const struct bfd_elf_special_section *ssect;
sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
if (sdata == NULL)
{
sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd,
sizeof (*sdata));
if (sdata == NULL)
return false;
sec->used_by_bfd = sdata;
}
/* Indicate whether or not this section should use RELA relocations. */
bed = get_elf_backend_data (abfd);
sec->use_rela_p = bed->default_use_rela_p;
/* Set up ELF section type and flags for newly created sections, if
there is an ABI mandated section. */
ssect = (*bed->get_sec_type_attr) (abfd, sec);
if (ssect != NULL)
{
elf_section_type (sec) = ssect->type;
elf_section_flags (sec) = ssect->attr;
}
return _bfd_generic_new_section_hook (abfd, sec);
}
/* Create a new bfd section from an ELF program header.
Since program segments have no names, we generate a synthetic name
of the form segment<NUM>, where NUM is generally the index in the
program header table. For segments that are split (see below) we
generate the names segment<NUM>a and segment<NUM>b.
Note that some program segments may have a file size that is different than
(less than) the memory size. All this means is that at execution the
system must allocate the amount of memory specified by the memory size,