diff options
Diffstat (limited to 'configure.ac')
0 files changed, 0 insertions, 0 deletions
![]() |
index : riscv-gnu-toolchain/gdb.git | |
Unnamed repository; edit this file 'description' to name the repository. | root |
aboutsummaryrefslogtreecommitdiff |
/* ELF executable support for BFD.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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"
#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 bfd_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;
elf_program_header_size (abfd) = (bfd_size_type) -1;
return TRUE;
}
bfd_boolean
bfd_elf_make_generic_object (bfd *abfd)
{
return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
GENERIC_ELF_DATA);
}
bfd_boolean
bfd_elf_mkcorefile (bfd *abfd)
{
/* I think this can be done just like an object file. */
return bfd_elf_make_generic_object (abfd);
}
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
|| (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
|| bfd_seek (abfd, offset, SEEK_SET) != 0)
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);
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
&& 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 (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr)
shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
/* 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 = 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 = 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) \
( (shdr)->sh_type == SHT_GROUP \
&& (shdr)->sh_size >= (2 * GRP_ENTRY_SIZE) \
&& (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))
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))
{
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);
return FALSE;
}
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))
return FALSE;
/* 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];
}
}
}
}
}
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 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 = (Elf_Internal_Group *) shdr->contents;
unsigned int 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;
}
/* 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)
{
BFD_ASSERT (strcmp (name,
bfd_get_section_name (abfd, hdr->bfd_section)) == 0);
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 ((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. */
static const struct
{
const char *name;
int len;
} debug_sections [] =
{
{ STRING_COMMA_LEN ("debug") }, /* 'd' */
{ NULL, 0 }, /* 'e' */
{ NULL, 0 }, /* 'f' */
{ STRING_COMMA_LEN ("gnu.linkonce.wi.") }, /* 'g' */
{ NULL, 0 }, /* 'h' */
{ NULL, 0 }, /* 'i' */
{ NULL, 0 }, /* 'j' */
{ NULL, 0 }, /* 'k' */
{ STRING_COMMA_LEN ("line") }, /* 'l' */
{ NULL, 0 }, /* 'm' */
{ NULL, 0 }, /* 'n' */
{ NULL, 0 }, /* 'o' */
{ NULL, 0 }, /* 'p' */
{ NULL, 0 }, /* 'q' */
{ NULL, 0 }, /* 'r' */
{ STRING_COMMA_LEN ("stab") }, /* 's' */
{ NULL, 0 }, /* 't' */
{ NULL, 0 }, /* 'u' */
{ NULL, 0 }, /* 'v' */
{ NULL, 0 }, /* 'w' */
{ NULL, 0 }, /* 'x' */
{ NULL, 0 }, /* 'y' */
{ STRING_COMMA_LEN ("zdebug") } /* 'z' */
};
if (name [0] == '.')
{
int i = name [1] - 'd';
if (i >= 0
&& i < (int) ARRAY_SIZE (debug_sections)
&& debug_sections [i].name != NULL
&& strncmp (&name [1], debug_sections [i].name,
debug_sections [i].len) == 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
&& ELF_IS_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;
}
}
}
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;
}
/* 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)
{
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
BFD_ASSERT (!elf_flags_init (obfd)
|| (elf_elfheader (obfd)->e_flags
== elf_elfheader (ibfd)->e_flags));
elf_gp (obfd) = elf_gp (ibfd);
elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
elf_flags_init (obfd) = TRUE;
/* Copy object attributes. */
_bfd_elf_copy_obj_attributes (ibfd, obfd);
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;
extdynend = extdyn + s->size;
for (; extdyn < extdynend; 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;
}
/* 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;
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. */
if (elf_tdata (abfd)->dynversym_section != 0
&& (elf_tdata (abfd)->dynverdef_section != 0
|| elf_tdata (abfd)->dynverref_section != 0))
{
unsigned int vernum;
const char *version_string;
vernum = ((elf_symbol_type *) symbol)->version & 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;
}
}
}
}
if ((((elf_symbol_type *) symbol)->version & VERSYM_HIDDEN) == 0)
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;
}
}
/* Allocate an ELF string table--force the first byte to be zero. */
struct bfd_strtab_hash *
_bfd_elf_stringtab_init (void)
{
struct bfd_strtab_hash *ret;
ret = _bfd_stringtab_init ();
if (ret != NULL)
{
bfd_size_type loc;
loc = _bfd_stringtab_add (ret, "", TRUE, FALSE);
BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1);
if (loc == (bfd_size_type) -1)
{
_bfd_stringtab_free (ret);
ret = NULL;
}
}
return ret;
}
/* 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;
if (shindex >= elf_numsections (abfd))
return FALSE;
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)
return FALSE;
bed = get_elf_backend_data (abfd);
switch (hdr->sh_type)
{
case SHT_NULL:
/* Inactive section. Throw it away. */
return TRUE;
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. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_DYNAMIC: /* Dynamic linking information. */
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
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:
return FALSE;
}
}
else if (elf_elfsections (abfd)[hdr->sh_link] == NULL)
return FALSE;
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;
}
}
}
}
break;
case SHT_SYMTAB: /* A symbol table */
if (elf_onesymtab (abfd) == shindex)
return TRUE;
if (hdr->sh_entsize != bed->s->sizeof_sym)
return FALSE;
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
return FALSE;
BFD_ASSERT (elf_onesymtab (abfd) == 0);
elf_onesymtab (abfd) = shindex;
elf_tdata (abfd)->symtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr;
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))
return FALSE;
/* 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. */
if (elf_elfsections (abfd)[elf_symtab_shndx (abfd)]->sh_link != shindex)
{
unsigned int i, num_sec;
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)
return bfd_section_from_shdr (abfd, i);
}
return TRUE;
case SHT_DYNSYM: /* A dynamic symbol table */
if (elf_dynsymtab (abfd) == shindex)
return TRUE;
if (hdr->sh_entsize != bed->s->sizeof_sym)
return FALSE;
BFD_ASSERT (elf_dynsymtab (abfd) == 0);
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. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections */
if (elf_symtab_shndx (abfd) == shindex)
return TRUE;
BFD_ASSERT (elf_symtab_shndx (abfd) == 0);
elf_symtab_shndx (abfd) = shindex;
elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
return TRUE;
case SHT_STRTAB: /* A string table */
if (hdr->bfd_section != NULL)
return TRUE;
if (ehdr->e_shstrndx == shindex)
{
elf_tdata (abfd)->shstrtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
return TRUE;
}
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;
return TRUE;
}
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. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
}
/* 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)
return FALSE;
if (! bfd_section_from_shdr (abfd, i))
return FALSE;
if (elf_onesymtab (abfd) == i)
goto symtab_strtab;
if (elf_dynsymtab (abfd) == i)
goto dynsymtab_strtab;
}
}
}
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_REL:
case SHT_RELA:
/* *These* do a lot of work -- but build no sections! */
{
asection *target_sect;
Elf_Internal_Shdr *hdr2;
unsigned int num_sec = elf_numsections (abfd);
if (hdr->sh_entsize
!= (bfd_size_type) (hdr->sh_type == SHT_REL
? bed->s->sizeof_rel : bed->s->sizeof_rela))
return FALSE;
/* 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));
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
}
/* 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))
return FALSE;
/* 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)
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
if (! bfd_section_from_shdr (abfd, hdr->sh_info))
return FALSE;
target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
if (target_sect == NULL)
return FALSE;
if ((target_sect->flags & SEC_RELOC) == 0
|| target_sect->reloc_count == 0)
hdr2 = &elf_section_data (target_sect)->rel_hdr;
else
{
bfd_size_type amt;
BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
amt = sizeof (*hdr2);
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
if (hdr2 == NULL)
return FALSE;
elf_section_data (target_sect)->rel_hdr2 = hdr2;
}
*hdr2 = *hdr;
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)
target_sect->use_rela_p = hdr->sh_type == SHT_RELA;
abfd->flags |= HAS_RELOC;
return TRUE;
}
case SHT_GNU_verdef:
elf_dynverdef (abfd) = shindex;
elf_tdata (abfd)->dynverdef_hdr = *hdr;
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_GNU_versym:
if (hdr->sh_entsize != sizeof (Elf_External_Versym))
return FALSE;
elf_dynversym (abfd) = shindex;
elf_tdata (abfd)->dynversym_hdr = *hdr;
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_GNU_verneed:
elf_dynverref (abfd) = shindex;
elf_tdata (abfd)->dynverref_hdr = *hdr;
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_SHLIB:
return TRUE;
case SHT_GROUP:
if (! IS_VALID_GROUP_SECTION_HEADER (hdr))
return FALSE;
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
if (hdr->contents != NULL)
{
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE;
asection *s;
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;
}
}
}
break;
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))
return FALSE;
_bfd_elf_parse_attributes (abfd, hdr);
return TRUE;
}
/* Check for any processor-specific section types. */
if (bed->elf_backend_section_from_shdr (abfd, hdr, name, shindex))
return TRUE;
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. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
}
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. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
}
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);
return FALSE;
}
return TRUE;
}
/* 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 },
{ 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 (".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 }
};
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 *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);
}
bfd_boolean
_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;
/* When we read a file, we don't need to set ELF section type and
flags. They will be overridden in _bfd_elf_make_section_from_shdr
anyway. We will set ELF section type and flags for all linker
created sections. If user specifies BFD section flags, we will
set ELF section type and flags based on BFD section flags in
elf_fake_sections. */
if ((!sec->flags && abfd->direction != read_direction)
|| (sec->flags & SEC_LINKER_CREATED) != 0)
{
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,
but only initialize it with the first "file size" bytes read from the
file. This would occur for example, with program segments consisting
of combined data+bss.
To handle the above situation, this routine generates TWO bfd sections
for the single program segment. The first has the length specified by
the file size of the segment, and the second has the length specified
by the difference between the two sizes. In effect, the segment is split
into its initialized and uninitialized parts.
*/
bfd_boolean
_bfd_elf_make_section_from_phdr (bfd *abfd,
Elf_Internal_Phdr *hdr,
int hdr_index,
const char *type_name)
{
asection *newsect;
char *name;
char namebuf[64];
size_t len;
int split;
split = ((hdr->p_memsz > 0)
&& (hdr->p_filesz > 0)
&& (hdr->p_memsz > hdr->p_filesz));
if (hdr->p_filesz > 0)
{
sprintf (namebuf, "%s%d%s", type_name, hdr_index, split ? "a" : "");
len = strlen (namebuf) + 1;
name = (char *) bfd_alloc (abfd, len);
if (!name)
return FALSE;
memcpy (name, namebuf, len);
newsect = bfd_make_section (abfd, name);
if (newsect == NULL)
return FALSE;
newsect->vma = hdr->p_vaddr;
newsect->lma = hdr->p_paddr;
newsect->size = hdr->p_filesz;
newsect->filepos = hdr->p_offset;
newsect->flags |= SEC_HAS_CONTENTS;
newsect->alignment_power = bfd_log2 (hdr->p_align);
if (hdr->p_type == PT_LOAD)
{
newsect->flags |= SEC_ALLOC;
newsect->flags |= SEC_LOAD;
if (hdr->p_flags & PF_X)
{
/* FIXME: all we known is that it has execute PERMISSION,
may be data. */
newsect->flags |= SEC_CODE;
}
}
if (!(hdr->p_flags & PF_W))
{
newsect->flags |= SEC_READONLY;
}
}
if (hdr->p_memsz > hdr->p_filesz)
{
bfd_vma align;
sprintf (namebuf, "%s%d%s", type_name, hdr_index, split ? "b" : "");
len = strlen (namebuf) + 1;
name = (char *) bfd_alloc (abfd, len);
if (!name)
return FALSE;
memcpy (name, namebuf, len);
newsect = bfd_make_section (abfd, name);
if (newsect == NULL)
return FALSE;
newsect->vma = hdr->p_vaddr + hdr->p_filesz;
newsect->lma = hdr->p_paddr + hdr->p_filesz;
newsect->size = hdr->p_memsz - hdr->p_filesz;
newsect->filepos = hdr->p_offset + hdr->p_filesz;
align = newsect->vma & -newsect->vma;
if (align == 0 || align > hdr->p_align)
align = hdr->p_align;
newsect->alignment_power = bfd_log2 (align);
if (hdr->p_type == PT_LOAD)
{
/* Hack for gdb. Segments that have not been modified do
not have their contents written to a core file, on the
assumption that a debugger can find the contents in the
executable. We flag this case by setting the fake
section size to zero. Note that "real" bss sections will
always have their contents dumped to the core file. */
if (bfd_get_format (abfd) == bfd_core)
newsect->size = 0;
newsect->flags |= SEC_ALLOC;
if (hdr->p_flags & PF_X)
newsect->flags |= SEC_CODE;
}
if (!(hdr->p_flags & PF_W))
newsect->flags |= SEC_READONLY;
}
return TRUE;
}
bfd_boolean
bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
{
const struct elf_backend_data *bed;
switch (hdr->p_type)
{
case PT_NULL:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "null");
case PT_LOAD:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "load");
case PT_DYNAMIC:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "dynamic");
case PT_INTERP:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "interp");
case PT_NOTE:
if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "note"))
return FALSE;
if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
return FALSE;
return TRUE;
case PT_SHLIB:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "shlib");
case PT_PHDR:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "phdr");
case PT_GNU_EH_FRAME:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index,
"eh_frame_hdr");
case PT_GNU_STACK:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "stack");
case PT_GNU_RELRO:
return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "relro");
default:
/* Check for any processor-specific program segment types. */
bed = get_elf_backend_data (abfd);
return bed->elf_backend_section_from_phdr (abfd, hdr, hdr_index, "proc");
}
}
/* Initialize REL_HDR, the section-header for new section, containing
relocations against ASECT. If USE_RELA_P is TRUE, we use RELA
relocations; otherwise, we use REL relocations. */
bfd_boolean
_bfd_elf_init_reloc_shdr (bfd *abfd,
Elf_Internal_Shdr *rel_hdr,
asection *asect,
bfd_boolean use_rela_p)
{
char *name;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_size_type amt = sizeof ".rela" + strlen (asect->name);
name = (char *) bfd_alloc (abfd, amt);
if (name == NULL)
return FALSE;
sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
rel_hdr->sh_name =
(unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
FALSE);
if (rel_hdr->sh_name == (unsigned int) -1)
return FALSE;
rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
rel_hdr->sh_entsize = (use_rela_p
? bed->s->sizeof_rela
: bed->s->sizeof_rel);
rel_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
rel_hdr->sh_flags = 0;
rel_hdr->sh_addr = 0;
rel_hdr->sh_size = 0;
rel_hdr->sh_offset = 0;
return TRUE;
}
/* Return the default section type based on the passed in section flags. */
int
bfd_elf_get_default_section_type (flagword flags)
{
if ((flags & SEC_ALLOC) != 0
&& ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0
|| (flags & SEC_NEVER_LOAD) != 0))
return SHT_NOBITS;
return SHT_PROGBITS;
}
/* Set up an ELF internal section header for a section. */
static void
elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
Elf_Internal_Shdr *this_hdr;
unsigned int sh_type;
if (*failedptr)
{
/* We already failed; just get out of the bfd_map_over_sections
loop. */
return;
}
this_hdr = &elf_section_data (asect)->this_hdr;
this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
asect->name, FALSE);
if (this_hdr->sh_name == (unsigned int) -1)
{
*failedptr = TRUE;
return;
}
/* Don't clear sh_flags. Assembler may set additional bits. */
if ((asect->flags & SEC_ALLOC) != 0
|| asect->user_set_vma)
this_hdr->sh_addr = asect->vma;
else
this_hdr->sh_addr = 0;
this_hdr->sh_offset = 0;
this_hdr->sh_size = asect->size;
this_hdr->sh_link = 0;
this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
/* The sh_entsize and sh_info fields may have been set already by
copy_private_section_data. */
this_hdr->bfd_section = asect;
this_hdr->contents = NULL;
/* If the section type is unspecified, we set it based on
asect->flags. */
if ((asect->flags & SEC_GROUP) != 0)
sh_type = SHT_GROUP;
else
sh_type = bfd_elf_get_default_section_type (asect->flags);
if (this_hdr->sh_type == SHT_NULL)
this_hdr->sh_type = sh_type;
else if (this_hdr->sh_type == SHT_NOBITS
&& sh_type == SHT_PROGBITS
&& (asect->flags & SEC_ALLOC) != 0)
{
/* Warn if we are changing a NOBITS section to PROGBITS, but
allow the link to proceed. This can happen when users link
non-bss input sections to bss output sections, or emit data
to a bss output section via a linker script. */
(*_bfd_error_handler)
(_("warning: section `%A' type changed to PROGBITS"), asect);
this_hdr->sh_type = sh_type;
}
switch (this_hdr->sh_type)
{
default:
break;
case SHT_STRTAB:
case SHT_INIT_ARRAY:
case SHT_FINI_ARRAY:
case SHT_PREINIT_ARRAY:
case SHT_NOTE:
case SHT_NOBITS:
case SHT_PROGBITS:
break;
case SHT_HASH:
this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
break;
case SHT_DYNSYM:
this_hdr->sh_entsize = bed->s->sizeof_sym;
break;
case SHT_DYNAMIC:
this_hdr->sh_entsize = bed->s->sizeof_dyn;
break;
case SHT_RELA:
if (get_elf_backend_data (abfd)->may_use_rela_p)
this_hdr->sh_entsize = bed->s->sizeof_rela;
break;
case SHT_REL:
if (get_elf_backend_data (abfd)->may_use_rel_p)
this_hdr->sh_entsize = bed->s->sizeof_rel;
break;
case SHT_GNU_versym:
this_hdr->sh_entsize = sizeof (Elf_External_Versym);
break;
case SHT_GNU_verdef:
this_hdr->sh_entsize = 0;
/* objcopy or strip will copy over sh_info, but may not set
cverdefs. The linker will set cverdefs, but sh_info will be
zero. */
if (this_hdr->sh_info == 0)
this_hdr->sh_info = elf_tdata (abfd)->cverdefs;
else
BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverdefs);
break;
case SHT_GNU_verneed:
this_hdr->sh_entsize = 0;
/* objcopy or strip will copy over sh_info, but may not set
cverrefs. The linker will set cverrefs, but sh_info will be
zero. */
if (this_hdr->sh_info == 0)
this_hdr->sh_info = elf_tdata (abfd)->cverrefs;
else
BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
break;
case SHT_GROUP:
this_hdr->sh_entsize = GRP_ENTRY_SIZE;
break;
case SHT_GNU_HASH:
this_hdr->sh_entsize = bed->s->arch_size == 64 ? 0 : 4;
break;
}
if ((asect->flags & SEC_ALLOC) != 0)
this_hdr->sh_flags |= SHF_ALLOC;
if ((asect->flags & SEC_READONLY) == 0)
this_hdr->sh_flags |= SHF_WRITE;
if ((asect->flags & SEC_CODE) != 0)
this_hdr->sh_flags |= SHF_EXECINSTR;
if ((asect->flags & SEC_MERGE) != 0)
{
this_hdr->sh_flags |= SHF_MERGE;
this_hdr->sh_entsize = asect->entsize;
if ((asect->flags & SEC_STRINGS) != 0)
this_hdr->sh_flags |= SHF_STRINGS;
}
if ((asect->flags & SEC_GROUP) == 0 && elf_group_name (asect) != NULL)
this_hdr->sh_flags |= SHF_GROUP;
if ((asect->flags & SEC_THREAD_LOCAL) != 0)
{
this_hdr->sh_flags |= SHF_TLS;
if (asect->size == 0
&& (asect->flags & SEC_HAS_CONTENTS) == 0)
{
struct bfd_link_order *o = asect->map_tail.link_order;
this_hdr->sh_size = 0;
if (o != NULL)
{
this_hdr->sh_size = o->offset + o->size;
if (this_hdr->sh_size != 0)
this_hdr->sh_type = SHT_NOBITS;
}
}
}
/* Check for processor-specific section types. */
sh_type = this_hdr->sh_type;
if (bed->elf_backend_fake_sections
&& !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
*failedptr = TRUE;
if (sh_type == SHT_NOBITS && asect->size != 0)
{
/* Don't change the header type from NOBITS if we are being
called for objcopy --only-keep-debug. */
this_hdr->sh_type = sh_type;
}
/* If the section has relocs, set up a section header for the
SHT_REL[A] section. If two relocation sections are required for
this section, it is up to the processor-specific back-end to
create the other. */
if ((asect->flags & SEC_RELOC) != 0
&& !_bfd_elf_init_reloc_shdr (abfd,
&elf_section_data (asect)->rel_hdr,
asect,
asect->use_rela_p))
*failedptr = TRUE;
}
/* Fill in the contents of a SHT_GROUP section. Called from
_bfd_elf_compute_section_file_positions for gas, objcopy, and
when ELF targets use the generic linker, ld. Called for ld -r
from bfd_elf_final_link. */
void
bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
{
bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
asection *elt, *first;
unsigned char *loc;
bfd_boolean gas;
/* Ignore linker created group section. See elfNN_ia64_object_p in
elfxx-ia64.c. */
if (((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP)
|| *failedptr)
return;
if (elf_section_data (sec)->this_hdr.sh_info == 0)
{
unsigned long symindx = 0;
/* elf_group_id will have been set up by objcopy and the
generic linker. */
if (elf_group_id (sec) != NULL)
symindx = elf_group_id (sec)->udata.i;
if (symindx == 0)
{
/* If called from the assembler, swap_out_syms will have set up
elf_section_syms. */
BFD_ASSERT (elf_section_syms (abfd) != NULL);
symindx = elf_section_syms (abfd)[sec->index]->udata.i;
}
elf_section_data (sec)->this_hdr.sh_info = symindx;
}
else if (elf_section_data (sec)->this_hdr.sh_info == (unsigned int) -2)
{
/* The ELF backend linker sets sh_info to -2 when the group
signature symbol is global, and thus the index can't be
set until all local symbols are output. */
asection *igroup = elf_sec_group (elf_next_in_group (sec));
struct bfd_elf_section_data *sec_data = elf_section_data (igroup);
unsigned long symndx = sec_data->this_hdr.sh_info;
unsigned long extsymoff = 0;
struct elf_link_hash_entry *h;
if (!elf_bad_symtab (igroup->owner))
{
Elf_Internal_Shdr *symtab_hdr;
symtab_hdr = &elf_tdata (igroup->owner)->symtab_hdr;
extsymoff = symtab_hdr->sh_info;
}
h = elf_sym_hashes (igroup->owner)[symndx - extsymoff];
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
elf_section_data (sec)->this_hdr.sh_info = h->indx;
}
/* The contents won't be allocated for "ld -r" or objcopy. */
gas = TRUE;
if (sec->contents == NULL)
{
gas = FALSE;
sec->contents = (unsigned char *) bfd_alloc (abfd, sec->size);
/* Arrange for the section to be written out. */
elf_section_data (sec)->this_hdr.contents = sec->contents;
if (sec->contents == NULL)
{
*failedptr = TRUE;
return;
}
}
loc = sec->contents + sec->size;
/* Get the pointer to the first section in the group that gas
squirreled away here. objcopy arranges for this to be set to the
start of the input section group. */
first = elt = elf_next_in_group (sec);
/* First element is a flag word. Rest of section is elf section
indices for all the sections of the group. Write them backwards
just to keep the group in the same order as given in .section
directives, not that it matters. */
while (elt != NULL)
{
asection *s;
s = elt;
if (!gas)
s = s->output_section;
if (s != NULL
&& !bfd_is_abs_section (s))
{
unsigned int idx = elf_section_data (s)->this_idx;
loc -= 4;
H_PUT_32 (abfd, idx, loc);
}
elt = elf_next_in_group (elt);
if (elt == first)
break;
}
if ((loc -= 4) != sec->contents)
abort ();
H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
}
/* Assign all ELF section numbers. The dummy first section is handled here
too. The link/info pointers for the standard section types are filled
in here too, while we're at it. */
static bfd_boolean
assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
{
struct elf_obj_tdata *t = elf_tdata (abfd);
asection *sec;
unsigned int section_number, secn;
Elf_Internal_Shdr **i_shdrp;
struct bfd_elf_section_data *d;
bfd_boolean need_symtab;
section_number = 1;
_bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
/* SHT_GROUP sections are in relocatable files only. */
if (link_info == NULL || link_info->relocatable)
{
/* Put SHT_GROUP sections first. */
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{
d = elf_section_data (sec);
if (d->this_hdr.sh_type == SHT_GROUP)
{
if (sec->flags & SEC_LINKER_CREATED)
{
/* Remove the linker created SHT_GROUP sections. */
bfd_section_list_remove (abfd, sec);
abfd->section_count--;
}
else
d->this_idx = section_number++;
}
}
}
for (sec = abfd->sections; sec; sec = sec->next)
{
d = elf_section_data (sec);
if (d->this_hdr.sh_type != SHT_GROUP)
d->this_idx = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
if ((sec->flags & SEC_RELOC) == 0)
d->rel_idx = 0;
else
{
d->rel_idx = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
}
if (d->rel_hdr2)
{
d->rel_idx2 = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name);
}
else
d->rel_idx2 = 0;
}
t->shstrtab_section = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
need_symtab = (bfd_get_symcount (abfd) > 0
|| (link_info == NULL
&& ((abfd->flags & (EXEC_P | DYNAMIC | HAS_RELOC))
== HAS_RELOC)));
if (need_symtab)
{
t->symtab_section = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
{
t->symtab_shndx_section = section_number++;
t->symtab_shndx_hdr.sh_name
= (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
".symtab_shndx", FALSE);
if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
return FALSE;
}
t->strtab_section = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
}
_bfd_elf_strtab_finalize (elf_shstrtab (abfd));
t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
elf_numsections (abfd) = section_number;
elf_elfheader (abfd)->e_shnum = section_number;
/* Set up the list of section header pointers, in agreement with the
indices. */
i_shdrp = (Elf_Internal_Shdr **) bfd_zalloc2 (abfd, section_number,
sizeof (Elf_Internal_Shdr *));
if (i_shdrp == NULL)
return FALSE;
i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd,
sizeof (Elf_Internal_Shdr));
if (i_shdrp[0] == NULL)
{
bfd_release (abfd, i_shdrp);
return FALSE;
}
elf_elfsections (abfd) = i_shdrp;
i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
if (need_symtab)
{
i_shdrp[t->symtab_section] = &t->symtab_hdr;
if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
{
i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
t->symtab_shndx_hdr.sh_link = t->symtab_section;
}
i_shdrp[t->strtab_section] = &t->strtab_hdr;
t->symtab_hdr.sh_link = t->strtab_section;
}
for (sec = abfd->sections; sec; sec = sec->next)
{
asection *s;
const char *name;
d = elf_section_data (sec);
i_shdrp[d->this_idx] = &d->this_hdr;
if (d->rel_idx != 0)
i_shdrp[d->rel_idx] = &d->rel_hdr;
if (d->rel_idx2 != 0)
i_shdrp[d->rel_idx2] = d->rel_hdr2;
/* Fill in the sh_link and sh_info fields while we're at it. */
/* sh_link of a reloc section is the section index of the symbol
table. sh_info is the section index of the section to which
the relocation entries apply. */
if (d->rel_idx != 0)
{
d->rel_hdr.sh_link = t->symtab_section;
d->rel_hdr.sh_info = d->this_idx;
}
if (d->rel_idx2 != 0)
{
d->rel_hdr2->sh_link = t->symtab_section;
d->rel_hdr2->sh_info = d->this_idx;
}
/* We need to set up sh_link for SHF_LINK_ORDER. */
if ((d->this_hdr.sh_flags & SHF_LINK_ORDER) != 0)
{
s = elf_linked_to_section (sec);
if (s)
{
/* elf_linked_to_section points to the input section. */
if (link_info != NULL)
{
/* Check discarded linkonce section. */
if (elf_discarded_section (s))
{
asection *kept;
(*_bfd_error_handler)
(_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
abfd, d->this_hdr.bfd_section,
s, s->owner);
/* Point to the kept section if it has the same
size as the discarded one. */
kept = _bfd_elf_check_kept_section (s, link_info);
if (kept == NULL)
{
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
s = kept;
}
s = s->output_section;
BFD_ASSERT (s != NULL);
}
else
{
/* Handle objcopy. */
if (s->output_section == NULL)
{
(*_bfd_error_handler)
(_("%B: sh_link of section `%A' points to removed section `%A' of `%B'"),
abfd, d->this_hdr.bfd_section, s, s->owner);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
s = s->output_section;
}
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
}
else
{
/* PR 290:
The Intel C compiler generates SHT_IA_64_UNWIND with
SHF_LINK_ORDER. But it doesn't set the sh_link or
sh_info fields. Hence we could get the situation
where s is NULL. */
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, sec);
}
}
switch (d->this_hdr.sh_type)
{
case SHT_REL:
case SHT_RELA:
/* A reloc section which we are treating as a normal BFD
section. sh_link is the section index of the symbol
table. sh_info is the section index of the section to
which the relocation entries apply. We assume that an
allocated reloc section uses the dynamic symbol table.
FIXME: How can we be sure? */
s = bfd_get_section_by_name (abfd, ".dynsym");
if (s != NULL)
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
/* We look up the section the relocs apply to by name. */
name = sec->name;
if (d->this_hdr.sh_type == SHT_REL)
name += 4;
else
name += 5;
s = bfd_get_section_by_name (abfd, name);
if (s != NULL)
d->this_hdr.sh_info = elf_section_data (s)->this_idx;
break;
case SHT_STRTAB:
/* We assume that a section named .stab*str is a stabs
string section. We look for a section with the same name
but without the trailing ``str'', and set its sh_link
field to point to this section. */
if (CONST_STRNEQ (sec->name, ".stab")
&& strcmp (sec->name + strlen (sec->name) - 3, "str") == 0)
{
size_t len;
char *alc;
len = strlen (sec->name);
alc = (char *) bfd_malloc (len - 2);
if (alc == NULL)
return FALSE;
memcpy (alc, sec->name, len - 3);
alc[len - 3] = '\0';
s = bfd_get_section_by_name (abfd, alc);
free (alc);
if (s != NULL)
{
elf_section_data (s)->this_hdr.sh_link = d->this_idx;
/* This is a .stab section. */
if (elf_section_data (s)->this_hdr.sh_entsize == 0)
elf_section_data (s)->this_hdr.sh_entsize
= 4 + 2 * bfd_get_arch_size (abfd) / 8;
}
}
break;
case SHT_DYNAMIC:
case SHT_DYNSYM:
case SHT_GNU_verneed:
case SHT_GNU_verdef:
/* sh_link is the section header index of the string table
used for the dynamic entries, or the symbol table, or the
version strings. */
s = bfd_get_section_by_name (abfd, ".dynstr");
if (s != NULL)
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
break;
case SHT_GNU_LIBLIST:
/* sh_link is the section header index of the prelink library
list used for the dynamic entries, or the symbol table, or
the version strings. */
s = bfd_get_section_by_name (abfd, (sec->flags & SEC_ALLOC)
? ".dynstr" : ".gnu.libstr");
if (s != NULL)
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
break;
case SHT_HASH:
case SHT_GNU_HASH:
case SHT_GNU_versym:
/* sh_link is the section header index of the symbol table
this hash table or version table is for. */
s = bfd_get_section_by_name (abfd, ".dynsym");
if (s != NULL)
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
break;
case SHT_GROUP:
d->this_hdr.sh_link = t->symtab_section;
}
}
for (secn = 1; secn < section_number; ++secn)
if (i_shdrp[secn] == NULL)
i_shdrp[secn] = i_shdrp[0];
else
i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
i_shdrp[secn]->sh_name);
return TRUE;
}
/* Map symbol from it's internal number to the external number, moving
all local symbols to be at the head of the list. */
static bfd_boolean
sym_is_global (bfd *abfd, asymbol *sym)
{
/* If the backend has a special mapping, use it. */
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (bed->elf_backend_sym_is_global)
return (*bed->elf_backend_sym_is_global) (abfd, sym);
return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
|| bfd_is_und_section (bfd_get_section (sym))
|| bfd_is_com_section (bfd_get_section (sym)));
}
/* Don't output section symbols for sections that are not going to be
output. */
static bfd_boolean
ignore_section_sym (bfd *abfd, asymbol *sym)
{
return ((sym->flags & BSF_SECTION_SYM) != 0
&& !(sym->section->owner == abfd
|| (sym->section->output_section->owner == abfd
&& sym->section->output_offset == 0)));
}
static bfd_boolean
elf_map_symbols (bfd *abfd)
{
unsigned int symcount = bfd_get_symcount (abfd);
asymbol **syms = bfd_get_outsymbols (abfd);
asymbol **sect_syms;
unsigned int num_locals = 0;
unsigned int num_globals = 0;
unsigned int num_locals2 = 0;
unsigned int num_globals2 = 0;
int max_index = 0;
unsigned int idx;
asection *asect;
asymbol **new_syms;
#ifdef DEBUG
fprintf (stderr, "elf_map_symbols\n");
fflush (stderr);
#endif
for (asect = abfd->sections; asect; asect = asect->next)
{
if (max_index < asect->index)
max_index = asect->index;
}
max_index++;
sect_syms = (asymbol **) bfd_zalloc2 (abfd, max_index, sizeof (asymbol *));
if (sect_syms == NULL)
return FALSE;
elf_section_syms (abfd) = sect_syms;
elf_num_section_syms (abfd) = max_index;
/* Init sect_syms entries for any section symbols we have already
decided to output. */
for (idx = 0; idx < symcount; idx++)
{
asymbol *sym = syms[idx];
if ((sym->flags & BSF_SECTION_SYM) != 0
&& sym->value == 0
&& !ignore_section_sym (abfd, sym))
{
asection *sec = sym->section;
if (sec->owner != abfd)
sec = sec->output_section;
sect_syms[sec->index] = syms[idx];
}
}
/* Classify all of the symbols. */
for (idx = 0; idx < symcount; idx++)
{
if (ignore_section_sym (abfd, syms[idx]))
continue;
if (!sym_is_global (abfd, syms[idx]))
num_locals++;
else
num_globals++;
}
/* We will be adding a section symbol for each normal BFD section. Most
sections will already have a section symbol in outsymbols, but
eg. SHT_GROUP sections will not, and we need the section symbol mapped
at least in that case. */
for (asect = abfd->sections; asect; asect = asect->next)
{
if (sect_syms[asect->index] == NULL)
{
if (!sym_is_global (abfd, asect->symbol))
num_locals++;
else
num_globals++;
}
}
/* Now sort the symbols so the local symbols are first. */
new_syms = (asymbol **) bfd_alloc2 (abfd, num_locals + num_globals,
sizeof (asymbol *));
if (new_syms == NULL)
return FALSE;
for (idx = 0; idx < symcount; idx++)
{
asymbol *sym = syms[idx];
unsigned int i;
if (ignore_section_sym (abfd, sym))
continue;
if (!sym_is_global (abfd, sym))
i = num_locals2++;
else
i = num_locals + num_globals2++;
new_syms[i] = sym;
sym->udata.i = i + 1;
}
for (asect = abfd->sections; asect; asect = asect->next)
{
if (sect_syms[asect->index] == NULL)
{
asymbol *sym = asect->symbol;
unsigned int i;
sect_syms[asect->index] = sym;
if (!sym_is_global (abfd, sym))
i = num_locals2++;
else
i = num_locals + num_globals2++;
new_syms[i] = sym;
sym->udata.i = i + 1;
}
}
bfd_set_symtab (abfd, new_syms, num_locals + num_globals);
elf_num_locals (abfd) = num_locals;
elf_num_globals (abfd) = num_globals;
return TRUE;
}
/* Align to the maximum file alignment that could be required for any
ELF data structure. */
static inline file_ptr
align_file_position (file_ptr off, int align)
{
return (off + align - 1) & ~(align - 1);
}
/* Assign a file position to a section, optionally aligning to the
required section alignment. */
file_ptr
_bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp,
file_ptr offset,
bfd_boolean align)
{
if (align && i_shdrp->sh_addralign > 1)
offset = BFD_ALIGN (offset, i_shdrp->sh_addralign);
i_shdrp->sh_offset = offset;
if (i_shdrp->bfd_section != NULL)
i_shdrp->bfd_section->filepos = offset;
if (i_shdrp->sh_type != SHT_NOBITS)
offset += i_shdrp->sh_size;
return offset;
}
/* Compute the file positions we are going to put the sections at, and
otherwise prepare to begin writing out the ELF file. If LINK_INFO
is not NULL, this is being called by the ELF backend linker. */
bfd_boolean
_bfd_elf_compute_section_file_positions (bfd *abfd,
struct bfd_link_info *link_info)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean failed;
struct bfd_strtab_hash *strtab = NULL;
Elf_Internal_Shdr *shstrtab_hdr;
bfd_boolean need_symtab;
if (abfd->output_has_begun)
return TRUE;
/* Do any elf backend specific processing first. */
if (bed->elf_backend_begin_write_processing)
(*bed->elf_backend_begin_write_processing) (abfd, link_info);
if (! prep_headers (abfd))
return FALSE;
/* Post process the headers if necessary. */
if (bed->elf_backend_post_process_headers)
(*bed->elf_backend_post_process_headers) (abfd, link_info);
failed = FALSE;
bfd_map_over_sections (abfd, elf_fake_sections, &failed);
if (failed)
return FALSE;
if (!assign_section_numbers (abfd, link_info))
return FALSE;
/* The backend linker builds symbol table information itself. */
need_symtab = (link_info == NULL
&& (bfd_get_symcount (abfd) > 0
|| ((abfd->flags & (EXEC_P | DYNAMIC | HAS_RELOC))
== HAS_RELOC)));
if (need_symtab)
{
/* Non-zero if doing a relocatable link. */
int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
if (! swap_out_syms (abfd, &strtab, relocatable_p))
return FALSE;
}
if (link_info == NULL)
{
bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
if (failed)
return FALSE;
}
shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
/* sh_name was set in prep_headers. */
shstrtab_hdr->sh_type = SHT_STRTAB;
shstrtab_hdr->sh_flags = 0;
shstrtab_hdr->sh_addr = 0;
shstrtab_hdr->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
shstrtab_hdr->sh_entsize = 0;
shstrtab_hdr->sh_link = 0;
shstrtab_hdr->sh_info = 0;
/* sh_offset is set in assign_file_positions_except_relocs. */
shstrtab_hdr->sh_addralign = 1;
if (!assign_file_positions_except_relocs (abfd, link_info))
return FALSE;
if (need_symtab)
{
file_ptr off;
Elf_Internal_Shdr *hdr;
off = elf_tdata (abfd)->next_file_pos;
hdr = &elf_tdata (abfd)->symtab_hdr;
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
if (hdr->sh_size != 0)
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
hdr = &elf_tdata (abfd)->strtab_hdr;
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
elf_tdata (abfd)->next_file_pos = off;
/* Now that we know where the .strtab section goes, write it
out. */
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|| ! _bfd_stringtab_emit (abfd, strtab))
return FALSE;
_bfd_stringtab_free (strtab);
}
abfd->output_has_begun = TRUE;
return TRUE;
}
/* Make an initial estimate of the size of the program header. If we
get the number wrong here, we'll redo section placement. */
static bfd_size_type
get_program_header_size (bfd *abfd, struct bfd_link_info *info)
{
size_t segs;
asection *s;
const struct elf_backend_data *bed;
/* Assume we will need exactly two PT_LOAD segments: one for text
and one for data. */
segs = 2;
s = bfd_get_section_by_name (abfd, ".interp");
if (s != NULL && (s->flags & SEC_LOAD) != 0)
{
/* If we have a loadable interpreter section, we need a
PT_INTERP segment. In this case, assume we also need a
PT_PHDR segment, although that may not be true for all
targets. */
segs += 2;
}
if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
{
/* We need a PT_DYNAMIC segment. */
++segs;
}
if (info != NULL && info->relro)
{
/* We need a PT_GNU_RELRO segment. */
++segs;
}
if (elf_tdata (abfd)->eh_frame_hdr)
{
/* We need a PT_GNU_EH_FRAME segment. */
++segs;
}
if (elf_tdata (abfd)->stack_flags)
{
/* We need a PT_GNU_STACK segment. */
++segs;
}
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
&& CONST_STRNEQ (s->name, ".note"))
{
/* We need a PT_NOTE segment. */
++segs;
/* Try to create just one PT_NOTE segment
for all adjacent loadable .note* sections.
gABI requires that within a PT_NOTE segment
(and also inside of each SHT_NOTE section)
each note is padded to a multiple of 4 size,
so we check whether the sections are correctly
aligned. */
if (s->alignment_power == 2)
while (s->next != NULL
&& s->next->alignment_power == 2
&& (s->next->flags & SEC_LOAD) != 0
&& CONST_STRNEQ (s->next->name, ".note"))
s = s->next;
}
}
for (s = abfd->sections; s != NULL; s = s->next)
{
if (s->flags & SEC_THREAD_LOCAL)
{
/* We need a PT_TLS segment. */
++segs;
break;
}
}
/* Let the backend count up any program headers it might need. */
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_additional_program_headers)
{
int a;
a = (*bed->elf_backend_additional_program_headers) (abfd, info);
if (a == -1)
abort ();
segs += a;
}
return segs * bed->s->sizeof_phdr;
}
/* Find the segment that contains the output_section of section. */
Elf_Internal_Phdr *
_bfd_elf_find_segment_containing_section (bfd * abfd, asection * section)
{
struct elf_segment_map *m;
Elf_Internal_Phdr *p;
for (m = elf_tdata (abfd)->segment_map,
p = elf_tdata (abfd)->phdr;
m != NULL;
m = m->next, p++)
{
int i;
for (i = m->count - 1; i >= 0; i--)
if (m->sections[i] == section)
return p;
}
return NULL;
}
/* Create a mapping from a set of sections to a program segment. */
static struct elf_segment_map *
make_mapping (bfd *abfd,
asection **sections,
unsigned int from,
unsigned int to,
bfd_boolean phdr)
{
struct elf_segment_map *m;
unsigned int i;
asection **hdrpp;
bfd_size_type amt;
amt = sizeof (struct elf_segment_map);
amt += (to - from - 1) * sizeof (asection *);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
return NULL;
m->next = NULL;
m->p_type = PT_LOAD;
for (i = from, hdrpp = sections + from; i < to; i++, hdrpp++)
m->sections[i - from] = *hdrpp;
m->count = to - from;
if (from == 0 && phdr)
{
/* Include the headers in the first PT_LOAD segment. */
m->includes_filehdr = 1;
m->includes_phdrs = 1;
}
return m;
}
/* Create the PT_DYNAMIC segment, which includes DYNSEC. Returns NULL
on failure. */
struct elf_segment_map *
_bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
{
struct elf_segment_map *m;
m = (struct elf_segment_map *) bfd_zalloc (abfd,
sizeof (struct elf_segment_map));
if (m == NULL)
return NULL;
m->next = NULL;
m->p_type = PT_DYNAMIC;
m->count = 1;
m->sections[0] = dynsec;
return m;
}
/* Possibly add or remove segments from the segment map. */
static bfd_boolean
elf_modify_segment_map (bfd *abfd,
struct bfd_link_info *info,
bfd_boolean remove_empty_load)
{
struct elf_segment_map **m;
const struct elf_backend_data *bed;
/* The placement algorithm assumes that non allocated sections are
not in PT_LOAD segments. We ensure this here by removing such
sections from the segment map. We also remove excluded
sections. Finally, any PT_LOAD segment without sections is
removed. */
m = &elf_tdata (abfd)->segment_map;
while (*m)
{
unsigned int i, new_count;
for (new_count = 0, i = 0; i < (*m)->count; i++)
{
if (((*m)->sections[i]->flags & SEC_EXCLUDE) == 0
&& (((*m)->sections[i]->flags & SEC_ALLOC) != 0
|| (*m)->p_type != PT_LOAD))
{
(*m)->sections[new_count] = (*m)->sections[i];
new_count++;
}
}
(*m)->count = new_count;
if (remove_empty_load && (*m)->p_type == PT_LOAD && (*m)->count == 0)
*m = (*m)->next;
else
m = &(*m)->next;
}
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_modify_segment_map != NULL)
{
if (!(*bed->elf_backend_modify_segment_map) (abfd, info))
return FALSE;
}
return TRUE;
}
/* Set up a mapping from BFD sections to program segments. */
bfd_boolean
_bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
{
unsigned int count;
struct elf_segment_map *m;
asection **sections = NULL;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean no_user_phdrs;
no_user_phdrs = elf_tdata (abfd)->segment_map == NULL;
if (no_user_phdrs && bfd_count_sections (abfd) != 0)
{
asection *s;
unsigned int i;
struct elf_segment_map *mfirst;
struct elf_segment_map **pm;
asection *last_hdr;
bfd_vma last_size;
unsigned int phdr_index;
bfd_vma maxpagesize;
asection **hdrpp;
bfd_boolean phdr_in_segment = TRUE;
bfd_boolean writable;
int tls_count = 0;
asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
/* Select the allocated sections, and sort them. */
sections = (asection **) bfd_malloc2 (bfd_count_sections (abfd),
sizeof (asection *));
if (sections == NULL)
goto error_return;
i = 0;
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_ALLOC) != 0)
{
sections[i] = s;
++i;
}
}
BFD_ASSERT (i <= bfd_count_sections (abfd));
count = i;
qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
/* Build the mapping. */
mfirst = NULL;
pm = &mfirst;
/* If we have a .interp section, then create a PT_PHDR segment for
the program headers and a PT_INTERP segment for the .interp
section. */
s = bfd_get_section_by_name (abfd, ".interp");
if (s != NULL && (s->flags & SEC_LOAD) != 0)
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_PHDR;
/* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */
m->p_flags = PF_R | PF_X;
m->p_flags_valid = 1;
m->includes_phdrs = 1;
*pm = m;
pm = &m->next;
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_INTERP;
m->count = 1;
m->sections[0] = s;
*pm = m;
pm = &m->next;
}
/* Look through the sections. We put sections in the same program
segment when the start of the second section can be placed within
a few bytes of the end of the first section. */
last_hdr = NULL;
last_size = 0;
phdr_index = 0;
maxpagesize = bed->maxpagesize;
writable = FALSE;
dynsec = bfd_get_section_by_name (abfd, ".dynamic");
if (dynsec != NULL
&& (dynsec->flags & SEC_LOAD) == 0)
dynsec = NULL;
/* Deal with -Ttext or something similar such that the first section
is not adjacent to the program headers. This is an
approximation, since at this point we don't know exactly how many
program headers we will need. */
if (count > 0)
{
bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
if (phdr_size == (bfd_size_type) -1)
phdr_size = get_program_header_size (abfd, info);
if ((abfd->flags & D_PAGED) == 0
|| sections[0]->lma < phdr_size
|| sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
phdr_in_segment = FALSE;
}
for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
{
asection *hdr;
bfd_boolean new_segment;
hdr = *hdrpp;
/* See if this section and the last one will fit in the same
segment. */
if (last_hdr == NULL)
{
/* If we don't have a segment yet, then we don't need a new
one (we build the last one after this loop). */
new_segment = FALSE;
}
else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma)
{
/* If this section has a different relation between the
virtual address and the load address, then we need a new
segment. */
new_segment = TRUE;
}
/* In the next test we have to be careful when last_hdr->lma is close
to the end of the address space. If the aligned address wraps
around to the start of the address space, then there are no more
pages left in memory and it is OK to assume that the current
section can be included in the current segment. */
else if ((BFD_ALIGN (last_hdr->lma + last_size, maxpagesize) + maxpagesize
> last_hdr->lma)
&& (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize) + maxpagesize
<= hdr->lma))
{
/* If putting this section in this segment would force us to
skip a page in the segment, then we need a new segment. */
new_segment = TRUE;
}
else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
&& (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
{
/* We don't want to put a loadable section after a
nonloadable section in the same segment.
Consider .tbss sections as loadable for this purpose. */
new_segment = TRUE;
}
else if ((abfd->flags & D_PAGED) == 0)
{
/* If the file is not demand paged, which means that we
don't require the sections to be correctly aligned in the
file, then there is no other reason for a new segment. */
new_segment = FALSE;
}
else if (! writable
&& (hdr->flags & SEC_READONLY) == 0
&& (((last_hdr->lma + last_size - 1)
& ~(maxpagesize - 1))
!= (hdr->lma & ~(maxpagesize - 1))))
{
/* We don't want to put a writable section in a read only
segment, unless they are on the same page in memory
anyhow. We already know that the last section does not
bring us past the current section on the page, so the
only case in which the new section is not on the same
page as the previous section is when the previous section
ends precisely on a page boundary. */
new_segment = TRUE;
}
else
{
/* Otherwise, we can use the same segment. */
new_segment = FALSE;
}
/* Allow interested parties a chance to override our decision. */
if (last_hdr != NULL
&& info != NULL
&& info->callbacks->override_segment_assignment != NULL)
new_segment
= info->callbacks->override_segment_assignment (info, abfd, hdr,
last_hdr,
new_segment);
if (! new_segment)
{
if ((hdr->flags & SEC_READONLY) == 0)
writable = TRUE;
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
!= SEC_THREAD_LOCAL)
last_size = hdr->size;
else
last_size = 0;
continue;
}
/* We need a new program segment. We must create a new program
header holding all the sections from phdr_index until hdr. */
m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
if (m == NULL)
goto error_return;
*pm = m;
pm = &m->next;
if ((hdr->flags & SEC_READONLY) == 0)
writable = TRUE;
else
writable = FALSE;
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
last_size = hdr->size;
else
last_size = 0;
phdr_index = i;
phdr_in_segment = FALSE;
}
/* Create a final PT_LOAD program segment. */
if (last_hdr != NULL)
{
m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
if (m == NULL)
goto error_return;
*pm = m;
pm = &m->next;
}
/* If there is a .dynamic section, throw in a PT_DYNAMIC segment. */
if (dynsec != NULL)
{
m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
if (m == NULL)
goto error_return;
*pm = m;
pm = &m->next;
}
/* For each batch of consecutive loadable .note sections,
add a PT_NOTE segment. We don't use bfd_get_section_by_name,
because if we link together nonloadable .note sections and
loadable .note sections, we will generate two .note sections
in the output file. FIXME: Using names for section types is
bogus anyhow. */
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
&& CONST_STRNEQ (s->name, ".note"))
{
asection *s2;
count = 1;
amt = sizeof (struct elf_segment_map);
if (s->alignment_power == 2)
for (s2 = s; s2->next != NULL; s2 = s2->next)
{
if (s2->next->alignment_power == 2
&& (s2->next->flags & SEC_LOAD) != 0
&& CONST_STRNEQ (s2->next->name, ".note")
&& align_power (s2->vma + s2->size, 2)
== s2->next->vma)
count++;
else
break;
}
amt += (count - 1) * sizeof (asection *);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_NOTE;
m->count = count;
while (count > 1)
{
m->sections[m->count - count--] = s;
BFD_ASSERT ((s->flags & SEC_THREAD_LOCAL) == 0);
s = s->next;
}
m->sections[m->count - 1] = s;
BFD_ASSERT ((s->flags & SEC_THREAD_LOCAL) == 0);
*pm = m;
pm = &m->next;
}
if (s->flags & SEC_THREAD_LOCAL)
{
if (! tls_count)
first_tls = s;
tls_count++;
}
}
/* If there are any SHF_TLS output sections, add PT_TLS segment. */
if (tls_count > 0)
{
amt = sizeof (struct elf_segment_map);
amt += (tls_count - 1) * sizeof (asection *);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_TLS;
m->count = tls_count;
/* Mandated PF_R. */
m->p_flags = PF_R;
m->p_flags_valid = 1;
for (i = 0; i < (unsigned int) tls_count; ++i)
{
BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
m->sections[i] = first_tls;
first_tls = first_tls->next;
}
*pm = m;
pm = &m->next;
}
/* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
segment. */
eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
if (eh_frame_hdr != NULL
&& (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_GNU_EH_FRAME;
m->count = 1;
m->sections[0] = eh_frame_hdr->output_section;
*pm = m;
pm = &m->next;
}
if (elf_tdata (abfd)->stack_flags)
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_GNU_STACK;
m->p_flags = elf_tdata (abfd)->stack_flags;
m->p_flags_valid = 1;
*pm = m;
pm = &m->next;
}
if (info != NULL && info->relro)
{
for (m = mfirst; m != NULL; m = m->next)
{
if (m->p_type == PT_LOAD)
{
asection *last = m->sections[m->count - 1];
bfd_vma vaddr = m->sections[0]->vma;
bfd_vma filesz = last->vma - vaddr + last->size;
if (vaddr < info->relro_end
&& vaddr >= info->relro_start
&& (vaddr + filesz) >= info->relro_end)
break;
}
}
/* Make a PT_GNU_RELRO segment only when it isn't empty. */
if (m != NULL)
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_GNU_RELRO;
m->p_flags = PF_R;
m->p_flags_valid = 1;
*pm = m;
pm = &m->next;
}
}
free (sections);
elf_tdata (abfd)->segment_map = mfirst;
}
if (!elf_modify_segment_map (abfd, info, no_user_phdrs))
return FALSE;
for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
++count;
elf_tdata (abfd)->program_header_size = count * bed->s->sizeof_phdr;
return TRUE;
error_return:
if (sections != NULL)
free (sections);
return FALSE;
}
/* Sort sections by address. */
static int
elf_sort_sections (const void *arg1, const void *arg2)
{
const asection *sec1 = *(const asection **) arg1;
const asection *sec2 = *(const asection **) arg2;
bfd_size_type size1, size2;
/* Sort by LMA first, since this is the address used to
place the section into a segment. */
if (sec1->lma < sec2->lma)
return -1;
else if (sec1->lma > sec2->lma)
return 1;
/* Then sort by VMA. Normally the LMA and the VMA will be
the same, and this will do nothing. */
if (sec1->vma < sec2->vma)
return -1;
else if (sec1->vma > sec2->vma)
return 1;
/* Put !SEC_LOAD sections after SEC_LOAD ones. */
#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
if (TOEND (sec1))
{
if (TOEND (sec2))
{
/* If the indicies are the same, do not return 0
here, but continue to try the next comparison. */
if (sec1->target_index - sec2->target_index != 0)
return sec1->target_index - sec2->target_index;
}
else
return 1;
}
else if (TOEND (sec2))
return -1;
#undef TOEND
/* Sort by size, to put zero sized sections
before others at the same address. */
size1 = (sec1->flags & SEC_LOAD) ? sec1->size : 0;
size2 = (sec2->flags & SEC_LOAD) ? sec2->size : 0;
if (size1 < size2)
return -1;
if (size1 > size2)
return 1;
return sec1->target_index - sec2->target_index;
}
/* Ian Lance Taylor writes:
We shouldn't be using % with a negative signed number. That's just
not good. We have to make sure either that the number is not
negative, or that the number has an unsigned type. When the types
are all the same size they wind up as unsigned. When file_ptr is a
larger signed type, the arithmetic winds up as signed long long,
which is wrong.
What we're trying to say here is something like ``increase OFF by
the least amount that will cause it to be equal to the VMA modulo
the page size.'' */
/* In other words, something like:
vma_offset = m->sections[0]->vma % bed->maxpagesize;
off_offset = off % bed->maxpagesize;
if (vma_offset < off_offset)
adjustment = vma_offset + bed->maxpagesize - off_offset;
else
adjustment = vma_offset - off_offset;
which can can be collapsed into the expression below. */
static file_ptr
vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
{
return ((vma - off) % maxpagesize);
}
static void
print_segment_map (const struct elf_segment_map *m)
{
unsigned int j;
const char *pt = get_segment_type (m->p_type);
char buf[32];
if (pt == NULL)
{
if (m->p_type >= PT_LOPROC && m->p_type <= PT_HIPROC)
sprintf (buf, "LOPROC+%7.7x",
(unsigned int) (m->p_type - PT_LOPROC));
else if (m->p_type >= PT_LOOS && m->p_type <= PT_HIOS)
sprintf (buf, "LOOS+%7.7x",
(unsigned int) (m->p_type - PT_LOOS));
else
snprintf (buf, sizeof (buf), "%8.8x",
(unsigned int) m->p_type);
pt = buf;
}
fprintf (stderr, "%s:", pt);
for (j = 0; j < m->count; j++)
fprintf (stderr, " %s", m->sections [j]->name);
putc ('\n',stderr);
}
static bfd_boolean
write_zeros (bfd *abfd, file_ptr pos, bfd_size_type len)
{
void *buf;
bfd_boolean ret;
if (bfd_seek (abfd, pos, SEEK_SET) != 0)
return FALSE;
buf = bfd_zmalloc (len);
if (buf == NULL)
return FALSE;
ret = bfd_bwrite (buf, len, abfd) == len;
free (buf);
return ret;
}
/* Assign file positions to the sections based on the mapping from
sections to segments. This function also sets up some fields in
the file header. */
static bfd_boolean
assign_file_positions_for_load_sections (bfd *abfd,
struct bfd_link_info *link_info)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_segment_map *m;
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
file_ptr off;
bfd_size_type maxpagesize;
unsigned int alloc;
unsigned int i, j;
bfd_vma header_pad = 0;
if (link_info == NULL
&& !_bfd_elf_map_sections_to_segments (abfd, link_info))
return FALSE;
alloc = 0;
for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
{
++alloc;
if (m->header_size)
header_pad = m->header_size;
}
elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
elf_elfheader (abfd)->e_phnum = alloc;
if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr;
else
BFD_ASSERT (elf_tdata (abfd)->program_header_size
>= alloc * bed->s->sizeof_phdr);
if (alloc == 0)
{
elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
return TRUE;
}
/* We're writing the size in elf_tdata (abfd)->program_header_size,
see assign_file_positions_except_relocs, so make sure we have
that amount allocated, with trailing space cleared.
The variable alloc contains the computed need, while elf_tdata
(abfd)->program_header_size contains the size used for the
layout.
See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments
where the layout is forced to according to a larger size in the
last iterations for the testcase ld-elf/header. */
BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr
== 0);
phdrs = (Elf_Internal_Phdr *)
bfd_zalloc2 (abfd,
(elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr),
sizeof (Elf_Internal_Phdr));
elf_tdata (abfd)->phdr = phdrs;
if (phdrs == NULL)
return FALSE;
maxpagesize = 1;
if ((abfd->flags & D_PAGED) != 0)
maxpagesize = bed->maxpagesize;
off = bed->s->sizeof_ehdr;
off += alloc * bed->s->sizeof_phdr;
if (header_pad < (bfd_vma) off)
header_pad = 0;
else
header_pad -= off;
off += header_pad;
for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
m != NULL;
m = m->next, p++, j++)
{
asection **secpp;
bfd_vma off_adjust;
bfd_boolean no_contents;
/* If elf_segment_map is not from map_sections_to_segments, the
sections may not be correctly ordered. NOTE: sorting should
not be done to the PT_NOTE section of a corefile, which may
contain several pseudo-sections artificially created by bfd.
Sorting these pseudo-sections breaks things badly. */
if (m->count > 1
&& !(elf_elfheader (abfd)->e_type == ET_CORE
&& m->p_type == PT_NOTE))
qsort (m->sections, (size_t) m->count, sizeof (asection *),
elf_sort_sections);
/* An ELF segment (described by Elf_Internal_Phdr) may contain a
number of sections with contents contributing to both p_filesz
and p_memsz, followed by a number of sections with no contents
that just contribute to p_memsz. In this loop, OFF tracks next
available file offset for PT_LOAD and PT_NOTE segments. */
p->p_type = m->p_type;
p->p_flags = m->p_flags;
if (m->count == 0)
p->p_vaddr = 0;
else
p->p_vaddr = m->sections[0]->vma - m->p_vaddr_offset;
if (m->p_paddr_valid)
p->p_paddr = m->p_paddr;
else if (m->count == 0)
p->p_paddr = 0;
else
p->p_paddr = m->sections[0]->lma - m->p_vaddr_offset;
if (p->p_type == PT_LOAD
&& (abfd->flags & D_PAGED) != 0)
{
/* p_align in demand paged PT_LOAD segments effectively stores
the maximum page size. When copying an executable with
objcopy, we set m->p_align from the input file. Use this
value for maxpagesize rather than bed->maxpagesize, which
may be different. Note that we use maxpagesize for PT_TLS
segment alignment later in this function, so we are relying
on at least one PT_LOAD segment appearing before a PT_TLS
segment. */
if (m->p_align_valid)
maxpagesize = m->p_align;
p->p_align = maxpagesize;
}
else if (m->p_align_valid)
p->p_align = m->p_align;
else if (m->count == 0)
p->p_align = 1 << bed->s->log_file_align;
else
p->p_align = 0;
no_contents = FALSE;
off_adjust = 0;
if (p->p_type == PT_LOAD
&& m->count > 0)
{
bfd_size_type align;
unsigned int align_power = 0;
if (m->p_align_valid)
align = p->p_align;
else
{
for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
{
unsigned int secalign;
secalign = bfd_get_section_alignment (abfd, *secpp);
if (secalign > align_power)
align_power = secalign;
}
align = (bfd_size_type) 1 << align_power;
if (align < maxpagesize)
align = maxpagesize;
}
for (i = 0; i < m->count; i++)
if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
/* If we aren't making room for this section, then
it must be SHT_NOBITS regardless of what we've
set via struct bfd_elf_special_section. */
elf_section_type (m->sections[i]) = SHT_NOBITS;
/* Find out whether this segment contains any loadable
sections. */
no_contents = TRUE;
for (i = 0; i < m->count; i++)
if (elf_section_type (m->sections[i]) != SHT_NOBITS)
{
no_contents = FALSE;
break;
}
off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
off += off_adjust;
if (no_contents)
{
/* We shouldn't need to align the segment on disk since
the segment doesn't need file space, but the gABI
arguably requires the alignment and glibc ld.so
checks it. So to comply with the alignment
requirement but not waste file space, we adjust
p_offset for just this segment. (OFF_ADJUST is
subtracted from OFF later.) This may put p_offset
past the end of file, but that shouldn't matter. */
}
else
off_adjust = 0;
}
/* Make sure the .dynamic section is the first section in the
PT_DYNAMIC segment. */
else if (p->p_type == PT_DYNAMIC
&& m->count > 1
&& strcmp (m->sections[0]->name, ".dynamic") != 0)
{
_bfd_error_handler
(_("%B: The first section in the PT_DYNAMIC segment is not the .dynamic section"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Set the note section type to SHT_NOTE. */
else if (p->p_type == PT_NOTE)
for (i = 0; i < m->count; i++)
elf_section_type (m->sections[i]) = SHT_NOTE;
p->p_offset = 0;
p->p_filesz = 0;
p->p_memsz = 0;
if (m->includes_filehdr)
{
if (!m->p_flags_valid)
p->p_flags |= PF_R;
p->p_filesz = bed->s->sizeof_ehdr;
p->p_memsz = bed->s->sizeof_ehdr;
if (m->count > 0)
{
BFD_ASSERT (p->p_type == PT_LOAD);
if (p->p_vaddr < (bfd_vma) off)
{
(*_bfd_error_handler)
(_("%B: Not enough room for program headers, try linking with -N"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
p->p_vaddr -= off;
if (!m->p_paddr_valid)
p->p_paddr -= off;
}
}
if (m->includes_phdrs)
{
if (!m->p_flags_valid)
p->p_flags |= PF_R;
if (!m->includes_filehdr)
{
p->p_offset = bed->s->sizeof_ehdr;
if (m->count > 0)
{