Line 1... |
Line 1... |
/* ELF executable support for BFD.
|
/* ELF executable support for BFD.
|
|
|
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
|
Free Software Foundation, Inc.
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
Line 256... |
Line 257... |
{
|
{
|
/* I think this can be done just like an object file. */
|
/* I think this can be done just like an object file. */
|
return bfd_elf_make_generic_object (abfd);
|
return bfd_elf_make_generic_object (abfd);
|
}
|
}
|
|
|
char *
|
static char *
|
bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
|
bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
|
{
|
{
|
Elf_Internal_Shdr **i_shdrp;
|
Elf_Internal_Shdr **i_shdrp;
|
bfd_byte *shstrtab = NULL;
|
bfd_byte *shstrtab = NULL;
|
file_ptr offset;
|
file_ptr offset;
|
Line 279... |
Line 280... |
offset = i_shdrp[shindex]->sh_offset;
|
offset = i_shdrp[shindex]->sh_offset;
|
shstrtabsize = i_shdrp[shindex]->sh_size;
|
shstrtabsize = i_shdrp[shindex]->sh_size;
|
|
|
/* Allocate and clear an extra byte at the end, to prevent crashes
|
/* Allocate and clear an extra byte at the end, to prevent crashes
|
in case the string table is not terminated. */
|
in case the string table is not terminated. */
|
if (shstrtabsize + 1 == 0
|
if (shstrtabsize + 1 <= 1
|
|| (shstrtab = bfd_alloc (abfd, shstrtabsize + 1)) == NULL
|
|| (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
|
|| bfd_seek (abfd, offset, SEEK_SET) != 0)
|
|| bfd_seek (abfd, offset, SEEK_SET) != 0)
|
shstrtab = NULL;
|
shstrtab = NULL;
|
else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
|
else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
|
{
|
{
|
if (bfd_get_error () != bfd_error_system_call)
|
if (bfd_get_error () != bfd_error_system_call)
|
bfd_set_error (bfd_error_file_truncated);
|
bfd_set_error (bfd_error_file_truncated);
|
shstrtab = NULL;
|
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
|
else
|
shstrtab[shstrtabsize] = '\0';
|
shstrtab[shstrtabsize] = '\0';
|
i_shdrp[shindex]->contents = shstrtab;
|
i_shdrp[shindex]->contents = shstrtab;
|
}
|
}
|
Line 324... |
Line 329... |
(_("%B: invalid string offset %u >= %lu for section `%s'"),
|
(_("%B: invalid string offset %u >= %lu for section `%s'"),
|
abfd, strindex, (unsigned long) hdr->sh_size,
|
abfd, strindex, (unsigned long) hdr->sh_size,
|
(shindex == shstrndx && strindex == hdr->sh_name
|
(shindex == shstrndx && strindex == hdr->sh_name
|
? ".shstrtab"
|
? ".shstrtab"
|
: bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
|
: bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
|
return "";
|
return NULL;
|
}
|
}
|
|
|
return ((char *) hdr->contents) + strindex;
|
return ((char *) hdr->contents) + strindex;
|
}
|
}
|
|
|
Line 352... |
Line 357... |
Elf_Internal_Shdr *shndx_hdr;
|
Elf_Internal_Shdr *shndx_hdr;
|
void *alloc_ext;
|
void *alloc_ext;
|
const bfd_byte *esym;
|
const bfd_byte *esym;
|
Elf_External_Sym_Shndx *alloc_extshndx;
|
Elf_External_Sym_Shndx *alloc_extshndx;
|
Elf_External_Sym_Shndx *shndx;
|
Elf_External_Sym_Shndx *shndx;
|
|
Elf_Internal_Sym *alloc_intsym;
|
Elf_Internal_Sym *isym;
|
Elf_Internal_Sym *isym;
|
Elf_Internal_Sym *isymend;
|
Elf_Internal_Sym *isymend;
|
const struct elf_backend_data *bed;
|
const struct elf_backend_data *bed;
|
size_t extsym_size;
|
size_t extsym_size;
|
bfd_size_type amt;
|
bfd_size_type amt;
|
Line 373... |
Line 379... |
shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
|
shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
|
|
|
/* Read the symbols. */
|
/* Read the symbols. */
|
alloc_ext = NULL;
|
alloc_ext = NULL;
|
alloc_extshndx = NULL;
|
alloc_extshndx = NULL;
|
|
alloc_intsym = NULL;
|
bed = get_elf_backend_data (ibfd);
|
bed = get_elf_backend_data (ibfd);
|
extsym_size = bed->s->sizeof_sym;
|
extsym_size = bed->s->sizeof_sym;
|
amt = symcount * extsym_size;
|
amt = symcount * extsym_size;
|
pos = symtab_hdr->sh_offset + symoffset * extsym_size;
|
pos = symtab_hdr->sh_offset + symoffset * extsym_size;
|
if (extsym_buf == NULL)
|
if (extsym_buf == NULL)
|
Line 398... |
Line 405... |
{
|
{
|
amt = symcount * sizeof (Elf_External_Sym_Shndx);
|
amt = symcount * sizeof (Elf_External_Sym_Shndx);
|
pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
|
pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
|
if (extshndx_buf == NULL)
|
if (extshndx_buf == NULL)
|
{
|
{
|
alloc_extshndx = bfd_malloc2 (symcount,
|
alloc_extshndx = (Elf_External_Sym_Shndx *)
|
sizeof (Elf_External_Sym_Shndx));
|
bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx));
|
extshndx_buf = alloc_extshndx;
|
extshndx_buf = alloc_extshndx;
|
}
|
}
|
if (extshndx_buf == NULL
|
if (extshndx_buf == NULL
|
|| bfd_seek (ibfd, pos, SEEK_SET) != 0
|
|| bfd_seek (ibfd, pos, SEEK_SET) != 0
|
|| bfd_bread (extshndx_buf, amt, ibfd) != amt)
|
|| bfd_bread (extshndx_buf, amt, ibfd) != amt)
|
Line 413... |
Line 420... |
}
|
}
|
}
|
}
|
|
|
if (intsym_buf == NULL)
|
if (intsym_buf == NULL)
|
{
|
{
|
intsym_buf = bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
|
alloc_intsym = (Elf_Internal_Sym *)
|
|
bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
|
|
intsym_buf = alloc_intsym;
|
if (intsym_buf == NULL)
|
if (intsym_buf == NULL)
|
goto out;
|
goto out;
|
}
|
}
|
|
|
/* Convert the symbols to internal form. */
|
/* Convert the symbols to internal form. */
|
isymend = intsym_buf + symcount;
|
isymend = intsym_buf + symcount;
|
for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf;
|
for (esym = (const bfd_byte *) extsym_buf, isym = intsym_buf,
|
|
shndx = extshndx_buf;
|
isym < isymend;
|
isym < isymend;
|
esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
|
esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
|
if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
|
if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
|
{
|
{
|
symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
|
symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
|
(*_bfd_error_handler) (_("%B symbol number %lu references "
|
(*_bfd_error_handler) (_("%B symbol number %lu references "
|
"nonexistent SHT_SYMTAB_SHNDX section"),
|
"nonexistent SHT_SYMTAB_SHNDX section"),
|
ibfd, (unsigned long) symoffset);
|
ibfd, (unsigned long) symoffset);
|
|
if (alloc_intsym != NULL)
|
|
free (alloc_intsym);
|
intsym_buf = NULL;
|
intsym_buf = NULL;
|
goto out;
|
goto out;
|
}
|
}
|
|
|
out:
|
out:
|
Line 455... |
Line 467... |
unsigned int iname = isym->st_name;
|
unsigned int iname = isym->st_name;
|
unsigned int shindex = symtab_hdr->sh_link;
|
unsigned int shindex = symtab_hdr->sh_link;
|
|
|
if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION
|
if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION
|
/* Check for a bogus st_shndx to avoid crashing. */
|
/* Check for a bogus st_shndx to avoid crashing. */
|
&& isym->st_shndx < elf_numsections (abfd)
|
&& isym->st_shndx < elf_numsections (abfd))
|
&& !(isym->st_shndx >= SHN_LORESERVE && isym->st_shndx <= SHN_HIRESERVE))
|
|
{
|
{
|
iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
|
iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
|
shindex = elf_elfheader (abfd)->e_shstrndx;
|
shindex = elf_elfheader (abfd)->e_shstrndx;
|
}
|
}
|
|
|
Line 493... |
Line 504... |
Elf_External_Sym_Shndx eshndx;
|
Elf_External_Sym_Shndx eshndx;
|
Elf_Internal_Sym isym;
|
Elf_Internal_Sym isym;
|
|
|
/* First we need to ensure the symbol table is available. Make sure
|
/* First we need to ensure the symbol table is available. Make sure
|
that it is a symbol table section. */
|
that it is a symbol table section. */
|
|
if (ghdr->sh_link >= elf_numsections (abfd))
|
|
return NULL;
|
hdr = elf_elfsections (abfd) [ghdr->sh_link];
|
hdr = elf_elfsections (abfd) [ghdr->sh_link];
|
if (hdr->sh_type != SHT_SYMTAB
|
if (hdr->sh_type != SHT_SYMTAB
|
|| ! bfd_section_from_shdr (abfd, ghdr->sh_link))
|
|| ! bfd_section_from_shdr (abfd, ghdr->sh_link))
|
return NULL;
|
return NULL;
|
|
|
Line 551... |
Line 564... |
/* We keep a list of elf section headers for group sections,
|
/* We keep a list of elf section headers for group sections,
|
so we can find them quickly. */
|
so we can find them quickly. */
|
bfd_size_type amt;
|
bfd_size_type amt;
|
|
|
elf_tdata (abfd)->num_group = num_group;
|
elf_tdata (abfd)->num_group = num_group;
|
elf_tdata (abfd)->group_sect_ptr
|
elf_tdata (abfd)->group_sect_ptr = (Elf_Internal_Shdr **)
|
= bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
|
bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
|
if (elf_tdata (abfd)->group_sect_ptr == NULL)
|
if (elf_tdata (abfd)->group_sect_ptr == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
num_group = 0;
|
num_group = 0;
|
for (i = 0; i < shnum; i++)
|
for (i = 0; i < shnum; i++)
|
Line 573... |
Line 586... |
num_group += 1;
|
num_group += 1;
|
|
|
/* Read the raw contents. */
|
/* Read the raw contents. */
|
BFD_ASSERT (sizeof (*dest) >= 4);
|
BFD_ASSERT (sizeof (*dest) >= 4);
|
amt = shdr->sh_size * sizeof (*dest) / 4;
|
amt = shdr->sh_size * sizeof (*dest) / 4;
|
shdr->contents = bfd_alloc2 (abfd, shdr->sh_size,
|
shdr->contents = (unsigned char *)
|
sizeof (*dest) / 4);
|
bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
|
/* PR binutils/4110: Handle corrupt group headers. */
|
/* PR binutils/4110: Handle corrupt group headers. */
|
if (shdr->contents == NULL)
|
if (shdr->contents == NULL)
|
{
|
{
|
_bfd_error_handler
|
_bfd_error_handler
|
(_("%B: Corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
|
(_("%B: Corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
|
Line 711... |
Line 724... |
/* FIXME: The old Intel compiler and old strip/objcopy may
|
/* FIXME: The old Intel compiler and old strip/objcopy may
|
not set the sh_link or sh_info fields. Hence we could
|
not set the sh_link or sh_info fields. Hence we could
|
get the situation where elfsec is 0. */
|
get the situation where elfsec is 0. */
|
if (elfsec == 0)
|
if (elfsec == 0)
|
{
|
{
|
const struct elf_backend_data *bed
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
= get_elf_backend_data (abfd);
|
|
if (bed->link_order_error_handler)
|
if (bed->link_order_error_handler)
|
bed->link_order_error_handler
|
bed->link_order_error_handler
|
(_("%B: warning: sh_link not set for section `%A'"),
|
(_("%B: warning: sh_link not set for section `%A'"),
|
abfd, s);
|
abfd, s);
|
}
|
}
|
else
|
else
|
{
|
{
|
asection *link;
|
asection *link = NULL;
|
|
|
|
if (elfsec < elf_numsections (abfd))
|
|
{
|
this_hdr = elf_elfsections (abfd)[elfsec];
|
this_hdr = elf_elfsections (abfd)[elfsec];
|
|
link = this_hdr->bfd_section;
|
|
}
|
|
|
/* PR 1991, 2008:
|
/* PR 1991, 2008:
|
Some strip/objcopy may leave an incorrect value in
|
Some strip/objcopy may leave an incorrect value in
|
sh_link. We don't want to proceed. */
|
sh_link. We don't want to proceed. */
|
link = this_hdr->bfd_section;
|
|
if (link == NULL)
|
if (link == NULL)
|
{
|
{
|
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
(_("%B: sh_link [%d] in section `%A' is incorrect"),
|
(_("%B: sh_link [%d] in section `%A' is incorrect"),
|
s->owner, s, elfsec);
|
s->owner, s, elfsec);
|
Line 823... |
Line 838... |
newsect->filepos = hdr->sh_offset;
|
newsect->filepos = hdr->sh_offset;
|
|
|
if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr)
|
if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr)
|
|| ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
|
|| ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
|
|| ! bfd_set_section_alignment (abfd, newsect,
|
|| ! bfd_set_section_alignment (abfd, newsect,
|
bfd_log2 ((bfd_vma) hdr->sh_addralign)))
|
bfd_log2 (hdr->sh_addralign)))
|
return FALSE;
|
return FALSE;
|
|
|
flags = SEC_NO_FLAGS;
|
flags = SEC_NO_FLAGS;
|
if (hdr->sh_type != SHT_NOBITS)
|
if (hdr->sh_type != SHT_NOBITS)
|
flags |= SEC_HAS_CONTENTS;
|
flags |= SEC_HAS_CONTENTS;
|
Line 881... |
Line 896... |
{ NULL, 0 }, /* 'n' */
|
{ NULL, 0 }, /* 'n' */
|
{ NULL, 0 }, /* 'o' */
|
{ NULL, 0 }, /* 'o' */
|
{ NULL, 0 }, /* 'p' */
|
{ NULL, 0 }, /* 'p' */
|
{ NULL, 0 }, /* 'q' */
|
{ NULL, 0 }, /* 'q' */
|
{ NULL, 0 }, /* 'r' */
|
{ NULL, 0 }, /* 'r' */
|
{ STRING_COMMA_LEN ("stab") } /* 's' */
|
{ 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] == '.')
|
if (name [0] == '.')
|
{
|
{
|
int i = name [1] - 'd';
|
int i = name [1] - 'd';
|
Line 919... |
Line 941... |
/* We do not parse the PT_NOTE segments as we are interested even in the
|
/* 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.
|
separate debug info files which may have the segments offsets corrupted.
|
PT_NOTEs from the core files are currently not parsed using BFD. */
|
PT_NOTEs from the core files are currently not parsed using BFD. */
|
if (hdr->sh_type == SHT_NOTE)
|
if (hdr->sh_type == SHT_NOTE)
|
{
|
{
|
char *contents;
|
bfd_byte *contents;
|
|
|
contents = bfd_malloc (hdr->sh_size);
|
if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
|
if (!contents)
|
|
return FALSE;
|
return FALSE;
|
|
|
if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
|
elf_parse_notes (abfd, (char *) contents, hdr->sh_size, -1);
|
hdr->sh_size)
|
|
|| !elf_parse_notes (abfd, contents, hdr->sh_size, -1))
|
|
{
|
|
free (contents);
|
|
return FALSE;
|
|
}
|
|
|
|
free (contents);
|
free (contents);
|
}
|
}
|
|
|
if ((flags & SEC_ALLOC) != 0)
|
if ((flags & SEC_ALLOC) != 0)
|
{
|
{
|
Elf_Internal_Phdr *phdr;
|
Elf_Internal_Phdr *phdr;
|
unsigned int i;
|
unsigned int i, nload;
|
|
|
/* Look through the phdrs to see if we need to adjust the lma.
|
/* Some ELF linkers produce binaries with all the program header
|
If all the p_paddr fields are zero, we ignore them, since
|
p_paddr fields zero. If we have such a binary with more than
|
some ELF linkers produce such output. */
|
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;
|
phdr = elf_tdata (abfd)->phdr;
|
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
|
for (nload = 0, i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
|
{
|
|
if (phdr->p_paddr != 0)
|
if (phdr->p_paddr != 0)
|
break;
|
break;
|
}
|
else if (phdr->p_type == PT_LOAD && phdr->p_memsz != 0)
|
if (i < elf_elfheader (abfd)->e_phnum)
|
++nload;
|
{
|
if (i >= elf_elfheader (abfd)->e_phnum && nload > 1)
|
|
return TRUE;
|
|
|
phdr = elf_tdata (abfd)->phdr;
|
phdr = elf_tdata (abfd)->phdr;
|
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
|
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
|
{
|
{
|
/* This section is part of this segment if its file
|
|
offset plus size lies within the segment's memory
|
|
span and, if the section is loaded, the extent of the
|
|
loaded data lies within the extent of the segment.
|
|
|
|
Note - we used to check the p_paddr field as well, and
|
|
refuse to set the LMA if it was 0. This is wrong
|
|
though, as a perfectly valid initialised segment can
|
|
have a p_paddr of zero. Some architectures, eg ARM,
|
|
place special significance on the address 0 and
|
|
executables need to be able to have a segment which
|
|
covers this address. */
|
|
if (phdr->p_type == PT_LOAD
|
if (phdr->p_type == PT_LOAD
|
&& (bfd_vma) hdr->sh_offset >= phdr->p_offset
|
&& ELF_IS_SECTION_IN_SEGMENT (hdr, phdr))
|
&& (hdr->sh_offset + hdr->sh_size
|
|
<= phdr->p_offset + phdr->p_memsz)
|
|
&& ((flags & SEC_LOAD) == 0
|
|
|| (hdr->sh_offset + hdr->sh_size
|
|
<= phdr->p_offset + phdr->p_filesz)))
|
|
{
|
{
|
if ((flags & SEC_LOAD) == 0)
|
if ((flags & SEC_LOAD) == 0)
|
newsect->lma = (phdr->p_paddr
|
newsect->lma = (phdr->p_paddr
|
+ hdr->sh_addr - phdr->p_vaddr);
|
+ hdr->sh_addr - phdr->p_vaddr);
|
else
|
else
|
Line 1000... |
Line 999... |
<= phdr->p_vaddr + phdr->p_memsz))
|
<= phdr->p_vaddr + phdr->p_memsz))
|
break;
|
break;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/*
|
|
INTERNAL_FUNCTION
|
|
bfd_elf_find_section
|
|
|
|
SYNOPSIS
|
|
struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name);
|
|
|
|
DESCRIPTION
|
|
Helper functions for GDB to locate the string tables.
|
|
Since BFD hides string tables from callers, GDB needs to use an
|
|
internal hook to find them. Sun's .stabstr, in particular,
|
|
isn't even pointed to by the .stab section, so ordinary
|
|
mechanisms wouldn't work to find it, even if we had some.
|
|
*/
|
|
|
|
struct elf_internal_shdr *
|
|
bfd_elf_find_section (bfd *abfd, char *name)
|
|
{
|
|
Elf_Internal_Shdr **i_shdrp;
|
|
char *shstrtab;
|
|
unsigned int max;
|
|
unsigned int i;
|
|
|
|
i_shdrp = elf_elfsections (abfd);
|
|
if (i_shdrp != NULL)
|
|
{
|
|
shstrtab = bfd_elf_get_str_section (abfd,
|
|
elf_elfheader (abfd)->e_shstrndx);
|
|
if (shstrtab != NULL)
|
|
{
|
|
max = elf_numsections (abfd);
|
|
for (i = 1; i < max; i++)
|
|
if (!strcmp (&shstrtab[i_shdrp[i]->sh_name], name))
|
|
return i_shdrp[i];
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const char *const bfd_elf_section_type_names[] = {
|
const char *const bfd_elf_section_type_names[] = {
|
"SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB",
|
"SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB",
|
"SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE",
|
"SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE",
|
"SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
|
"SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
|
};
|
};
|
Line 1132... |
Line 1091... |
/* Print out the program headers. */
|
/* Print out the program headers. */
|
|
|
bfd_boolean
|
bfd_boolean
|
_bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
|
_bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
|
{
|
{
|
FILE *f = farg;
|
FILE *f = (FILE *) farg;
|
Elf_Internal_Phdr *p;
|
Elf_Internal_Phdr *p;
|
asection *s;
|
asection *s;
|
bfd_byte *dynbuf = NULL;
|
bfd_byte *dynbuf = NULL;
|
|
|
p = elf_tdata (abfd)->phdr;
|
p = elf_tdata (abfd)->phdr;
|
Line 1178... |
Line 1137... |
}
|
}
|
|
|
s = bfd_get_section_by_name (abfd, ".dynamic");
|
s = bfd_get_section_by_name (abfd, ".dynamic");
|
if (s != NULL)
|
if (s != NULL)
|
{
|
{
|
int elfsec;
|
unsigned int elfsec;
|
unsigned long shlink;
|
unsigned long shlink;
|
bfd_byte *extdyn, *extdynend;
|
bfd_byte *extdyn, *extdynend;
|
size_t extdynsize;
|
size_t extdynsize;
|
void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
|
void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
|
|
|
Line 1190... |
Line 1149... |
|
|
if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
|
if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
|
goto error_return;
|
goto error_return;
|
|
|
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
|
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
|
if (elfsec == -1)
|
if (elfsec == SHN_BAD)
|
goto error_return;
|
goto error_return;
|
shlink = elf_elfsections (abfd)[elfsec]->sh_link;
|
shlink = elf_elfsections (abfd)[elfsec]->sh_link;
|
|
|
extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
|
extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
|
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
|
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
|
Line 1202... |
Line 1161... |
extdyn = dynbuf;
|
extdyn = dynbuf;
|
extdynend = extdyn + s->size;
|
extdynend = extdyn + s->size;
|
for (; extdyn < extdynend; extdyn += extdynsize)
|
for (; extdyn < extdynend; extdyn += extdynsize)
|
{
|
{
|
Elf_Internal_Dyn dyn;
|
Elf_Internal_Dyn dyn;
|
const char *name;
|
const char *name = "";
|
char ab[20];
|
char ab[20];
|
bfd_boolean stringp;
|
bfd_boolean stringp;
|
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
|
|
(*swap_dyn_in) (abfd, extdyn, &dyn);
|
(*swap_dyn_in) (abfd, extdyn, &dyn);
|
|
|
if (dyn.d_tag == DT_NULL)
|
if (dyn.d_tag == DT_NULL)
|
break;
|
break;
|
|
|
stringp = FALSE;
|
stringp = FALSE;
|
switch (dyn.d_tag)
|
switch (dyn.d_tag)
|
{
|
{
|
default:
|
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);
|
sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
|
name = ab;
|
name = ab;
|
|
}
|
break;
|
break;
|
|
|
case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
|
case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
|
case DT_PLTRELSZ: name = "PLTRELSZ"; break;
|
case DT_PLTRELSZ: name = "PLTRELSZ"; break;
|
case DT_PLTGOT: name = "PLTGOT"; break;
|
case DT_PLTGOT: name = "PLTGOT"; break;
|
Line 1279... |
Line 1245... |
case DT_USED: name = "USED"; break;
|
case DT_USED: name = "USED"; break;
|
case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
|
case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
|
case DT_GNU_HASH: name = "GNU_HASH"; break;
|
case DT_GNU_HASH: name = "GNU_HASH"; break;
|
}
|
}
|
|
|
fprintf (f, " %-11s ", name);
|
fprintf (f, " %-20s ", name);
|
if (! stringp)
|
if (! stringp)
|
fprintf (f, "0x%lx", (unsigned long) dyn.d_un.d_val);
|
{
|
|
fprintf (f, "0x");
|
|
bfd_fprintf_vma (abfd, f, dyn.d_un.d_val);
|
|
}
|
else
|
else
|
{
|
{
|
const char *string;
|
const char *string;
|
unsigned int tagv = dyn.d_un.d_val;
|
unsigned int tagv = dyn.d_un.d_val;
|
|
|
Line 1365... |
Line 1334... |
bfd_elf_print_symbol (bfd *abfd,
|
bfd_elf_print_symbol (bfd *abfd,
|
void *filep,
|
void *filep,
|
asymbol *symbol,
|
asymbol *symbol,
|
bfd_print_symbol_type how)
|
bfd_print_symbol_type how)
|
{
|
{
|
FILE *file = filep;
|
FILE *file = (FILE *) filep;
|
switch (how)
|
switch (how)
|
{
|
{
|
case bfd_print_symbol_name:
|
case bfd_print_symbol_name:
|
fprintf (file, "%s", symbol->name);
|
fprintf (file, "%s", symbol->name);
|
break;
|
break;
|
case bfd_print_symbol_more:
|
case bfd_print_symbol_more:
|
fprintf (file, "elf ");
|
fprintf (file, "elf ");
|
bfd_fprintf_vma (abfd, file, symbol->value);
|
bfd_fprintf_vma (abfd, file, symbol->value);
|
fprintf (file, " %lx", (long) symbol->flags);
|
fprintf (file, " %lx", (unsigned long) symbol->flags);
|
break;
|
break;
|
case bfd_print_symbol_all:
|
case bfd_print_symbol_all:
|
{
|
{
|
const char *section_name;
|
const char *section_name;
|
const char *name = NULL;
|
const char *name = NULL;
|
Line 1509... |
Line 1478... |
/* Create a new bfd section from an ELF section header. */
|
/* Create a new bfd section from an ELF section header. */
|
|
|
bfd_boolean
|
bfd_boolean
|
bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
|
bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
|
{
|
{
|
Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
|
Elf_Internal_Shdr *hdr;
|
Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
|
Elf_Internal_Ehdr *ehdr;
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
const struct elf_backend_data *bed;
|
const char *name;
|
const char *name;
|
|
|
name = bfd_elf_string_from_elf_section (abfd,
|
if (shindex >= elf_numsections (abfd))
|
elf_elfheader (abfd)->e_shstrndx,
|
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);
|
hdr->sh_name);
|
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
|
bed = get_elf_backend_data (abfd);
|
switch (hdr->sh_type)
|
switch (hdr->sh_type)
|
{
|
{
|
case SHT_NULL:
|
case SHT_NULL:
|
/* Inactive section. Throw it away. */
|
/* Inactive section. Throw it away. */
|
return TRUE;
|
return TRUE;
|
Line 1540... |
Line 1514... |
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
|
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
|
|
|
case SHT_DYNAMIC: /* Dynamic linking information. */
|
case SHT_DYNAMIC: /* Dynamic linking information. */
|
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
|
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
|
return FALSE;
|
return FALSE;
|
if (hdr->sh_link > elf_numsections (abfd)
|
if (hdr->sh_link > elf_numsections (abfd))
|
|| elf_elfsections (abfd)[hdr->sh_link] == NULL)
|
{
|
|
/* PR 10478: Accept sparc binaries with a sh_link
|
|
field set to SHN_BEFORE or SHN_AFTER. */
|
|
switch (bfd_get_arch (abfd))
|
|
{
|
|
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;
|
return FALSE;
|
if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
|
else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
|
{
|
{
|
Elf_Internal_Shdr *dynsymhdr;
|
Elf_Internal_Shdr *dynsymhdr;
|
|
|
/* The shared libraries distributed with hpux11 have a bogus
|
/* The shared libraries distributed with hpux11 have a bogus
|
sh_link field for the ".dynamic" section. Find the
|
sh_link field for the ".dynamic" section. Find the
|
Line 1579... |
Line 1567... |
if (elf_onesymtab (abfd) == shindex)
|
if (elf_onesymtab (abfd) == shindex)
|
return TRUE;
|
return TRUE;
|
|
|
if (hdr->sh_entsize != bed->s->sizeof_sym)
|
if (hdr->sh_entsize != bed->s->sizeof_sym)
|
return FALSE;
|
return FALSE;
|
|
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
|
|
return FALSE;
|
BFD_ASSERT (elf_onesymtab (abfd) == 0);
|
BFD_ASSERT (elf_onesymtab (abfd) == 0);
|
elf_onesymtab (abfd) = shindex;
|
elf_onesymtab (abfd) = shindex;
|
elf_tdata (abfd)->symtab_hdr = *hdr;
|
elf_tdata (abfd)->symtab_hdr = *hdr;
|
elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr;
|
elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr;
|
abfd->flags |= HAS_SYMS;
|
abfd->flags |= HAS_SYMS;
|
Line 1720... |
Line 1710... |
!= (bfd_size_type) (hdr->sh_type == SHT_REL
|
!= (bfd_size_type) (hdr->sh_type == SHT_REL
|
? bed->s->sizeof_rel : bed->s->sizeof_rela))
|
? bed->s->sizeof_rel : bed->s->sizeof_rela))
|
return FALSE;
|
return FALSE;
|
|
|
/* Check for a bogus link to avoid crashing. */
|
/* Check for a bogus link to avoid crashing. */
|
if ((hdr->sh_link >= SHN_LORESERVE && hdr->sh_link <= SHN_HIRESERVE)
|
if (hdr->sh_link >= num_sec)
|
|| hdr->sh_link >= num_sec)
|
|
{
|
{
|
((*_bfd_error_handler)
|
((*_bfd_error_handler)
|
(_("%B: invalid link %lu for reloc section %s (index %u)"),
|
(_("%B: invalid link %lu for reloc section %s (index %u)"),
|
abfd, hdr->sh_link, name, shindex));
|
abfd, hdr->sh_link, name, shindex));
|
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
|
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
|
Line 1736... |
Line 1725... |
libraries for Solaris in which some of the objects have
|
libraries for Solaris in which some of the objects have
|
bogus sh_link fields. It would be nice if we could just
|
bogus sh_link fields. It would be nice if we could just
|
reject them, but, unfortunately, some people need to use
|
reject them, but, unfortunately, some people need to use
|
them. We scan through the section headers; if we find only
|
them. We scan through the section headers; if we find only
|
one suitable symbol table, we clobber the sh_link to point
|
one suitable symbol table, we clobber the sh_link to point
|
to it. I hope this doesn't break anything. */
|
to it. I hope this doesn't break anything.
|
if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB
|
|
|
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)
|
&& elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_DYNSYM)
|
{
|
{
|
unsigned int scan;
|
unsigned int scan;
|
int found;
|
int found;
|
|
|
Line 1772... |
Line 1764... |
/* If this reloc section does not use the main symbol table we
|
/* If this reloc section does not use the main symbol table we
|
don't treat it as a reloc section. BFD can't adequately
|
don't treat it as a reloc section. BFD can't adequately
|
represent such a section, so at least for now, we don't
|
represent such a section, so at least for now, we don't
|
try. We just present it as a normal section. We also
|
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
|
can't use it as a reloc section if it points to the null
|
section, an invalid section, or another reloc section. */
|
section, an invalid section, another reloc section, or its
|
|
sh_link points to the null section. */
|
if (hdr->sh_link != elf_onesymtab (abfd)
|
if (hdr->sh_link != elf_onesymtab (abfd)
|
|
|| hdr->sh_link == SHN_UNDEF
|
|| hdr->sh_info == SHN_UNDEF
|
|| hdr->sh_info == SHN_UNDEF
|
|| (hdr->sh_info >= SHN_LORESERVE && hdr->sh_info <= SHN_HIRESERVE)
|
|
|| hdr->sh_info >= num_sec
|
|| hdr->sh_info >= num_sec
|
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
|
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
|
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA)
|
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA)
|
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
|
return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
|
shindex);
|
shindex);
|
Line 1796... |
Line 1789... |
else
|
else
|
{
|
{
|
bfd_size_type amt;
|
bfd_size_type amt;
|
BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
|
BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
|
amt = sizeof (*hdr2);
|
amt = sizeof (*hdr2);
|
hdr2 = bfd_alloc (abfd, amt);
|
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
|
if (hdr2 == NULL)
|
if (hdr2 == NULL)
|
return FALSE;
|
return FALSE;
|
elf_section_data (target_sect)->rel_hdr2 = hdr2;
|
elf_section_data (target_sect)->rel_hdr2 = hdr2;
|
}
|
}
|
*hdr2 = *hdr;
|
*hdr2 = *hdr;
|
Line 1836... |
Line 1829... |
|
|
case SHT_SHLIB:
|
case SHT_SHLIB:
|
return TRUE;
|
return TRUE;
|
|
|
case SHT_GROUP:
|
case SHT_GROUP:
|
/* We need a BFD section for objcopy and relocatable linking,
|
|
and it's handy to have the signature available as the section
|
|
name. */
|
|
if (! IS_VALID_GROUP_SECTION_HEADER (hdr))
|
if (! IS_VALID_GROUP_SECTION_HEADER (hdr))
|
return FALSE;
|
return FALSE;
|
name = group_signature (abfd, hdr);
|
|
if (name == NULL)
|
|
return FALSE;
|
|
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
|
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
|
return FALSE;
|
return FALSE;
|
if (hdr->contents != NULL)
|
if (hdr->contents != NULL)
|
{
|
{
|
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
|
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
|
Line 1936... |
Line 1923... |
}
|
}
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/* Return the section for the local symbol specified by ABFD, R_SYMNDX.
|
/* Return the local symbol specified by ABFD, R_SYMNDX. */
|
Return SEC for sections that have no elf section, and NULL on error. */
|
|
|
|
asection *
|
Elf_Internal_Sym *
|
bfd_section_from_r_symndx (bfd *abfd,
|
bfd_sym_from_r_symndx (struct sym_cache *cache,
|
struct sym_sec_cache *cache,
|
bfd *abfd,
|
asection *sec,
|
|
unsigned long r_symndx)
|
unsigned long r_symndx)
|
{
|
{
|
unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
|
unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
|
asection *s;
|
|
|
|
if (cache->abfd != abfd || cache->indx[ent] != r_symndx)
|
if (cache->abfd != abfd || cache->indx[ent] != r_symndx)
|
{
|
{
|
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
unsigned char esym[sizeof (Elf64_External_Sym)];
|
unsigned char esym[sizeof (Elf64_External_Sym)];
|
Elf_External_Sym_Shndx eshndx;
|
Elf_External_Sym_Shndx eshndx;
|
Elf_Internal_Sym isym;
|
|
|
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
|
if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
|
&isym, esym, &eshndx) == NULL)
|
&cache->sym[ent], esym, &eshndx) == NULL)
|
return NULL;
|
return NULL;
|
|
|
if (cache->abfd != abfd)
|
if (cache->abfd != abfd)
|
{
|
{
|
memset (cache->indx, -1, sizeof (cache->indx));
|
memset (cache->indx, -1, sizeof (cache->indx));
|
cache->abfd = abfd;
|
cache->abfd = abfd;
|
}
|
}
|
cache->indx[ent] = r_symndx;
|
cache->indx[ent] = r_symndx;
|
cache->shndx[ent] = isym.st_shndx;
|
|
}
|
}
|
|
|
s = bfd_section_from_elf_index (abfd, cache->shndx[ent]);
|
return &cache->sym[ent];
|
if (s != NULL)
|
|
return s;
|
|
|
|
return sec;
|
|
}
|
}
|
|
|
/* Given an ELF section number, retrieve the corresponding BFD
|
/* Given an ELF section number, retrieve the corresponding BFD
|
section. */
|
section. */
|
|
|
Line 2096... |
Line 2074... |
{ STRING_COMMA_LEN (".tbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
|
{ 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 },
|
{ STRING_COMMA_LEN (".tdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
|
{ NULL, 0, 0, 0, 0 }
|
{ 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[] =
|
static const struct bfd_elf_special_section *special_sections[] =
|
{
|
{
|
special_sections_b, /* 'b' */
|
special_sections_b, /* 'b' */
|
special_sections_c, /* 'c' */
|
special_sections_c, /* 'c' */
|
special_sections_d, /* 'd' */
|
special_sections_d, /* 'd' */
|
Line 2117... |
Line 2104... |
special_sections_p, /* 'p' */
|
special_sections_p, /* 'p' */
|
NULL, /* 'q' */
|
NULL, /* 'q' */
|
special_sections_r, /* 'r' */
|
special_sections_r, /* 'r' */
|
special_sections_s, /* 's' */
|
special_sections_s, /* 's' */
|
special_sections_t, /* 't' */
|
special_sections_t, /* 't' */
|
|
NULL, /* 'u' */
|
|
NULL, /* 'v' */
|
|
NULL, /* 'w' */
|
|
NULL, /* 'x' */
|
|
NULL, /* 'y' */
|
|
special_sections_z /* 'z' */
|
};
|
};
|
|
|
const struct bfd_elf_special_section *
|
const struct bfd_elf_special_section *
|
_bfd_elf_get_special_section (const char *name,
|
_bfd_elf_get_special_section (const char *name,
|
const struct bfd_elf_special_section *spec,
|
const struct bfd_elf_special_section *spec,
|
Line 2193... |
Line 2186... |
|
|
if (sec->name[0] != '.')
|
if (sec->name[0] != '.')
|
return NULL;
|
return NULL;
|
|
|
i = sec->name[1] - 'b';
|
i = sec->name[1] - 'b';
|
if (i < 0 || i > 't' - 'b')
|
if (i < 0 || i > 'z' - 'b')
|
return NULL;
|
return NULL;
|
|
|
spec = special_sections[i];
|
spec = special_sections[i];
|
|
|
if (spec == NULL)
|
if (spec == NULL)
|
Line 2214... |
Line 2207... |
const struct bfd_elf_special_section *ssect;
|
const struct bfd_elf_special_section *ssect;
|
|
|
sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
|
sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
|
if (sdata == NULL)
|
if (sdata == NULL)
|
{
|
{
|
sdata = bfd_zalloc (abfd, sizeof (*sdata));
|
sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd,
|
|
sizeof (*sdata));
|
if (sdata == NULL)
|
if (sdata == NULL)
|
return FALSE;
|
return FALSE;
|
sec->used_by_bfd = sdata;
|
sec->used_by_bfd = sdata;
|
}
|
}
|
|
|
Line 2270... |
Line 2264... |
|
|
bfd_boolean
|
bfd_boolean
|
_bfd_elf_make_section_from_phdr (bfd *abfd,
|
_bfd_elf_make_section_from_phdr (bfd *abfd,
|
Elf_Internal_Phdr *hdr,
|
Elf_Internal_Phdr *hdr,
|
int index,
|
int index,
|
const char *typename)
|
const char *type_name)
|
{
|
{
|
asection *newsect;
|
asection *newsect;
|
char *name;
|
char *name;
|
char namebuf[64];
|
char namebuf[64];
|
size_t len;
|
size_t len;
|
Line 2284... |
Line 2278... |
&& (hdr->p_filesz > 0)
|
&& (hdr->p_filesz > 0)
|
&& (hdr->p_memsz > hdr->p_filesz));
|
&& (hdr->p_memsz > hdr->p_filesz));
|
|
|
if (hdr->p_filesz > 0)
|
if (hdr->p_filesz > 0)
|
{
|
{
|
sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
|
sprintf (namebuf, "%s%d%s", type_name, index, split ? "a" : "");
|
len = strlen (namebuf) + 1;
|
len = strlen (namebuf) + 1;
|
name = bfd_alloc (abfd, len);
|
name = (char *) bfd_alloc (abfd, len);
|
if (!name)
|
if (!name)
|
return FALSE;
|
return FALSE;
|
memcpy (name, namebuf, len);
|
memcpy (name, namebuf, len);
|
newsect = bfd_make_section (abfd, name);
|
newsect = bfd_make_section (abfd, name);
|
if (newsect == NULL)
|
if (newsect == NULL)
|
Line 2320... |
Line 2314... |
|
|
if (hdr->p_memsz > hdr->p_filesz)
|
if (hdr->p_memsz > hdr->p_filesz)
|
{
|
{
|
bfd_vma align;
|
bfd_vma align;
|
|
|
sprintf (namebuf, "%s%d%s", typename, index, split ? "b" : "");
|
sprintf (namebuf, "%s%d%s", type_name, index, split ? "b" : "");
|
len = strlen (namebuf) + 1;
|
len = strlen (namebuf) + 1;
|
name = bfd_alloc (abfd, len);
|
name = (char *) bfd_alloc (abfd, len);
|
if (!name)
|
if (!name)
|
return FALSE;
|
return FALSE;
|
memcpy (name, namebuf, len);
|
memcpy (name, namebuf, len);
|
newsect = bfd_make_section (abfd, name);
|
newsect = bfd_make_section (abfd, name);
|
if (newsect == NULL)
|
if (newsect == NULL)
|
Line 2421... |
Line 2415... |
{
|
{
|
char *name;
|
char *name;
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
bfd_size_type amt = sizeof ".rela" + strlen (asect->name);
|
bfd_size_type amt = sizeof ".rela" + strlen (asect->name);
|
|
|
name = bfd_alloc (abfd, amt);
|
name = (char *) bfd_alloc (abfd, amt);
|
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
|
sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
|
rel_hdr->sh_name =
|
rel_hdr->sh_name =
|
(unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
|
(unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
|
Line 2434... |
Line 2428... |
return FALSE;
|
return FALSE;
|
rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
|
rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
|
rel_hdr->sh_entsize = (use_rela_p
|
rel_hdr->sh_entsize = (use_rela_p
|
? bed->s->sizeof_rela
|
? bed->s->sizeof_rela
|
: bed->s->sizeof_rel);
|
: bed->s->sizeof_rel);
|
rel_hdr->sh_addralign = 1 << bed->s->log_file_align;
|
rel_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
|
rel_hdr->sh_flags = 0;
|
rel_hdr->sh_flags = 0;
|
rel_hdr->sh_addr = 0;
|
rel_hdr->sh_addr = 0;
|
rel_hdr->sh_size = 0;
|
rel_hdr->sh_size = 0;
|
rel_hdr->sh_offset = 0;
|
rel_hdr->sh_offset = 0;
|
|
|
return TRUE;
|
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. */
|
/* Set up an ELF internal section header for a section. */
|
|
|
static void
|
static void
|
elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
|
elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
|
{
|
{
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
bfd_boolean *failedptr = failedptrarg;
|
bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
|
Elf_Internal_Shdr *this_hdr;
|
Elf_Internal_Shdr *this_hdr;
|
unsigned int sh_type;
|
unsigned int sh_type;
|
|
|
if (*failedptr)
|
if (*failedptr)
|
{
|
{
|
Line 2481... |
Line 2487... |
this_hdr->sh_addr = 0;
|
this_hdr->sh_addr = 0;
|
|
|
this_hdr->sh_offset = 0;
|
this_hdr->sh_offset = 0;
|
this_hdr->sh_size = asect->size;
|
this_hdr->sh_size = asect->size;
|
this_hdr->sh_link = 0;
|
this_hdr->sh_link = 0;
|
this_hdr->sh_addralign = 1 << asect->alignment_power;
|
this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
|
/* The sh_entsize and sh_info fields may have been set already by
|
/* The sh_entsize and sh_info fields may have been set already by
|
copy_private_section_data. */
|
copy_private_section_data. */
|
|
|
this_hdr->bfd_section = asect;
|
this_hdr->bfd_section = asect;
|
this_hdr->contents = NULL;
|
this_hdr->contents = NULL;
|
|
|
/* If the section type is unspecified, we set it based on
|
/* If the section type is unspecified, we set it based on
|
asect->flags. */
|
asect->flags. */
|
if ((asect->flags & SEC_GROUP) != 0)
|
if ((asect->flags & SEC_GROUP) != 0)
|
sh_type = SHT_GROUP;
|
sh_type = SHT_GROUP;
|
else if ((asect->flags & SEC_ALLOC) != 0
|
|
&& (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|
|
|| (asect->flags & SEC_NEVER_LOAD) != 0))
|
|
sh_type = SHT_NOBITS;
|
|
else
|
else
|
sh_type = SHT_PROGBITS;
|
sh_type = bfd_elf_get_default_section_type (asect->flags);
|
|
|
if (this_hdr->sh_type == SHT_NULL)
|
if (this_hdr->sh_type == SHT_NULL)
|
this_hdr->sh_type = sh_type;
|
this_hdr->sh_type = sh_type;
|
else if (this_hdr->sh_type == SHT_NOBITS
|
else if (this_hdr->sh_type == SHT_NOBITS
|
&& sh_type == SHT_PROGBITS
|
&& sh_type == SHT_PROGBITS
|
Line 2645... |
Line 2647... |
asect,
|
asect,
|
asect->use_rela_p))
|
asect->use_rela_p))
|
*failedptr = TRUE;
|
*failedptr = TRUE;
|
}
|
}
|
|
|
/* Fill in the contents of a SHT_GROUP section. */
|
/* 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
|
void
|
bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
|
bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
|
{
|
{
|
bfd_boolean *failedptr = failedptrarg;
|
bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
|
unsigned long symindx;
|
|
asection *elt, *first;
|
asection *elt, *first;
|
unsigned char *loc;
|
unsigned char *loc;
|
bfd_boolean gas;
|
bfd_boolean gas;
|
|
|
/* Ignore linker created group section. See elfNN_ia64_object_p in
|
/* Ignore linker created group section. See elfNN_ia64_object_p in
|
elfxx-ia64.c. */
|
elfxx-ia64.c. */
|
if (((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP)
|
if (((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP)
|
|| *failedptr)
|
|| *failedptr)
|
return;
|
return;
|
|
|
symindx = 0;
|
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)
|
if (elf_group_id (sec) != NULL)
|
symindx = elf_group_id (sec)->udata.i;
|
symindx = elf_group_id (sec)->udata.i;
|
|
|
if (symindx == 0)
|
if (symindx == 0)
|
{
|
{
|
/* If called from the assembler, swap_out_syms will have set up
|
/* If called from the assembler, swap_out_syms will have set up
|
elf_section_syms; If called for "ld -r", use target_index. */
|
elf_section_syms. */
|
if (elf_section_syms (abfd) != NULL)
|
BFD_ASSERT (elf_section_syms (abfd) != NULL);
|
symindx = elf_section_syms (abfd)[sec->index]->udata.i;
|
symindx = elf_section_syms (abfd)[sec->index]->udata.i;
|
else
|
|
symindx = sec->target_index;
|
|
}
|
}
|
elf_section_data (sec)->this_hdr.sh_info = symindx;
|
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. */
|
/* The contents won't be allocated for "ld -r" or objcopy. */
|
gas = TRUE;
|
gas = TRUE;
|
if (sec->contents == NULL)
|
if (sec->contents == NULL)
|
{
|
{
|
gas = FALSE;
|
gas = FALSE;
|
sec->contents = bfd_alloc (abfd, sec->size);
|
sec->contents = (unsigned char *) bfd_alloc (abfd, sec->size);
|
|
|
/* Arrange for the section to be written out. */
|
/* Arrange for the section to be written out. */
|
elf_section_data (sec)->this_hdr.contents = sec->contents;
|
elf_section_data (sec)->this_hdr.contents = sec->contents;
|
if (sec->contents == NULL)
|
if (sec->contents == NULL)
|
{
|
{
|
Line 2709... |
Line 2742... |
while (elt != NULL)
|
while (elt != NULL)
|
{
|
{
|
asection *s;
|
asection *s;
|
unsigned int idx;
|
unsigned int idx;
|
|
|
loc -= 4;
|
|
s = elt;
|
s = elt;
|
|
if (! elf_discarded_section (s))
|
|
{
|
|
loc -= 4;
|
if (!gas)
|
if (!gas)
|
s = s->output_section;
|
s = s->output_section;
|
idx = 0;
|
idx = 0;
|
if (s != NULL)
|
if (s != NULL)
|
idx = elf_section_data (s)->this_idx;
|
idx = elf_section_data (s)->this_idx;
|
H_PUT_32 (abfd, idx, loc);
|
H_PUT_32 (abfd, idx, loc);
|
|
}
|
elt = elf_next_in_group (elt);
|
elt = elf_next_in_group (elt);
|
if (elt == first)
|
if (elt == first)
|
break;
|
break;
|
}
|
}
|
|
|
Line 2740... |
Line 2776... |
struct elf_obj_tdata *t = elf_tdata (abfd);
|
struct elf_obj_tdata *t = elf_tdata (abfd);
|
asection *sec;
|
asection *sec;
|
unsigned int section_number, secn;
|
unsigned int section_number, secn;
|
Elf_Internal_Shdr **i_shdrp;
|
Elf_Internal_Shdr **i_shdrp;
|
struct bfd_elf_section_data *d;
|
struct bfd_elf_section_data *d;
|
|
bfd_boolean need_symtab;
|
|
|
section_number = 1;
|
section_number = 1;
|
|
|
_bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
|
_bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
|
|
|
Line 2762... |
Line 2799... |
/* Remove the linker created SHT_GROUP sections. */
|
/* Remove the linker created SHT_GROUP sections. */
|
bfd_section_list_remove (abfd, sec);
|
bfd_section_list_remove (abfd, sec);
|
abfd->section_count--;
|
abfd->section_count--;
|
}
|
}
|
else
|
else
|
{
|
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
d->this_idx = section_number++;
|
d->this_idx = section_number++;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
for (sec = abfd->sections; sec; sec = sec->next)
|
for (sec = abfd->sections; sec; sec = sec->next)
|
{
|
{
|
d = elf_section_data (sec);
|
d = elf_section_data (sec);
|
|
|
if (d->this_hdr.sh_type != SHT_GROUP)
|
if (d->this_hdr.sh_type != SHT_GROUP)
|
{
|
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
d->this_idx = section_number++;
|
d->this_idx = section_number++;
|
}
|
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
|
if ((sec->flags & SEC_RELOC) == 0)
|
if ((sec->flags & SEC_RELOC) == 0)
|
d->rel_idx = 0;
|
d->rel_idx = 0;
|
else
|
else
|
{
|
{
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
d->rel_idx = section_number++;
|
d->rel_idx = section_number++;
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
|
}
|
}
|
|
|
if (d->rel_hdr2)
|
if (d->rel_hdr2)
|
{
|
{
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
d->rel_idx2 = section_number++;
|
d->rel_idx2 = section_number++;
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name);
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name);
|
}
|
}
|
else
|
else
|
d->rel_idx2 = 0;
|
d->rel_idx2 = 0;
|
}
|
}
|
|
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
t->shstrtab_section = section_number++;
|
t->shstrtab_section = section_number++;
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
|
elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
|
elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
|
|
|
if (bfd_get_symcount (abfd) > 0)
|
need_symtab = (bfd_get_symcount (abfd) > 0
|
|
|| (link_info == NULL
|
|
&& ((abfd->flags & (EXEC_P | DYNAMIC | HAS_RELOC))
|
|
== HAS_RELOC)));
|
|
if (need_symtab)
|
{
|
{
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
t->symtab_section = section_number++;
|
t->symtab_section = section_number++;
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
|
if (section_number > SHN_LORESERVE - 2)
|
if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
|
{
|
{
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
t->symtab_shndx_section = section_number++;
|
t->symtab_shndx_section = section_number++;
|
t->symtab_shndx_hdr.sh_name
|
t->symtab_shndx_hdr.sh_name
|
= (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
|
= (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
|
".symtab_shndx", FALSE);
|
".symtab_shndx", FALSE);
|
if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
|
if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
|
return FALSE;
|
return FALSE;
|
}
|
}
|
if (section_number == SHN_LORESERVE)
|
|
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
t->strtab_section = section_number++;
|
t->strtab_section = section_number++;
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
|
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
|
}
|
}
|
|
|
_bfd_elf_strtab_finalize (elf_shstrtab (abfd));
|
_bfd_elf_strtab_finalize (elf_shstrtab (abfd));
|
t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
|
t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
|
|
|
elf_numsections (abfd) = section_number;
|
elf_numsections (abfd) = section_number;
|
elf_elfheader (abfd)->e_shnum = section_number;
|
elf_elfheader (abfd)->e_shnum = section_number;
|
if (section_number > SHN_LORESERVE)
|
|
elf_elfheader (abfd)->e_shnum -= SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
|
|
/* Set up the list of section header pointers, in agreement with the
|
/* Set up the list of section header pointers, in agreement with the
|
indices. */
|
indices. */
|
i_shdrp = bfd_zalloc2 (abfd, section_number, sizeof (Elf_Internal_Shdr *));
|
i_shdrp = (Elf_Internal_Shdr **) bfd_zalloc2 (abfd, section_number,
|
|
sizeof (Elf_Internal_Shdr *));
|
if (i_shdrp == NULL)
|
if (i_shdrp == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
i_shdrp[0] = bfd_zalloc (abfd, sizeof (Elf_Internal_Shdr));
|
i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd,
|
|
sizeof (Elf_Internal_Shdr));
|
if (i_shdrp[0] == NULL)
|
if (i_shdrp[0] == NULL)
|
{
|
{
|
bfd_release (abfd, i_shdrp);
|
bfd_release (abfd, i_shdrp);
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
elf_elfsections (abfd) = i_shdrp;
|
elf_elfsections (abfd) = i_shdrp;
|
|
|
i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
|
i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
|
if (bfd_get_symcount (abfd) > 0)
|
if (need_symtab)
|
{
|
{
|
i_shdrp[t->symtab_section] = &t->symtab_hdr;
|
i_shdrp[t->symtab_section] = &t->symtab_hdr;
|
if (elf_numsections (abfd) > SHN_LORESERVE)
|
if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
|
{
|
{
|
i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
|
i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
|
t->symtab_shndx_hdr.sh_link = t->symtab_section;
|
t->symtab_shndx_hdr.sh_link = t->symtab_section;
|
}
|
}
|
i_shdrp[t->strtab_section] = &t->strtab_hdr;
|
i_shdrp[t->strtab_section] = &t->strtab_hdr;
|
Line 2995... |
Line 3016... |
{
|
{
|
size_t len;
|
size_t len;
|
char *alc;
|
char *alc;
|
|
|
len = strlen (sec->name);
|
len = strlen (sec->name);
|
alc = bfd_malloc (len - 2);
|
alc = (char *) bfd_malloc (len - 2);
|
if (alc == NULL)
|
if (alc == NULL)
|
return FALSE;
|
return FALSE;
|
memcpy (alc, sec->name, len - 3);
|
memcpy (alc, sec->name, len - 3);
|
alc[len - 3] = '\0';
|
alc[len - 3] = '\0';
|
s = bfd_get_section_by_name (abfd, alc);
|
s = bfd_get_section_by_name (abfd, alc);
|
Line 3071... |
Line 3092... |
/* If the backend has a special mapping, use it. */
|
/* If the backend has a special mapping, use it. */
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
if (bed->elf_backend_sym_is_global)
|
if (bed->elf_backend_sym_is_global)
|
return (*bed->elf_backend_sym_is_global) (abfd, sym);
|
return (*bed->elf_backend_sym_is_global) (abfd, sym);
|
|
|
return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
|
return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
|
|| bfd_is_und_section (bfd_get_section (sym))
|
|| bfd_is_und_section (bfd_get_section (sym))
|
|| bfd_is_com_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
|
/* Don't output section symbols for sections that are not going to be
|
output. Also, don't output section symbols for reloc and other
|
output. */
|
special sections. */
|
|
|
|
static bfd_boolean
|
static bfd_boolean
|
ignore_section_sym (bfd *abfd, asymbol *sym)
|
ignore_section_sym (bfd *abfd, asymbol *sym)
|
{
|
{
|
return ((sym->flags & BSF_SECTION_SYM) != 0
|
return ((sym->flags & BSF_SECTION_SYM) != 0
|
&& (sym->value != 0
|
&& !(sym->section->owner == abfd
|
|| (sym->section->owner != abfd
|
|| (sym->section->output_section->owner == abfd
|
&& (sym->section->output_section->owner != abfd
|
&& sym->section->output_offset == 0)));
|
|| sym->section->output_offset != 0))));
|
|
}
|
}
|
|
|
static bfd_boolean
|
static bfd_boolean
|
elf_map_symbols (bfd *abfd)
|
elf_map_symbols (bfd *abfd)
|
{
|
{
|
Line 3117... |
Line 3136... |
if (max_index < asect->index)
|
if (max_index < asect->index)
|
max_index = asect->index;
|
max_index = asect->index;
|
}
|
}
|
|
|
max_index++;
|
max_index++;
|
sect_syms = bfd_zalloc2 (abfd, max_index, sizeof (asymbol *));
|
sect_syms = (asymbol **) bfd_zalloc2 (abfd, max_index, sizeof (asymbol *));
|
if (sect_syms == NULL)
|
if (sect_syms == NULL)
|
return FALSE;
|
return FALSE;
|
elf_section_syms (abfd) = sect_syms;
|
elf_section_syms (abfd) = sect_syms;
|
elf_num_section_syms (abfd) = max_index;
|
elf_num_section_syms (abfd) = max_index;
|
|
|
Line 3130... |
Line 3149... |
for (idx = 0; idx < symcount; idx++)
|
for (idx = 0; idx < symcount; idx++)
|
{
|
{
|
asymbol *sym = syms[idx];
|
asymbol *sym = syms[idx];
|
|
|
if ((sym->flags & BSF_SECTION_SYM) != 0
|
if ((sym->flags & BSF_SECTION_SYM) != 0
|
|
&& sym->value == 0
|
&& !ignore_section_sym (abfd, sym))
|
&& !ignore_section_sym (abfd, sym))
|
{
|
{
|
asection *sec = sym->section;
|
asection *sec = sym->section;
|
|
|
if (sec->owner != abfd)
|
if (sec->owner != abfd)
|
Line 3168... |
Line 3188... |
num_globals++;
|
num_globals++;
|
}
|
}
|
}
|
}
|
|
|
/* Now sort the symbols so the local symbols are first. */
|
/* Now sort the symbols so the local symbols are first. */
|
new_syms = bfd_alloc2 (abfd, num_locals + num_globals, sizeof (asymbol *));
|
new_syms = (asymbol **) bfd_alloc2 (abfd, num_locals + num_globals,
|
|
sizeof (asymbol *));
|
|
|
if (new_syms == NULL)
|
if (new_syms == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
for (idx = 0; idx < symcount; idx++)
|
for (idx = 0; idx < symcount; idx++)
|
Line 3228... |
Line 3249... |
file_ptr
|
file_ptr
|
_bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp,
|
_bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp,
|
file_ptr offset,
|
file_ptr offset,
|
bfd_boolean align)
|
bfd_boolean align)
|
{
|
{
|
if (align)
|
if (align && i_shdrp->sh_addralign > 1)
|
{
|
offset = BFD_ALIGN (offset, i_shdrp->sh_addralign);
|
unsigned int al;
|
|
|
|
al = i_shdrp->sh_addralign;
|
|
if (al > 1)
|
|
offset = BFD_ALIGN (offset, al);
|
|
}
|
|
i_shdrp->sh_offset = offset;
|
i_shdrp->sh_offset = offset;
|
if (i_shdrp->bfd_section != NULL)
|
if (i_shdrp->bfd_section != NULL)
|
i_shdrp->bfd_section->filepos = offset;
|
i_shdrp->bfd_section->filepos = offset;
|
if (i_shdrp->sh_type != SHT_NOBITS)
|
if (i_shdrp->sh_type != SHT_NOBITS)
|
offset += i_shdrp->sh_size;
|
offset += i_shdrp->sh_size;
|
Line 3256... |
Line 3271... |
{
|
{
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
bfd_boolean failed;
|
bfd_boolean failed;
|
struct bfd_strtab_hash *strtab = NULL;
|
struct bfd_strtab_hash *strtab = NULL;
|
Elf_Internal_Shdr *shstrtab_hdr;
|
Elf_Internal_Shdr *shstrtab_hdr;
|
|
bfd_boolean need_symtab;
|
|
|
if (abfd->output_has_begun)
|
if (abfd->output_has_begun)
|
return TRUE;
|
return TRUE;
|
|
|
/* Do any elf backend specific processing first. */
|
/* Do any elf backend specific processing first. */
|
Line 3280... |
Line 3296... |
|
|
if (!assign_section_numbers (abfd, link_info))
|
if (!assign_section_numbers (abfd, link_info))
|
return FALSE;
|
return FALSE;
|
|
|
/* The backend linker builds symbol table information itself. */
|
/* The backend linker builds symbol table information itself. */
|
if (link_info == NULL && bfd_get_symcount (abfd) > 0)
|
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. */
|
/* Non-zero if doing a relocatable link. */
|
int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
|
int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
|
|
|
if (! swap_out_syms (abfd, &strtab, relocatable_p))
|
if (! swap_out_syms (abfd, &strtab, relocatable_p))
|
Line 3311... |
Line 3331... |
shstrtab_hdr->sh_addralign = 1;
|
shstrtab_hdr->sh_addralign = 1;
|
|
|
if (!assign_file_positions_except_relocs (abfd, link_info))
|
if (!assign_file_positions_except_relocs (abfd, link_info))
|
return FALSE;
|
return FALSE;
|
|
|
if (link_info == NULL && bfd_get_symcount (abfd) > 0)
|
if (need_symtab)
|
{
|
{
|
file_ptr off;
|
file_ptr off;
|
Elf_Internal_Shdr *hdr;
|
Elf_Internal_Shdr *hdr;
|
|
|
off = elf_tdata (abfd)->next_file_pos;
|
off = elf_tdata (abfd)->next_file_pos;
|
Line 3373... |
Line 3393... |
{
|
{
|
/* We need a PT_DYNAMIC segment. */
|
/* We need a PT_DYNAMIC segment. */
|
++segs;
|
++segs;
|
}
|
}
|
|
|
if (info->relro)
|
if (info != NULL && info->relro)
|
{
|
{
|
/* We need a PT_GNU_RELRO segment. */
|
/* We need a PT_GNU_RELRO segment. */
|
++segs;
|
++segs;
|
}
|
}
|
|
|
Line 3478... |
Line 3498... |
asection **hdrpp;
|
asection **hdrpp;
|
bfd_size_type amt;
|
bfd_size_type amt;
|
|
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
amt += (to - from - 1) * sizeof (asection *);
|
amt += (to - from - 1) * sizeof (asection *);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
return NULL;
|
return NULL;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_LOAD;
|
m->p_type = PT_LOAD;
|
for (i = from, hdrpp = sections + from; i < to; i++, hdrpp++)
|
for (i = from, hdrpp = sections + from; i < to; i++, hdrpp++)
|
Line 3505... |
Line 3525... |
struct elf_segment_map *
|
struct elf_segment_map *
|
_bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
|
_bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
|
{
|
{
|
struct elf_segment_map *m;
|
struct elf_segment_map *m;
|
|
|
m = bfd_zalloc (abfd, sizeof (struct elf_segment_map));
|
m = (struct elf_segment_map *) bfd_zalloc (abfd,
|
|
sizeof (struct elf_segment_map));
|
if (m == NULL)
|
if (m == NULL)
|
return NULL;
|
return NULL;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_DYNAMIC;
|
m->p_type = PT_DYNAMIC;
|
m->count = 1;
|
m->count = 1;
|
Line 3596... |
Line 3617... |
asection *dynsec, *eh_frame_hdr;
|
asection *dynsec, *eh_frame_hdr;
|
bfd_size_type amt;
|
bfd_size_type amt;
|
|
|
/* Select the allocated sections, and sort them. */
|
/* Select the allocated sections, and sort them. */
|
|
|
sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *));
|
sections = (asection **) bfd_malloc2 (bfd_count_sections (abfd),
|
|
sizeof (asection *));
|
if (sections == NULL)
|
if (sections == NULL)
|
goto error_return;
|
goto error_return;
|
|
|
i = 0;
|
i = 0;
|
for (s = abfd->sections; s != NULL; s = s->next)
|
for (s = abfd->sections; s != NULL; s = s->next)
|
Line 3626... |
Line 3648... |
section. */
|
section. */
|
s = bfd_get_section_by_name (abfd, ".interp");
|
s = bfd_get_section_by_name (abfd, ".interp");
|
if (s != NULL && (s->flags & SEC_LOAD) != 0)
|
if (s != NULL && (s->flags & SEC_LOAD) != 0)
|
{
|
{
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
goto error_return;
|
goto error_return;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_PHDR;
|
m->p_type = PT_PHDR;
|
/* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */
|
/* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */
|
Line 3640... |
Line 3662... |
|
|
*pm = m;
|
*pm = m;
|
pm = &m->next;
|
pm = &m->next;
|
|
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
goto error_return;
|
goto error_return;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_INTERP;
|
m->p_type = PT_INTERP;
|
m->count = 1;
|
m->count = 1;
|
Line 3704... |
Line 3726... |
/* If this section has a different relation between the
|
/* If this section has a different relation between the
|
virtual address and the load address, then we need a new
|
virtual address and the load address, then we need a new
|
segment. */
|
segment. */
|
new_segment = TRUE;
|
new_segment = TRUE;
|
}
|
}
|
else if (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize)
|
/* In the next test we have to be careful when last_hdr->lma is close
|
< BFD_ALIGN (hdr->lma, maxpagesize))
|
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
|
/* If putting this section in this segment would force us to
|
skip a page in the segment, then we need a new segment. */
|
skip a page in the segment, then we need a new segment. */
|
new_segment = TRUE;
|
new_segment = TRUE;
|
}
|
}
|
Line 3748... |
Line 3777... |
/* Otherwise, we can use the same segment. */
|
/* Otherwise, we can use the same segment. */
|
new_segment = FALSE;
|
new_segment = FALSE;
|
}
|
}
|
|
|
/* Allow interested parties a chance to override our decision. */
|
/* Allow interested parties a chance to override our decision. */
|
if (last_hdr && info->callbacks->override_segment_assignment)
|
if (last_hdr != NULL
|
new_segment = info->callbacks->override_segment_assignment (info, abfd, hdr, last_hdr, new_segment);
|
&& 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 (! new_segment)
|
{
|
{
|
if ((hdr->flags & SEC_READONLY) == 0)
|
if ((hdr->flags & SEC_READONLY) == 0)
|
writable = TRUE;
|
writable = TRUE;
|
Line 3838... |
Line 3872... |
count++;
|
count++;
|
else
|
else
|
break;
|
break;
|
}
|
}
|
amt += (count - 1) * sizeof (asection *);
|
amt += (count - 1) * sizeof (asection *);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
goto error_return;
|
goto error_return;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_NOTE;
|
m->p_type = PT_NOTE;
|
m->count = count;
|
m->count = count;
|
Line 3870... |
Line 3904... |
{
|
{
|
int i;
|
int i;
|
|
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
amt += (tls_count - 1) * sizeof (asection *);
|
amt += (tls_count - 1) * sizeof (asection *);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
goto error_return;
|
goto error_return;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_TLS;
|
m->p_type = PT_TLS;
|
m->count = tls_count;
|
m->count = tls_count;
|
Line 3897... |
Line 3931... |
eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
|
eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
|
if (eh_frame_hdr != NULL
|
if (eh_frame_hdr != NULL
|
&& (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
|
&& (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
|
{
|
{
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
goto error_return;
|
goto error_return;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_GNU_EH_FRAME;
|
m->p_type = PT_GNU_EH_FRAME;
|
m->count = 1;
|
m->count = 1;
|
Line 3912... |
Line 3946... |
}
|
}
|
|
|
if (elf_tdata (abfd)->stack_flags)
|
if (elf_tdata (abfd)->stack_flags)
|
{
|
{
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
goto error_return;
|
goto error_return;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_GNU_STACK;
|
m->p_type = PT_GNU_STACK;
|
m->p_flags = elf_tdata (abfd)->stack_flags;
|
m->p_flags = elf_tdata (abfd)->stack_flags;
|
Line 3924... |
Line 3958... |
|
|
*pm = m;
|
*pm = m;
|
pm = &m->next;
|
pm = &m->next;
|
}
|
}
|
|
|
if (info->relro)
|
if (info != NULL && info->relro)
|
{
|
{
|
for (m = mfirst; m != NULL; m = m->next)
|
for (m = mfirst; m != NULL; m = m->next)
|
{
|
{
|
if (m->p_type == PT_LOAD)
|
if (m->p_type == PT_LOAD)
|
{
|
{
|
Line 3945... |
Line 3979... |
|
|
/* Make a PT_GNU_RELRO segment only when it isn't empty. */
|
/* Make a PT_GNU_RELRO segment only when it isn't empty. */
|
if (m != NULL)
|
if (m != NULL)
|
{
|
{
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
m = bfd_zalloc (abfd, amt);
|
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
if (m == NULL)
|
if (m == NULL)
|
goto error_return;
|
goto error_return;
|
m->next = NULL;
|
m->next = NULL;
|
m->p_type = PT_GNU_RELRO;
|
m->p_type = PT_GNU_RELRO;
|
m->p_flags = PF_R;
|
m->p_flags = PF_R;
|
Line 4106... |
Line 4140... |
Elf_Internal_Phdr *p;
|
Elf_Internal_Phdr *p;
|
file_ptr off;
|
file_ptr off;
|
bfd_size_type maxpagesize;
|
bfd_size_type maxpagesize;
|
unsigned int alloc;
|
unsigned int alloc;
|
unsigned int i, j;
|
unsigned int i, j;
|
|
bfd_vma header_pad = 0;
|
|
|
if (link_info == NULL
|
if (link_info == NULL
|
&& !elf_modify_segment_map (abfd, link_info, FALSE))
|
&& !_bfd_elf_map_sections_to_segments (abfd, link_info))
|
return FALSE;
|
return FALSE;
|
|
|
alloc = 0;
|
alloc = 0;
|
for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
|
for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
|
|
{
|
++alloc;
|
++alloc;
|
|
if (m->header_size)
|
|
header_pad = m->header_size;
|
|
}
|
|
|
elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
|
elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
|
elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
|
elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
|
elf_elfheader (abfd)->e_phnum = alloc;
|
elf_elfheader (abfd)->e_phnum = alloc;
|
|
|
Line 4131... |
Line 4170... |
{
|
{
|
elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
|
elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
phdrs = bfd_alloc2 (abfd, alloc, sizeof (Elf_Internal_Phdr));
|
/* 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;
|
elf_tdata (abfd)->phdr = phdrs;
|
if (phdrs == NULL)
|
if (phdrs == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
maxpagesize = 1;
|
maxpagesize = 1;
|
if ((abfd->flags & D_PAGED) != 0)
|
if ((abfd->flags & D_PAGED) != 0)
|
maxpagesize = bed->maxpagesize;
|
maxpagesize = bed->maxpagesize;
|
|
|
off = bed->s->sizeof_ehdr;
|
off = bed->s->sizeof_ehdr;
|
off += alloc * bed->s->sizeof_phdr;
|
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;
|
for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
|
m != NULL;
|
m != NULL;
|
m = m->next, p++, j++)
|
m = m->next, p++, j++)
|
{
|
{
|
Line 4238... |
Line 4296... |
it must be SHT_NOBITS regardless of what we've
|
it must be SHT_NOBITS regardless of what we've
|
set via struct bfd_elf_special_section. */
|
set via struct bfd_elf_special_section. */
|
elf_section_type (m->sections[i]) = SHT_NOBITS;
|
elf_section_type (m->sections[i]) = SHT_NOBITS;
|
|
|
/* Find out whether this segment contains any loadable
|
/* Find out whether this segment contains any loadable
|
sections. If the first section isn't loadable, the same
|
sections. */
|
holds for any other sections. */
|
|
i = 0;
|
|
while (elf_section_type (m->sections[i]) == SHT_NOBITS)
|
|
{
|
|
/* If a segment starts with .tbss, we need to look
|
|
at the next section to decide whether the segment
|
|
has any loadable sections. */
|
|
if ((elf_section_flags (m->sections[i]) & SHF_TLS) == 0
|
|
|| ++i >= m->count)
|
|
{
|
|
no_contents = TRUE;
|
no_contents = TRUE;
|
|
for (i = 0; i < m->count; i++)
|
|
if (elf_section_type (m->sections[i]) != SHT_NOBITS)
|
|
{
|
|
no_contents = FALSE;
|
break;
|
break;
|
}
|
}
|
}
|
|
|
|
off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
|
off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
|
off += off_adjust;
|
off += off_adjust;
|
if (no_contents)
|
if (no_contents)
|
{
|
{
|
Line 4336... |
Line 4387... |
}
|
}
|
}
|
}
|
|
|
p->p_filesz += alloc * bed->s->sizeof_phdr;
|
p->p_filesz += alloc * bed->s->sizeof_phdr;
|
p->p_memsz += alloc * bed->s->sizeof_phdr;
|
p->p_memsz += alloc * bed->s->sizeof_phdr;
|
|
if (m->count)
|
|
{
|
|
p->p_filesz += header_pad;
|
|
p->p_memsz += header_pad;
|
|
}
|
}
|
}
|
|
|
if (p->p_type == PT_LOAD
|
if (p->p_type == PT_LOAD
|
|| (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core))
|
|| (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core))
|
{
|
{
|
Line 4369... |
Line 4425... |
|
|
sec = *secpp;
|
sec = *secpp;
|
this_hdr = &elf_section_data (sec)->this_hdr;
|
this_hdr = &elf_section_data (sec)->this_hdr;
|
align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
|
align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
|
|
|
if (p->p_type == PT_LOAD
|
if ((p->p_type == PT_LOAD
|
|| p->p_type == PT_TLS)
|
|| p->p_type == PT_TLS)
|
{
|
&& (this_hdr->sh_type != SHT_NOBITS
|
bfd_signed_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
|
|
|
|
if (this_hdr->sh_type != SHT_NOBITS
|
|
|| ((this_hdr->sh_flags & SHF_ALLOC) != 0
|
|| ((this_hdr->sh_flags & SHF_ALLOC) != 0
|
&& ((this_hdr->sh_flags & SHF_TLS) == 0
|
&& ((this_hdr->sh_flags & SHF_TLS) == 0
|
|| p->p_type == PT_TLS)))
|
|| p->p_type == PT_TLS))))
|
{
|
{
|
|
bfd_signed_vma adjust = sec->vma - (p->p_vaddr + p->p_memsz);
|
|
|
if (adjust < 0)
|
if (adjust < 0)
|
{
|
{
|
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
(_("%B: section %A lma 0x%lx overlaps previous sections"),
|
(_("%B: section %A vma 0x%lx overlaps previous sections"),
|
abfd, sec, (unsigned long) sec->lma);
|
abfd, sec, (unsigned long) sec->vma);
|
adjust = 0;
|
adjust = 0;
|
}
|
}
|
p->p_memsz += adjust;
|
p->p_memsz += adjust;
|
|
|
if (this_hdr->sh_type != SHT_NOBITS)
|
if (this_hdr->sh_type != SHT_NOBITS)
|
{
|
{
|
off += adjust;
|
off += adjust;
|
p->p_filesz += adjust;
|
p->p_filesz += adjust;
|
}
|
}
|
}
|
}
|
}
|
|
|
|
if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
|
if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
|
{
|
{
|
/* The section at i == 0 is the one that actually contains
|
/* The section at i == 0 is the one that actually contains
|
everything. */
|
everything. */
|
Line 4551... |
Line 4605... |
|| hdr == i_shdrpp[tdata->symtab_shndx_section]
|
|| hdr == i_shdrpp[tdata->symtab_shndx_section]
|
|| hdr == i_shdrpp[tdata->strtab_section])
|
|| hdr == i_shdrpp[tdata->strtab_section])
|
hdr->sh_offset = -1;
|
hdr->sh_offset = -1;
|
else
|
else
|
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
|
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
|
|
|
if (i == SHN_LORESERVE - 1)
|
|
{
|
|
i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
hdrpp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
}
|
|
}
|
}
|
|
|
/* Now that we have set the section file positions, we can set up
|
/* Now that we have set the section file positions, we can set up
|
the file positions for the non PT_LOAD segments. */
|
the file positions for the non PT_LOAD segments. */
|
count = 0;
|
count = 0;
|
Line 4596... |
Line 4644... |
|
|
for (m = elf_tdata (abfd)->segment_map, p = phdrs;
|
for (m = elf_tdata (abfd)->segment_map, p = phdrs;
|
m != NULL;
|
m != NULL;
|
m = m->next, p++)
|
m = m->next, p++)
|
{
|
{
|
if (m->count != 0)
|
if (p->p_type == PT_GNU_RELRO)
|
{
|
|
if (p->p_type != PT_LOAD
|
|
&& (p->p_type != PT_NOTE
|
|
|| bfd_get_format (abfd) != bfd_core))
|
|
{
|
{
|
Elf_Internal_Shdr *hdr;
|
const Elf_Internal_Phdr *lp;
|
asection *sect;
|
|
|
|
BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
|
BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
|
|
|
sect = m->sections[m->count - 1];
|
if (link_info != NULL)
|
hdr = &elf_section_data (sect)->this_hdr;
|
|
p->p_filesz = sect->filepos - m->sections[0]->filepos;
|
|
if (hdr->sh_type != SHT_NOBITS)
|
|
p->p_filesz += hdr->sh_size;
|
|
|
|
if (p->p_type == PT_GNU_RELRO)
|
|
{
|
{
|
/* When we get here, we are copying executable
|
/* During linking the range of the RELRO segment is passed
|
or shared library. But we need to use the same
|
in link_info. */
|
linker logic. */
|
for (lp = phdrs; lp < phdrs + count; ++lp)
|
Elf_Internal_Phdr *lp;
|
{
|
|
if (lp->p_type == PT_LOAD
|
|
&& lp->p_vaddr >= link_info->relro_start
|
|
&& lp->p_vaddr < link_info->relro_end
|
|
&& lp->p_vaddr + lp->p_filesz >= link_info->relro_end)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise we are copying an executable or shared
|
|
library, but we need to use the same linker logic. */
|
for (lp = phdrs; lp < phdrs + count; ++lp)
|
for (lp = phdrs; lp < phdrs + count; ++lp)
|
{
|
{
|
if (lp->p_type == PT_LOAD
|
if (lp->p_type == PT_LOAD
|
&& lp->p_paddr == p->p_paddr)
|
&& lp->p_paddr == p->p_paddr)
|
break;
|
break;
|
}
|
}
|
|
}
|
|
|
if (lp < phdrs + count)
|
if (lp < phdrs + count)
|
{
|
{
|
/* We should use p_size if it is valid since it
|
p->p_vaddr = lp->p_vaddr;
|
may contain the first few bytes of the next
|
p->p_paddr = lp->p_paddr;
|
SEC_ALLOC section. */
|
p->p_offset = lp->p_offset;
|
if (m->p_size_valid)
|
if (link_info != NULL)
|
|
p->p_filesz = link_info->relro_end - lp->p_vaddr;
|
|
else if (m->p_size_valid)
|
p->p_filesz = m->p_size;
|
p->p_filesz = m->p_size;
|
else
|
else
|
abort ();
|
abort ();
|
p->p_vaddr = lp->p_vaddr;
|
|
p->p_offset = lp->p_offset;
|
|
p->p_memsz = p->p_filesz;
|
p->p_memsz = p->p_filesz;
|
p->p_align = 1;
|
p->p_align = 1;
|
|
p->p_flags = (lp->p_flags & ~PF_W);
|
}
|
}
|
else
|
else
|
abort ();
|
{
|
|
memset (p, 0, sizeof *p);
|
|
p->p_type = PT_NULL;
|
}
|
}
|
else
|
}
|
|
else if (m->count != 0)
|
|
{
|
|
if (p->p_type != PT_LOAD
|
|
&& (p->p_type != PT_NOTE
|
|
|| bfd_get_format (abfd) != bfd_core))
|
|
{
|
|
Elf_Internal_Shdr *hdr;
|
|
asection *sect;
|
|
|
|
BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
|
|
|
|
sect = m->sections[m->count - 1];
|
|
hdr = &elf_section_data (sect)->this_hdr;
|
|
p->p_filesz = sect->filepos - m->sections[0]->filepos;
|
|
if (hdr->sh_type != SHT_NOBITS)
|
|
p->p_filesz += hdr->sh_size;
|
p->p_offset = m->sections[0]->filepos;
|
p->p_offset = m->sections[0]->filepos;
|
}
|
}
|
}
|
}
|
else
|
else if (m->includes_filehdr)
|
{
|
|
if (m->includes_filehdr)
|
|
{
|
{
|
p->p_vaddr = filehdr_vaddr;
|
p->p_vaddr = filehdr_vaddr;
|
if (! m->p_paddr_valid)
|
if (! m->p_paddr_valid)
|
p->p_paddr = filehdr_paddr;
|
p->p_paddr = filehdr_paddr;
|
}
|
}
|
Line 4662... |
Line 4727... |
{
|
{
|
p->p_vaddr = phdrs_vaddr;
|
p->p_vaddr = phdrs_vaddr;
|
if (! m->p_paddr_valid)
|
if (! m->p_paddr_valid)
|
p->p_paddr = phdrs_paddr;
|
p->p_paddr = phdrs_paddr;
|
}
|
}
|
else if (p->p_type == PT_GNU_RELRO)
|
|
{
|
|
Elf_Internal_Phdr *lp;
|
|
|
|
for (lp = phdrs; lp < phdrs + count; ++lp)
|
|
{
|
|
if (lp->p_type == PT_LOAD
|
|
&& lp->p_vaddr <= link_info->relro_end
|
|
&& lp->p_vaddr >= link_info->relro_start
|
|
&& (lp->p_vaddr + lp->p_filesz
|
|
>= link_info->relro_end))
|
|
break;
|
|
}
|
|
|
|
if (lp < phdrs + count
|
|
&& link_info->relro_end > lp->p_vaddr)
|
|
{
|
|
p->p_vaddr = lp->p_vaddr;
|
|
p->p_paddr = lp->p_paddr;
|
|
p->p_offset = lp->p_offset;
|
|
p->p_filesz = link_info->relro_end - lp->p_vaddr;
|
|
p->p_memsz = p->p_filesz;
|
|
p->p_align = 1;
|
|
p->p_flags = (lp->p_flags & ~PF_W);
|
|
}
|
|
else
|
|
{
|
|
memset (p, 0, sizeof *p);
|
|
p->p_type = PT_NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
}
|
|
|
elf_tdata (abfd)->next_file_pos = off;
|
elf_tdata (abfd)->next_file_pos = off;
|
|
|
return TRUE;
|
return TRUE;
|
Line 4753... |
Line 4786... |
{
|
{
|
hdr->sh_offset = -1;
|
hdr->sh_offset = -1;
|
}
|
}
|
else
|
else
|
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
|
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
|
|
|
if (i == SHN_LORESERVE - 1)
|
|
{
|
|
i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
hdrpp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
}
|
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
unsigned int alloc;
|
unsigned int alloc;
|
Line 4804... |
Line 4831... |
static bfd_boolean
|
static bfd_boolean
|
prep_headers (bfd *abfd)
|
prep_headers (bfd *abfd)
|
{
|
{
|
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
|
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
|
Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
|
Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
|
Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
|
|
struct elf_strtab_hash *shstrtab;
|
struct elf_strtab_hash *shstrtab;
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
|
|
i_ehdrp = elf_elfheader (abfd);
|
i_ehdrp = elf_elfheader (abfd);
|
i_shdrp = elf_elfsections (abfd);
|
|
|
|
shstrtab = _bfd_elf_strtab_init ();
|
shstrtab = _bfd_elf_strtab_init ();
|
if (shstrtab == NULL)
|
if (shstrtab == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
Line 4954... |
Line 4979... |
|
|
if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
|
if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
|
|| bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt)
|
|| bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt)
|
return FALSE;
|
return FALSE;
|
}
|
}
|
if (count == SHN_LORESERVE - 1)
|
|
count += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
}
|
}
|
|
|
/* Write out the section header names. */
|
/* Write out the section header names. */
|
if (elf_shstrtab (abfd) != NULL
|
if (elf_shstrtab (abfd) != NULL
|
&& (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
|
&& (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
|
Line 4987... |
Line 5010... |
return _bfd_elf_write_object_contents (abfd);
|
return _bfd_elf_write_object_contents (abfd);
|
}
|
}
|
|
|
/* Given a section, search the header to find them. */
|
/* Given a section, search the header to find them. */
|
|
|
int
|
unsigned int
|
_bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
|
_bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
|
{
|
{
|
const struct elf_backend_data *bed;
|
const struct elf_backend_data *bed;
|
int index;
|
unsigned int index;
|
|
|
if (elf_section_data (asect) != NULL
|
if (elf_section_data (asect) != NULL
|
&& elf_section_data (asect)->this_idx != 0)
|
&& elf_section_data (asect)->this_idx != 0)
|
return elf_section_data (asect)->this_idx;
|
return elf_section_data (asect)->this_idx;
|
|
|
Line 5004... |
Line 5027... |
else if (bfd_is_com_section (asect))
|
else if (bfd_is_com_section (asect))
|
index = SHN_COMMON;
|
index = SHN_COMMON;
|
else if (bfd_is_und_section (asect))
|
else if (bfd_is_und_section (asect))
|
index = SHN_UNDEF;
|
index = SHN_UNDEF;
|
else
|
else
|
index = -1;
|
index = SHN_BAD;
|
|
|
bed = get_elf_backend_data (abfd);
|
bed = get_elf_backend_data (abfd);
|
if (bed->elf_backend_section_from_bfd_section)
|
if (bed->elf_backend_section_from_bfd_section)
|
{
|
{
|
int retval = index;
|
int retval = index;
|
|
|
if ((*bed->elf_backend_section_from_bfd_section) (abfd, asect, &retval))
|
if ((*bed->elf_backend_section_from_bfd_section) (abfd, asect, &retval))
|
return retval;
|
return retval;
|
}
|
}
|
|
|
if (index == -1)
|
if (index == SHN_BAD)
|
bfd_set_error (bfd_error_nonrepresentable_section);
|
bfd_set_error (bfd_error_nonrepresentable_section);
|
|
|
return index;
|
return index;
|
}
|
}
|
|
|
Line 5092... |
Line 5115... |
Elf_Internal_Phdr *segment;
|
Elf_Internal_Phdr *segment;
|
asection *section;
|
asection *section;
|
unsigned int i;
|
unsigned int i;
|
unsigned int num_segments;
|
unsigned int num_segments;
|
bfd_boolean phdr_included = FALSE;
|
bfd_boolean phdr_included = FALSE;
|
|
bfd_boolean p_paddr_valid;
|
bfd_vma maxpagesize;
|
bfd_vma maxpagesize;
|
struct elf_segment_map *phdr_adjust_seg = NULL;
|
struct elf_segment_map *phdr_adjust_seg = NULL;
|
unsigned int phdr_adjust_num = 0;
|
unsigned int phdr_adjust_num = 0;
|
const struct elf_backend_data *bed;
|
const struct elf_backend_data *bed;
|
|
|
Line 5220... |
Line 5244... |
|
|
/* Initialise the segment mark field. */
|
/* Initialise the segment mark field. */
|
for (section = ibfd->sections; section != NULL; section = section->next)
|
for (section = ibfd->sections; section != NULL; section = section->next)
|
section->segment_mark = FALSE;
|
section->segment_mark = FALSE;
|
|
|
|
/* The Solaris linker creates program headers in which all the
|
|
p_paddr fields are zero. When we try to objcopy or strip such a
|
|
file, we get confused. Check for this case, and if we find it
|
|
don't set the p_paddr_valid fields. */
|
|
p_paddr_valid = FALSE;
|
|
for (i = 0, segment = elf_tdata (ibfd)->phdr;
|
|
i < num_segments;
|
|
i++, segment++)
|
|
if (segment->p_paddr != 0)
|
|
{
|
|
p_paddr_valid = TRUE;
|
|
break;
|
|
}
|
|
|
/* Scan through the segments specified in the program header
|
/* Scan through the segments specified in the program header
|
of the input BFD. For this first scan we look for overlaps
|
of the input BFD. For this first scan we look for overlaps
|
in the loadable segments. These can be created by weird
|
in the loadable segments. These can be created by weird
|
parameters to objcopy. Also, fix some solaris weirdness. */
|
parameters to objcopy. Also, fix some solaris weirdness. */
|
for (i = 0, segment = elf_tdata (ibfd)->phdr;
|
for (i = 0, segment = elf_tdata (ibfd)->phdr;
|
Line 5338... |
Line 5376... |
|
|
/* Allocate a segment map big enough to contain
|
/* Allocate a segment map big enough to contain
|
all of the sections we have selected. */
|
all of the sections we have selected. */
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
|
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
|
map = bfd_zalloc (obfd, amt);
|
map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
|
if (map == NULL)
|
if (map == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
/* Initialise the fields of the segment map. Default to
|
/* Initialise the fields of the segment map. Default to
|
using the physical address of the segment in the input BFD. */
|
using the physical address of the segment in the input BFD. */
|
Line 5355... |
Line 5393... |
no need to preserve segment physical address in the corresponding
|
no need to preserve segment physical address in the corresponding
|
output segment. */
|
output segment. */
|
if (!first_section || first_section->output_section != NULL)
|
if (!first_section || first_section->output_section != NULL)
|
{
|
{
|
map->p_paddr = segment->p_paddr;
|
map->p_paddr = segment->p_paddr;
|
map->p_paddr_valid = 1;
|
map->p_paddr_valid = p_paddr_valid;
|
}
|
}
|
|
|
/* Determine if this segment contains the ELF file header
|
/* Determine if this segment contains the ELF file header
|
and if it contains the program headers themselves. */
|
and if it contains the program headers themselves. */
|
map->includes_filehdr = (segment->p_offset == 0
|
map->includes_filehdr = (segment->p_offset == 0
|
Line 5422... |
Line 5460... |
|
|
In order to save time, we allocate an array to hold the section
|
In order to save time, we allocate an array to hold the section
|
pointers that we are interested in. As these sections get assigned
|
pointers that we are interested in. As these sections get assigned
|
to a segment, they are removed from this array. */
|
to a segment, they are removed from this array. */
|
|
|
/* Gcc 2.96 miscompiles this code on mips. Don't do casting here
|
sections = (asection **) bfd_malloc2 (section_count, sizeof (asection *));
|
to work around this long long bug. */
|
|
sections = bfd_malloc2 (section_count, sizeof (asection *));
|
|
if (sections == NULL)
|
if (sections == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
/* Step One: Scan for segment vs section LMA conflicts.
|
/* Step One: Scan for segment vs section LMA conflicts.
|
Also add the sections to the section array allocated above.
|
Also add the sections to the section array allocated above.
|
Line 5458... |
Line 5494... |
|
|
/* The Solaris native linker always sets p_paddr to 0.
|
/* The Solaris native linker always sets p_paddr to 0.
|
We try to catch that case here, and set it to the
|
We try to catch that case here, and set it to the
|
correct value. Note - some backends require that
|
correct value. Note - some backends require that
|
p_paddr be left as zero. */
|
p_paddr be left as zero. */
|
if (segment->p_paddr == 0
|
if (!p_paddr_valid
|
&& segment->p_vaddr != 0
|
&& segment->p_vaddr != 0
|
&& !bed->want_p_paddr_set_to_zero
|
&& !bed->want_p_paddr_set_to_zero
|
&& isec == 0
|
&& isec == 0
|
&& output_section->lma != 0
|
&& output_section->lma != 0
|
&& output_section->vma == (segment->p_vaddr
|
&& output_section->vma == (segment->p_vaddr
|
Line 5516... |
Line 5552... |
program header in the input BFD. */
|
program header in the input BFD. */
|
map->count = section_count;
|
map->count = section_count;
|
*pointer_to_map = map;
|
*pointer_to_map = map;
|
pointer_to_map = &map->next;
|
pointer_to_map = &map->next;
|
|
|
if (!bed->want_p_paddr_set_to_zero
|
if (p_paddr_valid
|
|
&& !bed->want_p_paddr_set_to_zero
|
&& matching_lma != map->p_paddr
|
&& matching_lma != map->p_paddr
|
&& !map->includes_filehdr && !map->includes_phdrs)
|
&& !map->includes_filehdr
|
|
&& !map->includes_phdrs)
|
/* There is some padding before the first section in the
|
/* There is some padding before the first section in the
|
segment. So, we must account for that in the output
|
segment. So, we must account for that in the output
|
segment's vma. */
|
segment's vma. */
|
map->p_vaddr_offset = matching_lma - map->p_paddr;
|
map->p_vaddr_offset = matching_lma - map->p_paddr;
|
|
|
Line 5547... |
Line 5585... |
}
|
}
|
|
|
/* Offset the segment physical address from the lma
|
/* Offset the segment physical address from the lma
|
to allow for space taken up by elf headers. */
|
to allow for space taken up by elf headers. */
|
if (map->includes_filehdr)
|
if (map->includes_filehdr)
|
|
{
|
|
if (map->p_paddr >= iehdr->e_ehsize)
|
map->p_paddr -= iehdr->e_ehsize;
|
map->p_paddr -= iehdr->e_ehsize;
|
|
else
|
|
{
|
|
map->includes_filehdr = FALSE;
|
|
map->includes_phdrs = FALSE;
|
|
}
|
|
}
|
|
|
if (map->includes_phdrs)
|
if (map->includes_phdrs)
|
{
|
{
|
|
if (map->p_paddr >= iehdr->e_phnum * iehdr->e_phentsize)
|
|
{
|
map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
|
map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
|
|
|
/* iehdr->e_phnum is just an estimate of the number
|
/* iehdr->e_phnum is just an estimate of the number
|
of program headers that we will need. Make a note
|
of program headers that we will need. Make a note
|
here of the number we used and the segment we chose
|
here of the number we used and the segment we chose
|
to hold these headers, so that we can adjust the
|
to hold these headers, so that we can adjust the
|
offset when we know the correct value. */
|
offset when we know the correct value. */
|
phdr_adjust_num = iehdr->e_phnum;
|
phdr_adjust_num = iehdr->e_phnum;
|
phdr_adjust_seg = map;
|
phdr_adjust_seg = map;
|
}
|
}
|
|
else
|
|
map->includes_phdrs = FALSE;
|
|
}
|
}
|
}
|
|
|
/* Step Three: Loop over the sections again, this time assigning
|
/* Step Three: Loop over the sections again, this time assigning
|
those that fit to the current segment and removing them from the
|
those that fit to the current segment and removing them from the
|
sections array; but making sure not to leave large gaps. Once all
|
sections array; but making sure not to leave large gaps. Once all
|
Line 5655... |
Line 5706... |
/* We still have not allocated all of the sections to
|
/* We still have not allocated all of the sections to
|
segments. Create a new segment here, initialise it
|
segments. Create a new segment here, initialise it
|
and carry on looping. */
|
and carry on looping. */
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
|
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
|
map = bfd_alloc (obfd, amt);
|
map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
|
if (map == NULL)
|
if (map == NULL)
|
{
|
{
|
free (sections);
|
free (sections);
|
return FALSE;
|
return FALSE;
|
}
|
}
|
Line 5670... |
Line 5721... |
map->next = NULL;
|
map->next = NULL;
|
map->p_type = segment->p_type;
|
map->p_type = segment->p_type;
|
map->p_flags = segment->p_flags;
|
map->p_flags = segment->p_flags;
|
map->p_flags_valid = 1;
|
map->p_flags_valid = 1;
|
map->p_paddr = suggested_lma;
|
map->p_paddr = suggested_lma;
|
map->p_paddr_valid = 1;
|
map->p_paddr_valid = p_paddr_valid;
|
map->includes_filehdr = 0;
|
map->includes_filehdr = 0;
|
map->includes_phdrs = 0;
|
map->includes_phdrs = 0;
|
}
|
}
|
}
|
}
|
while (isec < section_count);
|
while (isec < section_count);
|
|
|
free (sections);
|
free (sections);
|
}
|
}
|
|
|
/* The Solaris linker creates program headers in which all the
|
|
p_paddr fields are zero. When we try to objcopy or strip such a
|
|
file, we get confused. Check for this case, and if we find it
|
|
reset the p_paddr_valid fields. */
|
|
for (map = map_first; map != NULL; map = map->next)
|
|
if (map->p_paddr != 0)
|
|
break;
|
|
if (map == NULL)
|
|
for (map = map_first; map != NULL; map = map->next)
|
|
map->p_paddr_valid = 0;
|
|
|
|
elf_tdata (obfd)->segment_map = map_first;
|
elf_tdata (obfd)->segment_map = map_first;
|
|
|
/* If we had to estimate the number of program headers that were
|
/* If we had to estimate the number of program headers that were
|
going to be needed, then check our estimate now and adjust
|
going to be needed, then check our estimate now and adjust
|
the offset if necessary. */
|
the offset if necessary. */
|
Line 5735... |
Line 5775... |
struct elf_segment_map **pointer_to_map;
|
struct elf_segment_map **pointer_to_map;
|
Elf_Internal_Phdr *segment;
|
Elf_Internal_Phdr *segment;
|
unsigned int i;
|
unsigned int i;
|
unsigned int num_segments;
|
unsigned int num_segments;
|
bfd_boolean phdr_included = FALSE;
|
bfd_boolean phdr_included = FALSE;
|
|
bfd_boolean p_paddr_valid;
|
|
|
iehdr = elf_elfheader (ibfd);
|
iehdr = elf_elfheader (ibfd);
|
|
|
map_first = NULL;
|
map_first = NULL;
|
pointer_to_map = &map_first;
|
pointer_to_map = &map_first;
|
|
|
|
/* If all the segment p_paddr fields are zero, don't set
|
|
map->p_paddr_valid. */
|
|
p_paddr_valid = FALSE;
|
num_segments = elf_elfheader (ibfd)->e_phnum;
|
num_segments = elf_elfheader (ibfd)->e_phnum;
|
for (i = 0, segment = elf_tdata (ibfd)->phdr;
|
for (i = 0, segment = elf_tdata (ibfd)->phdr;
|
i < num_segments;
|
i < num_segments;
|
i++, segment++)
|
i++, segment++)
|
|
if (segment->p_paddr != 0)
|
|
{
|
|
p_paddr_valid = TRUE;
|
|
break;
|
|
}
|
|
|
|
for (i = 0, segment = elf_tdata (ibfd)->phdr;
|
|
i < num_segments;
|
|
i++, segment++)
|
{
|
{
|
asection *section;
|
asection *section;
|
unsigned int section_count;
|
unsigned int section_count;
|
bfd_size_type amt;
|
bfd_size_type amt;
|
Elf_Internal_Shdr *this_hdr;
|
Elf_Internal_Shdr *this_hdr;
|
Line 5774... |
Line 5827... |
/* Allocate a segment map big enough to contain
|
/* Allocate a segment map big enough to contain
|
all of the sections we have selected. */
|
all of the sections we have selected. */
|
amt = sizeof (struct elf_segment_map);
|
amt = sizeof (struct elf_segment_map);
|
if (section_count != 0)
|
if (section_count != 0)
|
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
|
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
|
map = bfd_zalloc (obfd, amt);
|
map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
|
if (map == NULL)
|
if (map == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
/* Initialize the fields of the output segment map with the
|
/* Initialize the fields of the output segment map with the
|
input segment. */
|
input segment. */
|
map->next = NULL;
|
map->next = NULL;
|
map->p_type = segment->p_type;
|
map->p_type = segment->p_type;
|
map->p_flags = segment->p_flags;
|
map->p_flags = segment->p_flags;
|
map->p_flags_valid = 1;
|
map->p_flags_valid = 1;
|
map->p_paddr = segment->p_paddr;
|
map->p_paddr = segment->p_paddr;
|
map->p_paddr_valid = 1;
|
map->p_paddr_valid = p_paddr_valid;
|
map->p_align = segment->p_align;
|
map->p_align = segment->p_align;
|
map->p_align_valid = 1;
|
map->p_align_valid = 1;
|
map->p_vaddr_offset = 0;
|
map->p_vaddr_offset = 0;
|
|
|
if (map->p_type == PT_GNU_RELRO
|
if (map->p_type == PT_GNU_RELRO)
|
&& segment->p_filesz == segment->p_memsz)
|
|
{
|
{
|
/* The PT_GNU_RELRO segment may contain the first a few
|
/* The PT_GNU_RELRO segment may contain the first a few
|
bytes in the .got.plt section even if the whole .got.plt
|
bytes in the .got.plt section even if the whole .got.plt
|
section isn't in the PT_GNU_RELRO segment. We won't
|
section isn't in the PT_GNU_RELRO segment. We won't
|
change the size of the PT_GNU_RELRO segment. */
|
change the size of the PT_GNU_RELRO segment. */
|
map->p_size = segment->p_filesz;
|
map->p_size = segment->p_memsz;
|
map->p_size_valid = 1;
|
map->p_size_valid = 1;
|
}
|
}
|
|
|
/* Determine if this segment contains the ELF file header
|
/* Determine if this segment contains the ELF file header
|
and if it contains the program headers themselves. */
|
and if it contains the program headers themselves. */
|
Line 5819... |
Line 5871... |
|
|
if (segment->p_type == PT_LOAD && map->includes_phdrs)
|
if (segment->p_type == PT_LOAD && map->includes_phdrs)
|
phdr_included = TRUE;
|
phdr_included = TRUE;
|
}
|
}
|
|
|
if (!map->includes_phdrs && !map->includes_filehdr)
|
if (map->includes_filehdr && first_section)
|
|
/* We need to keep the space used by the headers fixed. */
|
|
map->header_size = first_section->vma - segment->p_vaddr;
|
|
|
|
if (!map->includes_phdrs
|
|
&& !map->includes_filehdr
|
|
&& map->p_paddr_valid)
|
/* There is some other padding before the first section. */
|
/* There is some other padding before the first section. */
|
map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
|
map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
|
- segment->p_paddr);
|
- segment->p_paddr);
|
|
|
if (section_count != 0)
|
if (section_count != 0)
|
Line 5985... |
Line 6043... |
|| (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0)
|
|| (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0)
|
{
|
{
|
if (elf_section_flags (isec) & SHF_GROUP)
|
if (elf_section_flags (isec) & SHF_GROUP)
|
elf_section_flags (osec) |= SHF_GROUP;
|
elf_section_flags (osec) |= SHF_GROUP;
|
elf_next_in_group (osec) = elf_next_in_group (isec);
|
elf_next_in_group (osec) = elf_next_in_group (isec);
|
elf_group_name (osec) = elf_group_name (isec);
|
elf_section_data (osec)->group = elf_section_data (isec)->group;
|
}
|
}
|
}
|
}
|
|
|
ihdr = &elf_section_data (isec)->this_hdr;
|
ihdr = &elf_section_data (isec)->this_hdr;
|
|
|
Line 6168... |
Line 6226... |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
symtab_hdr->sh_type = SHT_SYMTAB;
|
symtab_hdr->sh_type = SHT_SYMTAB;
|
symtab_hdr->sh_entsize = bed->s->sizeof_sym;
|
symtab_hdr->sh_entsize = bed->s->sizeof_sym;
|
symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
|
symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
|
symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
|
symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
|
symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
|
symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
|
|
|
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
|
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
|
symstrtab_hdr->sh_type = SHT_STRTAB;
|
symstrtab_hdr->sh_type = SHT_STRTAB;
|
|
|
outbound_syms = bfd_alloc2 (abfd, 1 + symcount, bed->s->sizeof_sym);
|
outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount,
|
|
bed->s->sizeof_sym);
|
if (outbound_syms == NULL)
|
if (outbound_syms == NULL)
|
{
|
{
|
_bfd_stringtab_free (stt);
|
_bfd_stringtab_free (stt);
|
return FALSE;
|
return FALSE;
|
}
|
}
|
Line 6186... |
Line 6245... |
outbound_shndx = NULL;
|
outbound_shndx = NULL;
|
symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
|
symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
|
if (symtab_shndx_hdr->sh_name != 0)
|
if (symtab_shndx_hdr->sh_name != 0)
|
{
|
{
|
amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
|
amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
|
outbound_shndx = bfd_zalloc2 (abfd, 1 + symcount,
|
outbound_shndx = (bfd_byte *)
|
sizeof (Elf_External_Sym_Shndx));
|
bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
|
if (outbound_shndx == NULL)
|
if (outbound_shndx == NULL)
|
{
|
{
|
_bfd_stringtab_free (stt);
|
_bfd_stringtab_free (stt);
|
return FALSE;
|
return FALSE;
|
}
|
}
|
Line 6268... |
Line 6327... |
(abfd, syms[idx]->section);
|
(abfd, syms[idx]->section);
|
}
|
}
|
else
|
else
|
{
|
{
|
asection *sec = syms[idx]->section;
|
asection *sec = syms[idx]->section;
|
int shndx;
|
unsigned int shndx;
|
|
|
if (sec->output_section)
|
if (sec->output_section)
|
{
|
{
|
value += sec->output_offset;
|
value += sec->output_offset;
|
sec = sec->output_section;
|
sec = sec->output_section;
|
Line 6315... |
Line 6374... |
}
|
}
|
else
|
else
|
{
|
{
|
shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
|
shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
|
|
|
if (shndx == -1)
|
if (shndx == SHN_BAD)
|
{
|
{
|
asection *sec2;
|
asection *sec2;
|
|
|
/* Writing this would be a hell of a lot easier if
|
/* Writing this would be a hell of a lot easier if
|
we had some decent documentation on bfd, and
|
we had some decent documentation on bfd, and
|
Line 6339... |
Line 6398... |
_bfd_stringtab_free (stt);
|
_bfd_stringtab_free (stt);
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
|
shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
|
BFD_ASSERT (shndx != -1);
|
BFD_ASSERT (shndx != SHN_BAD);
|
}
|
}
|
}
|
}
|
|
|
sym.st_shndx = shndx;
|
sym.st_shndx = shndx;
|
}
|
}
|
|
|
if ((flags & BSF_THREAD_LOCAL) != 0)
|
if ((flags & BSF_THREAD_LOCAL) != 0)
|
type = STT_TLS;
|
type = STT_TLS;
|
|
else if ((flags & BSF_GNU_INDIRECT_FUNCTION) != 0)
|
|
type = STT_GNU_IFUNC;
|
else if ((flags & BSF_FUNCTION) != 0)
|
else if ((flags & BSF_FUNCTION) != 0)
|
type = STT_FUNC;
|
type = STT_FUNC;
|
else if ((flags & BSF_OBJECT) != 0)
|
else if ((flags & BSF_OBJECT) != 0)
|
type = STT_OBJECT;
|
type = STT_OBJECT;
|
else if ((flags & BSF_RELC) != 0)
|
else if ((flags & BSF_RELC) != 0)
|
Line 6381... |
Line 6442... |
{
|
{
|
#ifdef USE_STT_COMMON
|
#ifdef USE_STT_COMMON
|
if (type == STT_OBJECT)
|
if (type == STT_OBJECT)
|
sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_COMMON);
|
sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_COMMON);
|
else
|
else
|
#else
|
|
sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
|
|
#endif
|
#endif
|
|
sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
|
}
|
}
|
else if (bfd_is_und_section (syms[idx]->section))
|
else if (bfd_is_und_section (syms[idx]->section))
|
sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
|
sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
|
? STB_WEAK
|
? STB_WEAK
|
: STB_GLOBAL),
|
: STB_GLOBAL),
|
Line 6398... |
Line 6458... |
{
|
{
|
int bind = STB_LOCAL;
|
int bind = STB_LOCAL;
|
|
|
if (flags & BSF_LOCAL)
|
if (flags & BSF_LOCAL)
|
bind = STB_LOCAL;
|
bind = STB_LOCAL;
|
|
else if (flags & BSF_GNU_UNIQUE)
|
|
bind = STB_GNU_UNIQUE;
|
else if (flags & BSF_WEAK)
|
else if (flags & BSF_WEAK)
|
bind = STB_WEAK;
|
bind = STB_WEAK;
|
else if (flags & BSF_GLOBAL)
|
else if (flags & BSF_GLOBAL)
|
bind = STB_GLOBAL;
|
bind = STB_GLOBAL;
|
|
|
Line 6546... |
Line 6608... |
return -1;
|
return -1;
|
}
|
}
|
|
|
ret = sizeof (arelent *);
|
ret = sizeof (arelent *);
|
for (s = abfd->sections; s != NULL; s = s->next)
|
for (s = abfd->sections; s != NULL; s = s->next)
|
if ((s->flags & SEC_LOAD) != 0
|
if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
|
&& elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
|
|
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
|
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
|
ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
|
ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
|
* sizeof (arelent *));
|
* sizeof (arelent *));
|
|
|
Line 6583... |
Line 6644... |
|
|
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
|
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
|
ret = 0;
|
ret = 0;
|
for (s = abfd->sections; s != NULL; s = s->next)
|
for (s = abfd->sections; s != NULL; s = s->next)
|
{
|
{
|
if ((s->flags & SEC_LOAD) != 0
|
if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
|
&& elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
|
|
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
|
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
|
{
|
{
|
arelent *p;
|
arelent *p;
|
long count, i;
|
long count, i;
|
Line 6624... |
Line 6684... |
unsigned int i;
|
unsigned int i;
|
bfd_byte *contents_end;
|
bfd_byte *contents_end;
|
|
|
hdr = &elf_tdata (abfd)->dynverref_hdr;
|
hdr = &elf_tdata (abfd)->dynverref_hdr;
|
|
|
elf_tdata (abfd)->verref = bfd_zalloc2 (abfd, hdr->sh_info,
|
elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
|
sizeof (Elf_Internal_Verneed));
|
bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
|
if (elf_tdata (abfd)->verref == NULL)
|
if (elf_tdata (abfd)->verref == NULL)
|
goto error_return;
|
goto error_return;
|
|
|
elf_tdata (abfd)->cverrefs = hdr->sh_info;
|
elf_tdata (abfd)->cverrefs = hdr->sh_info;
|
|
|
contents = bfd_malloc (hdr->sh_size);
|
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
|
if (contents == NULL)
|
if (contents == NULL)
|
{
|
{
|
error_return_verref:
|
error_return_verref:
|
elf_tdata (abfd)->verref = NULL;
|
elf_tdata (abfd)->verref = NULL;
|
elf_tdata (abfd)->cverrefs = 0;
|
elf_tdata (abfd)->cverrefs = 0;
|
Line 6671... |
Line 6731... |
|
|
if (iverneed->vn_cnt == 0)
|
if (iverneed->vn_cnt == 0)
|
iverneed->vn_auxptr = NULL;
|
iverneed->vn_auxptr = NULL;
|
else
|
else
|
{
|
{
|
iverneed->vn_auxptr = bfd_alloc2 (abfd, iverneed->vn_cnt,
|
iverneed->vn_auxptr = (struct elf_internal_vernaux *)
|
|
bfd_alloc2 (abfd, iverneed->vn_cnt,
|
sizeof (Elf_Internal_Vernaux));
|
sizeof (Elf_Internal_Vernaux));
|
if (iverneed->vn_auxptr == NULL)
|
if (iverneed->vn_auxptr == NULL)
|
goto error_return_verref;
|
goto error_return_verref;
|
}
|
}
|
|
|
Line 6740... |
Line 6801... |
unsigned int maxidx;
|
unsigned int maxidx;
|
bfd_byte *contents_end_def, *contents_end_aux;
|
bfd_byte *contents_end_def, *contents_end_aux;
|
|
|
hdr = &elf_tdata (abfd)->dynverdef_hdr;
|
hdr = &elf_tdata (abfd)->dynverdef_hdr;
|
|
|
contents = bfd_malloc (hdr->sh_size);
|
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
|
if (contents == NULL)
|
if (contents == NULL)
|
goto error_return;
|
goto error_return;
|
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|
|| bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
|
|| bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
|
goto error_return;
|
goto error_return;
|
Line 6784... |
Line 6845... |
if (freeidx > maxidx)
|
if (freeidx > maxidx)
|
maxidx = ++freeidx;
|
maxidx = ++freeidx;
|
else
|
else
|
freeidx = ++maxidx;
|
freeidx = ++maxidx;
|
}
|
}
|
elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, maxidx,
|
elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
|
sizeof (Elf_Internal_Verdef));
|
bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef));
|
if (elf_tdata (abfd)->verdef == NULL)
|
if (elf_tdata (abfd)->verdef == NULL)
|
goto error_return;
|
goto error_return;
|
|
|
elf_tdata (abfd)->cverdefs = maxidx;
|
elf_tdata (abfd)->cverdefs = maxidx;
|
|
|
Line 6818... |
Line 6879... |
|
|
if (iverdef->vd_cnt == 0)
|
if (iverdef->vd_cnt == 0)
|
iverdef->vd_auxptr = NULL;
|
iverdef->vd_auxptr = NULL;
|
else
|
else
|
{
|
{
|
iverdef->vd_auxptr = bfd_alloc2 (abfd, iverdef->vd_cnt,
|
iverdef->vd_auxptr = (struct elf_internal_verdaux *)
|
|
bfd_alloc2 (abfd, iverdef->vd_cnt,
|
sizeof (Elf_Internal_Verdaux));
|
sizeof (Elf_Internal_Verdaux));
|
if (iverdef->vd_auxptr == NULL)
|
if (iverdef->vd_auxptr == NULL)
|
goto error_return_verdef;
|
goto error_return_verdef;
|
}
|
}
|
|
|
Line 6876... |
Line 6938... |
if (freeidx < 3)
|
if (freeidx < 3)
|
freeidx = 3;
|
freeidx = 3;
|
else
|
else
|
freeidx++;
|
freeidx++;
|
|
|
elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, freeidx,
|
elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
|
sizeof (Elf_Internal_Verdef));
|
bfd_zalloc2 (abfd, freeidx, sizeof (Elf_Internal_Verdef));
|
if (elf_tdata (abfd)->verdef == NULL)
|
if (elf_tdata (abfd)->verdef == NULL)
|
goto error_return;
|
goto error_return;
|
|
|
elf_tdata (abfd)->cverdefs = freeidx;
|
elf_tdata (abfd)->cverdefs = freeidx;
|
}
|
}
|
Line 6903... |
Line 6965... |
|
|
iverdef->vd_nodename = bfd_elf_get_dt_soname (abfd);
|
iverdef->vd_nodename = bfd_elf_get_dt_soname (abfd);
|
if (iverdef->vd_nodename == NULL)
|
if (iverdef->vd_nodename == NULL)
|
goto error_return_verdef;
|
goto error_return_verdef;
|
iverdef->vd_nextdef = NULL;
|
iverdef->vd_nextdef = NULL;
|
iverdef->vd_auxptr = bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux));
|
iverdef->vd_auxptr = (struct elf_internal_verdaux *)
|
|
bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux));
|
if (iverdef->vd_auxptr == NULL)
|
if (iverdef->vd_auxptr == NULL)
|
goto error_return_verdef;
|
goto error_return_verdef;
|
|
|
iverdaux = iverdef->vd_auxptr;
|
iverdaux = iverdef->vd_auxptr;
|
iverdaux->vda_nodename = iverdef->vd_nodename;
|
iverdaux->vda_nodename = iverdef->vd_nodename;
|
Line 6926... |
Line 6989... |
_bfd_elf_make_empty_symbol (bfd *abfd)
|
_bfd_elf_make_empty_symbol (bfd *abfd)
|
{
|
{
|
elf_symbol_type *newsym;
|
elf_symbol_type *newsym;
|
bfd_size_type amt = sizeof (elf_symbol_type);
|
bfd_size_type amt = sizeof (elf_symbol_type);
|
|
|
newsym = bfd_zalloc (abfd, amt);
|
newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt);
|
if (!newsym)
|
if (!newsym)
|
return NULL;
|
return NULL;
|
else
|
else
|
{
|
{
|
newsym->symbol.the_bfd = abfd;
|
newsym->symbol.the_bfd = abfd;
|
Line 7000... |
Line 7063... |
|
|
/* Find the function to a particular section and offset,
|
/* Find the function to a particular section and offset,
|
for error reporting. */
|
for error reporting. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
|
elf_find_function (bfd *abfd,
|
asection *section,
|
asection *section,
|
asymbol **symbols,
|
asymbol **symbols,
|
bfd_vma offset,
|
bfd_vma offset,
|
const char **filename_ptr,
|
const char **filename_ptr,
|
const char **functionname_ptr)
|
const char **functionname_ptr)
|
Line 7020... |
Line 7083... |
file symbol must sort before other local symbols, but currently
|
file symbol must sort before other local symbols, but currently
|
ld -r doesn't do this. So, for ld -r output, it is possible to
|
ld -r doesn't do this. So, for ld -r output, it is possible to
|
make a better choice of file name for local symbols by ignoring
|
make a better choice of file name for local symbols by ignoring
|
file symbols appearing after a given local symbol. */
|
file symbols appearing after a given local symbol. */
|
enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
|
enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
|
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
|
|
filename = NULL;
|
filename = NULL;
|
func = NULL;
|
func = NULL;
|
file = NULL;
|
file = NULL;
|
low_func = 0;
|
low_func = 0;
|
state = nothing_seen;
|
state = nothing_seen;
|
|
|
for (p = symbols; *p != NULL; p++)
|
for (p = symbols; *p != NULL; p++)
|
{
|
{
|
elf_symbol_type *q;
|
elf_symbol_type *q;
|
|
unsigned int type;
|
|
|
q = (elf_symbol_type *) *p;
|
q = (elf_symbol_type *) *p;
|
|
|
switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
|
type = ELF_ST_TYPE (q->internal_elf_sym.st_info);
|
|
switch (type)
|
{
|
{
|
default:
|
|
break;
|
|
case STT_FILE:
|
case STT_FILE:
|
file = &q->symbol;
|
file = &q->symbol;
|
if (state == symbol_seen)
|
if (state == symbol_seen)
|
state = file_after_symbol_seen;
|
state = file_after_symbol_seen;
|
continue;
|
continue;
|
|
default:
|
|
if (!bed->is_function_type (type))
|
|
break;
|
case STT_NOTYPE:
|
case STT_NOTYPE:
|
case STT_FUNC:
|
|
if (bfd_get_section (&q->symbol) == section
|
if (bfd_get_section (&q->symbol) == section
|
&& q->symbol.value >= low_func
|
&& q->symbol.value >= low_func
|
&& q->symbol.value <= offset)
|
&& q->symbol.value <= offset)
|
{
|
{
|
func = (asymbol *) q;
|
func = (asymbol *) q;
|
Line 7408... |
Line 7474... |
|
|
/* Build the section name. */
|
/* Build the section name. */
|
|
|
sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
|
sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
|
len = strlen (buf) + 1;
|
len = strlen (buf) + 1;
|
threaded_name = bfd_alloc (abfd, len);
|
threaded_name = (char *) bfd_alloc (abfd, len);
|
if (threaded_name == NULL)
|
if (threaded_name == NULL)
|
return FALSE;
|
return FALSE;
|
memcpy (threaded_name, buf, len);
|
memcpy (threaded_name, buf, len);
|
|
|
sect = bfd_make_section_anyway_with_flags (abfd, threaded_name,
|
sect = bfd_make_section_anyway_with_flags (abfd, threaded_name,
|
Line 7538... |
Line 7604... |
elfcore_grok_ppc_vmx (bfd *abfd, Elf_Internal_Note *note)
|
elfcore_grok_ppc_vmx (bfd *abfd, Elf_Internal_Note *note)
|
{
|
{
|
return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vmx", note);
|
return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vmx", note);
|
}
|
}
|
|
|
|
static bfd_boolean
|
|
elfcore_grok_ppc_vsx (bfd *abfd, Elf_Internal_Note *note)
|
|
{
|
|
return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vsx", note);
|
|
}
|
|
|
#if defined (HAVE_PRPSINFO_T)
|
#if defined (HAVE_PRPSINFO_T)
|
typedef prpsinfo_t elfcore_psinfo_t;
|
typedef prpsinfo_t elfcore_psinfo_t;
|
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
|
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
|
typedef prpsinfo32_t elfcore_psinfo32_t;
|
typedef prpsinfo32_t elfcore_psinfo32_t;
|
Line 7561... |
Line 7632... |
|
|
char *
|
char *
|
_bfd_elfcore_strndup (bfd *abfd, char *start, size_t max)
|
_bfd_elfcore_strndup (bfd *abfd, char *start, size_t max)
|
{
|
{
|
char *dups;
|
char *dups;
|
char *end = memchr (start, '\0', max);
|
char *end = (char *) memchr (start, '\0', max);
|
size_t len;
|
size_t len;
|
|
|
if (end == NULL)
|
if (end == NULL)
|
len = max;
|
len = max;
|
else
|
else
|
len = end - start;
|
len = end - start;
|
|
|
dups = bfd_alloc (abfd, len + 1);
|
dups = (char *) bfd_alloc (abfd, len + 1);
|
if (dups == NULL)
|
if (dups == NULL)
|
return NULL;
|
return NULL;
|
|
|
memcpy (dups, start, len);
|
memcpy (dups, start, len);
|
dups[len] = '\0';
|
dups[len] = '\0';
|
Line 7789... |
Line 7860... |
/* Make a ".reg/999" section. */
|
/* Make a ".reg/999" section. */
|
/* thread_info.tid */
|
/* thread_info.tid */
|
sprintf (buf, ".reg/%ld", (long) bfd_get_32 (abfd, note->descdata + 8));
|
sprintf (buf, ".reg/%ld", (long) bfd_get_32 (abfd, note->descdata + 8));
|
|
|
len = strlen (buf) + 1;
|
len = strlen (buf) + 1;
|
name = bfd_alloc (abfd, len);
|
name = (char *) bfd_alloc (abfd, len);
|
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
memcpy (name, buf, len);
|
memcpy (name, buf, len);
|
|
|
Line 7817... |
Line 7888... |
|
|
case 3 /* NOTE_INFO_MODULE */:
|
case 3 /* NOTE_INFO_MODULE */:
|
/* Make a ".module/xxxxxxxx" section. */
|
/* Make a ".module/xxxxxxxx" section. */
|
/* module_info.base_address */
|
/* module_info.base_address */
|
base_addr = bfd_get_32 (abfd, note->descdata + 4);
|
base_addr = bfd_get_32 (abfd, note->descdata + 4);
|
sprintf (buf, ".module/%08lx", (long) base_addr);
|
sprintf (buf, ".module/%08lx", (unsigned long) base_addr);
|
|
|
len = strlen (buf) + 1;
|
len = strlen (buf) + 1;
|
name = bfd_alloc (abfd, len);
|
name = (char *) bfd_alloc (abfd, len);
|
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
memcpy (name, buf, len);
|
memcpy (name, buf, len);
|
|
|
Line 7893... |
Line 7964... |
&& strcmp (note->namedata, "LINUX") == 0)
|
&& strcmp (note->namedata, "LINUX") == 0)
|
return elfcore_grok_ppc_vmx (abfd, note);
|
return elfcore_grok_ppc_vmx (abfd, note);
|
else
|
else
|
return TRUE;
|
return TRUE;
|
|
|
|
case NT_PPC_VSX:
|
|
if (note->namesz == 6
|
|
&& strcmp (note->namedata, "LINUX") == 0)
|
|
return elfcore_grok_ppc_vsx (abfd, note);
|
|
else
|
|
return TRUE;
|
|
|
case NT_PRPSINFO:
|
case NT_PRPSINFO:
|
case NT_PSINFO:
|
case NT_PSINFO:
|
if (bed->elf_backend_grok_psinfo)
|
if (bed->elf_backend_grok_psinfo)
|
if ((*bed->elf_backend_grok_psinfo) (abfd, note))
|
if ((*bed->elf_backend_grok_psinfo) (abfd, note))
|
return TRUE;
|
return TRUE;
|
Line 7924... |
Line 8002... |
|
|
static bfd_boolean
|
static bfd_boolean
|
elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
|
elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
|
{
|
{
|
elf_tdata (abfd)->build_id_size = note->descsz;
|
elf_tdata (abfd)->build_id_size = note->descsz;
|
elf_tdata (abfd)->build_id = bfd_alloc (abfd, note->descsz);
|
elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz);
|
if (elf_tdata (abfd)->build_id == NULL)
|
if (elf_tdata (abfd)->build_id == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz);
|
memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz);
|
|
|
Line 8045... |
Line 8123... |
}
|
}
|
/* NOTREACHED */
|
/* NOTREACHED */
|
}
|
}
|
|
|
static bfd_boolean
|
static bfd_boolean
|
|
elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
|
|
{
|
|
/* Signal number at offset 0x08. */
|
|
elf_tdata (abfd)->core_signal
|
|
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
|
|
|
|
/* Process ID at offset 0x20. */
|
|
elf_tdata (abfd)->core_pid
|
|
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x20);
|
|
|
|
/* Command name at 0x48 (max 32 bytes, including nul). */
|
|
elf_tdata (abfd)->core_command
|
|
= _bfd_elfcore_strndup (abfd, note->descdata + 0x48, 31);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static bfd_boolean
|
|
elfcore_grok_openbsd_note (bfd *abfd, Elf_Internal_Note *note)
|
|
{
|
|
if (note->type == NT_OPENBSD_PROCINFO)
|
|
return elfcore_grok_openbsd_procinfo (abfd, note);
|
|
|
|
if (note->type == NT_OPENBSD_REGS)
|
|
return elfcore_make_note_pseudosection (abfd, ".reg", note);
|
|
|
|
if (note->type == NT_OPENBSD_FPREGS)
|
|
return elfcore_make_note_pseudosection (abfd, ".reg2", note);
|
|
|
|
if (note->type == NT_OPENBSD_XFPREGS)
|
|
return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
|
|
|
|
if (note->type == NT_OPENBSD_AUXV)
|
|
{
|
|
asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
|
|
SEC_HAS_CONTENTS);
|
|
|
|
if (sect == NULL)
|
|
return FALSE;
|
|
sect->size = note->descsz;
|
|
sect->filepos = note->descpos;
|
|
sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (note->type == NT_OPENBSD_WCOOKIE)
|
|
{
|
|
asection *sect = bfd_make_section_anyway_with_flags (abfd, ".wcookie",
|
|
SEC_HAS_CONTENTS);
|
|
|
|
if (sect == NULL)
|
|
return FALSE;
|
|
sect->size = note->descsz;
|
|
sect->filepos = note->descpos;
|
|
sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static bfd_boolean
|
elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
|
elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
|
{
|
{
|
void *ddata = note->descdata;
|
void *ddata = note->descdata;
|
char buf[100];
|
char buf[100];
|
char *name;
|
char *name;
|
Line 8079... |
Line 8221... |
elf_tdata (abfd)->core_lwpid = *tid;
|
elf_tdata (abfd)->core_lwpid = *tid;
|
|
|
/* Make a ".qnx_core_status/%d" section. */
|
/* Make a ".qnx_core_status/%d" section. */
|
sprintf (buf, ".qnx_core_status/%ld", *tid);
|
sprintf (buf, ".qnx_core_status/%ld", *tid);
|
|
|
name = bfd_alloc (abfd, strlen (buf) + 1);
|
name = (char *) bfd_alloc (abfd, strlen (buf) + 1);
|
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
strcpy (name, buf);
|
strcpy (name, buf);
|
|
|
sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
|
sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
|
Line 8108... |
Line 8250... |
asection *sect;
|
asection *sect;
|
|
|
/* Make a "(base)/%d" section. */
|
/* Make a "(base)/%d" section. */
|
sprintf (buf, "%s/%ld", base, tid);
|
sprintf (buf, "%s/%ld", base, tid);
|
|
|
name = bfd_alloc (abfd, strlen (buf) + 1);
|
name = (char *) bfd_alloc (abfd, strlen (buf) + 1);
|
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
strcpy (name, buf);
|
strcpy (name, buf);
|
|
|
sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
|
sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
|
Line 8165... |
Line 8307... |
asection *sect;
|
asection *sect;
|
size_t len;
|
size_t len;
|
|
|
/* Use note name as section name. */
|
/* Use note name as section name. */
|
len = note->namesz;
|
len = note->namesz;
|
name = bfd_alloc (abfd, len);
|
name = (char *) bfd_alloc (abfd, len);
|
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
memcpy (name, note->namedata, len);
|
memcpy (name, note->namedata, len);
|
name[len - 1] = '\0';
|
name[len - 1] = '\0';
|
|
|
Line 8219... |
Line 8361... |
if (name != NULL)
|
if (name != NULL)
|
namesz = strlen (name) + 1;
|
namesz = strlen (name) + 1;
|
|
|
newspace = 12 + ((namesz + 3) & -4) + ((size + 3) & -4);
|
newspace = 12 + ((namesz + 3) & -4) + ((size + 3) & -4);
|
|
|
buf = realloc (buf, *bufsiz + newspace);
|
buf = (char *) realloc (buf, *bufsiz + newspace);
|
if (buf == NULL)
|
if (buf == NULL)
|
return buf;
|
return buf;
|
dest = buf + *bufsiz;
|
dest = buf + *bufsiz;
|
*bufsiz += newspace;
|
*bufsiz += newspace;
|
xnp = (Elf_External_Note *) dest;
|
xnp = (Elf_External_Note *) dest;
|
Line 8459... |
Line 8601... |
char *note_name = "LINUX";
|
char *note_name = "LINUX";
|
return elfcore_write_note (abfd, buf, bufsiz,
|
return elfcore_write_note (abfd, buf, bufsiz,
|
note_name, NT_PPC_VMX, ppc_vmx, size);
|
note_name, NT_PPC_VMX, ppc_vmx, size);
|
}
|
}
|
|
|
|
char *
|
|
elfcore_write_ppc_vsx (bfd *abfd,
|
|
char *buf,
|
|
int *bufsiz,
|
|
const void *ppc_vsx,
|
|
int size)
|
|
{
|
|
char *note_name = "LINUX";
|
|
return elfcore_write_note (abfd, buf, bufsiz,
|
|
note_name, NT_PPC_VSX, ppc_vsx, size);
|
|
}
|
|
|
|
char *
|
|
elfcore_write_register_note (bfd *abfd,
|
|
char *buf,
|
|
int *bufsiz,
|
|
const char *section,
|
|
const void *data,
|
|
int size)
|
|
{
|
|
if (strcmp (section, ".reg2") == 0)
|
|
return elfcore_write_prfpreg (abfd, buf, bufsiz, data, size);
|
|
if (strcmp (section, ".reg-xfp") == 0)
|
|
return elfcore_write_prxfpreg (abfd, buf, bufsiz, data, size);
|
|
if (strcmp (section, ".reg-ppc-vmx") == 0)
|
|
return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size);
|
|
if (strcmp (section, ".reg-ppc-vsx") == 0)
|
|
return elfcore_write_ppc_vsx (abfd, buf, bufsiz, data, size);
|
|
return NULL;
|
|
}
|
|
|
static bfd_boolean
|
static bfd_boolean
|
elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
|
elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
|
{
|
{
|
char *p;
|
char *p;
|
|
|
Line 8471... |
Line 8644... |
{
|
{
|
/* FIXME: bad alignment assumption. */
|
/* FIXME: bad alignment assumption. */
|
Elf_External_Note *xnp = (Elf_External_Note *) p;
|
Elf_External_Note *xnp = (Elf_External_Note *) p;
|
Elf_Internal_Note in;
|
Elf_Internal_Note in;
|
|
|
|
if (offsetof (Elf_External_Note, name) > buf - p + size)
|
|
return FALSE;
|
|
|
in.type = H_GET_32 (abfd, xnp->type);
|
in.type = H_GET_32 (abfd, xnp->type);
|
|
|
in.namesz = H_GET_32 (abfd, xnp->namesz);
|
in.namesz = H_GET_32 (abfd, xnp->namesz);
|
in.namedata = xnp->name;
|
in.namedata = xnp->name;
|
|
if (in.namesz > buf - in.namedata + size)
|
|
return FALSE;
|
|
|
in.descsz = H_GET_32 (abfd, xnp->descsz);
|
in.descsz = H_GET_32 (abfd, xnp->descsz);
|
in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4);
|
in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4);
|
in.descpos = offset + (in.descdata - buf);
|
in.descpos = offset + (in.descdata - buf);
|
|
if (in.descsz != 0
|
|
&& (in.descdata >= buf + size
|
|
|| in.descsz > buf - in.descdata + size))
|
|
return FALSE;
|
|
|
switch (bfd_get_format (abfd))
|
switch (bfd_get_format (abfd))
|
{
|
{
|
default:
|
default:
|
return TRUE;
|
return TRUE;
|
Line 8491... |
Line 8673... |
if (CONST_STRNEQ (in.namedata, "NetBSD-CORE"))
|
if (CONST_STRNEQ (in.namedata, "NetBSD-CORE"))
|
{
|
{
|
if (! elfcore_grok_netbsd_note (abfd, &in))
|
if (! elfcore_grok_netbsd_note (abfd, &in))
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
else if (CONST_STRNEQ (in.namedata, "OpenBSD"))
|
|
{
|
|
if (! elfcore_grok_openbsd_note (abfd, &in))
|
|
return FALSE;
|
|
}
|
else if (CONST_STRNEQ (in.namedata, "QNX"))
|
else if (CONST_STRNEQ (in.namedata, "QNX"))
|
{
|
{
|
if (! elfcore_grok_nto_note (abfd, &in))
|
if (! elfcore_grok_nto_note (abfd, &in))
|
return FALSE;
|
return FALSE;
|
}
|
}
|
Line 8534... |
Line 8721... |
return TRUE;
|
return TRUE;
|
|
|
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
|
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
|
return FALSE;
|
return FALSE;
|
|
|
buf = bfd_malloc (size);
|
buf = (char *) bfd_malloc (size);
|
if (buf == NULL)
|
if (buf == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
if (bfd_bread (buf, size, abfd) != size
|
if (bfd_bread (buf, size, abfd) != size
|
|| !elf_parse_notes (abfd, buf, size, offset))
|
|| !elf_parse_notes (abfd, buf, size, offset))
|
Line 8730... |
Line 8917... |
if (!bed->plt_sym_val)
|
if (!bed->plt_sym_val)
|
return 0;
|
return 0;
|
|
|
relplt_name = bed->relplt_name;
|
relplt_name = bed->relplt_name;
|
if (relplt_name == NULL)
|
if (relplt_name == NULL)
|
relplt_name = bed->default_use_rela_p ? ".rela.plt" : ".rel.plt";
|
relplt_name = bed->rela_plts_and_copies_p ? ".rela.plt" : ".rel.plt";
|
relplt = bfd_get_section_by_name (abfd, relplt_name);
|
relplt = bfd_get_section_by_name (abfd, relplt_name);
|
if (relplt == NULL)
|
if (relplt == NULL)
|
return 0;
|
return 0;
|
|
|
hdr = &elf_section_data (relplt)->this_hdr;
|
hdr = &elf_section_data (relplt)->this_hdr;
|
Line 8751... |
Line 8938... |
return -1;
|
return -1;
|
|
|
count = relplt->size / hdr->sh_entsize;
|
count = relplt->size / hdr->sh_entsize;
|
size = count * sizeof (asymbol);
|
size = count * sizeof (asymbol);
|
p = relplt->relocation;
|
p = relplt->relocation;
|
for (i = 0; i < count; i++, p++)
|
for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
|
|
{
|
size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
|
size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
|
|
if (p->addend != 0)
|
|
{
|
|
#ifdef BFD64
|
|
size += sizeof ("+0x") - 1 + 8 + 8 * (bed->s->elfclass == ELFCLASS64);
|
|
#else
|
|
size += sizeof ("+0x") - 1 + 8;
|
|
#endif
|
|
}
|
|
}
|
|
|
s = *ret = bfd_malloc (size);
|
s = *ret = (asymbol *) bfd_malloc (size);
|
if (s == NULL)
|
if (s == NULL)
|
return -1;
|
return -1;
|
|
|
names = (char *) (s + count);
|
names = (char *) (s + count);
|
p = relplt->relocation;
|
p = relplt->relocation;
|
n = 0;
|
n = 0;
|
for (i = 0; i < count; i++, p++)
|
for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
|
{
|
{
|
size_t len;
|
size_t len;
|
bfd_vma addr;
|
bfd_vma addr;
|
|
|
addr = bed->plt_sym_val (i, plt, p);
|
addr = bed->plt_sym_val (i, plt, p);
|
Line 8775... |
Line 8972... |
*s = **p->sym_ptr_ptr;
|
*s = **p->sym_ptr_ptr;
|
/* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since
|
/* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since
|
we are defining a symbol, ensure one of them is set. */
|
we are defining a symbol, ensure one of them is set. */
|
if ((s->flags & BSF_LOCAL) == 0)
|
if ((s->flags & BSF_LOCAL) == 0)
|
s->flags |= BSF_GLOBAL;
|
s->flags |= BSF_GLOBAL;
|
|
s->flags |= BSF_SYNTHETIC;
|
s->section = plt;
|
s->section = plt;
|
s->value = addr - plt->vma;
|
s->value = addr - plt->vma;
|
s->name = names;
|
s->name = names;
|
s->udata.p = NULL;
|
s->udata.p = NULL;
|
len = strlen ((*p->sym_ptr_ptr)->name);
|
len = strlen ((*p->sym_ptr_ptr)->name);
|
memcpy (names, (*p->sym_ptr_ptr)->name, len);
|
memcpy (names, (*p->sym_ptr_ptr)->name, len);
|
names += len;
|
names += len;
|
|
if (p->addend != 0)
|
|
{
|
|
char buf[30], *a;
|
|
int len;
|
|
memcpy (names, "+0x", sizeof ("+0x") - 1);
|
|
names += sizeof ("+0x") - 1;
|
|
bfd_sprintf_vma (abfd, buf, p->addend);
|
|
for (a = buf; *a == '0'; ++a)
|
|
;
|
|
len = strlen (a);
|
|
memcpy (names, a, len);
|
|
names += len;
|
|
}
|
memcpy (names, "@plt", sizeof ("@plt"));
|
memcpy (names, "@plt", sizeof ("@plt"));
|
names += sizeof ("@plt");
|
names += sizeof ("@plt");
|
++s, ++n;
|
++s, ++n;
|
}
|
}
|
|
|
Line 8804... |
Line 9015... |
Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
|
Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
|
|
|
i_ehdrp = elf_elfheader (abfd);
|
i_ehdrp = elf_elfheader (abfd);
|
|
|
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
|
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
|
|
|
|
/* To make things simpler for the loader on Linux systems we set the
|
|
osabi field to ELFOSABI_LINUX if the binary contains symbols of
|
|
the STT_GNU_IFUNC type. */
|
|
if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
|
|
&& elf_tdata (abfd)->has_ifunc_symbols)
|
|
i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
|
}
|
}
|
|
|
|
|
/* Return TRUE for ELF symbol types that represent functions.
|
/* Return TRUE for ELF symbol types that represent functions.
|
This is the default version of this function, which is sufficient for
|
This is the default version of this function, which is sufficient for
|
most targets. It returns true if TYPE is STT_FUNC. */
|
most targets. It returns true if TYPE is STT_FUNC or STT_GNU_IFUNC. */
|
|
|
bfd_boolean
|
bfd_boolean
|
_bfd_elf_is_function_type (unsigned int type)
|
_bfd_elf_is_function_type (unsigned int type)
|
{
|
{
|
return (type == STT_FUNC);
|
return (type == STT_FUNC
|
|
|| type == STT_GNU_IFUNC);
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|