Line 1... |
Line 1... |
/* ELF executable support for BFD.
|
/* ELF executable support for BFD.
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
2001, 2002, 2003, 2004, 2005, 2006, 2007
|
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
|
|
Written by Fred Fish @ Cygnus Support, from information published
|
Written by Fred Fish @ Cygnus Support, from information published
|
in "UNIX System V Release 4, Programmers Guide: ANSI C and
|
in "UNIX System V Release 4, Programmers Guide: ANSI C and
|
Programming Support Tools". Sufficient support for gdb.
|
Programming Support Tools". Sufficient support for gdb.
|
Line 174... |
Line 174... |
elf_swap_symbol_in (bfd *abfd,
|
elf_swap_symbol_in (bfd *abfd,
|
const void *psrc,
|
const void *psrc,
|
const void *pshn,
|
const void *pshn,
|
Elf_Internal_Sym *dst)
|
Elf_Internal_Sym *dst)
|
{
|
{
|
const Elf_External_Sym *src = psrc;
|
const Elf_External_Sym *src = (const Elf_External_Sym *) psrc;
|
const Elf_External_Sym_Shndx *shndx = pshn;
|
const Elf_External_Sym_Shndx *shndx = (const Elf_External_Sym_Shndx *) pshn;
|
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
|
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
|
|
|
dst->st_name = H_GET_32 (abfd, src->st_name);
|
dst->st_name = H_GET_32 (abfd, src->st_name);
|
if (signed_vma)
|
if (signed_vma)
|
dst->st_value = H_GET_SIGNED_WORD (abfd, src->st_value);
|
dst->st_value = H_GET_SIGNED_WORD (abfd, src->st_value);
|
Line 187... |
Line 187... |
dst->st_value = H_GET_WORD (abfd, src->st_value);
|
dst->st_value = H_GET_WORD (abfd, src->st_value);
|
dst->st_size = H_GET_WORD (abfd, src->st_size);
|
dst->st_size = H_GET_WORD (abfd, src->st_size);
|
dst->st_info = H_GET_8 (abfd, src->st_info);
|
dst->st_info = H_GET_8 (abfd, src->st_info);
|
dst->st_other = H_GET_8 (abfd, src->st_other);
|
dst->st_other = H_GET_8 (abfd, src->st_other);
|
dst->st_shndx = H_GET_16 (abfd, src->st_shndx);
|
dst->st_shndx = H_GET_16 (abfd, src->st_shndx);
|
if (dst->st_shndx == SHN_XINDEX)
|
if (dst->st_shndx == (SHN_XINDEX & 0xffff))
|
{
|
{
|
if (shndx == NULL)
|
if (shndx == NULL)
|
return FALSE;
|
return FALSE;
|
dst->st_shndx = H_GET_32 (abfd, shndx->est_shndx);
|
dst->st_shndx = H_GET_32 (abfd, shndx->est_shndx);
|
}
|
}
|
|
else if (dst->st_shndx >= (SHN_LORESERVE & 0xffff))
|
|
dst->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/* Translate an ELF symbol in internal format into an ELF symbol in external
|
/* Translate an ELF symbol in internal format into an ELF symbol in external
|
format. */
|
format. */
|
Line 206... |
Line 208... |
const Elf_Internal_Sym *src,
|
const Elf_Internal_Sym *src,
|
void *cdst,
|
void *cdst,
|
void *shndx)
|
void *shndx)
|
{
|
{
|
unsigned int tmp;
|
unsigned int tmp;
|
Elf_External_Sym *dst = cdst;
|
Elf_External_Sym *dst = (Elf_External_Sym *) cdst;
|
H_PUT_32 (abfd, src->st_name, dst->st_name);
|
H_PUT_32 (abfd, src->st_name, dst->st_name);
|
H_PUT_WORD (abfd, src->st_value, dst->st_value);
|
H_PUT_WORD (abfd, src->st_value, dst->st_value);
|
H_PUT_WORD (abfd, src->st_size, dst->st_size);
|
H_PUT_WORD (abfd, src->st_size, dst->st_size);
|
H_PUT_8 (abfd, src->st_info, dst->st_info);
|
H_PUT_8 (abfd, src->st_info, dst->st_info);
|
H_PUT_8 (abfd, src->st_other, dst->st_other);
|
H_PUT_8 (abfd, src->st_other, dst->st_other);
|
tmp = src->st_shndx;
|
tmp = src->st_shndx;
|
if (tmp > SHN_HIRESERVE)
|
if (tmp >= (SHN_LORESERVE & 0xffff) && tmp < SHN_LORESERVE)
|
{
|
{
|
if (shndx == NULL)
|
if (shndx == NULL)
|
abort ();
|
abort ();
|
H_PUT_32 (abfd, tmp, shndx);
|
H_PUT_32 (abfd, tmp, shndx);
|
tmp = SHN_XINDEX;
|
tmp = SHN_XINDEX & 0xffff;
|
}
|
}
|
H_PUT_16 (abfd, tmp, dst->st_shndx);
|
H_PUT_16 (abfd, tmp, dst->st_shndx);
|
}
|
}
|
|
|
/* Translate an ELF file header in external format into an ELF file header in
|
/* Translate an ELF file header in external format into an ELF file header in
|
Line 278... |
Line 280... |
H_PUT_16 (abfd, src->e_ehsize, dst->e_ehsize);
|
H_PUT_16 (abfd, src->e_ehsize, dst->e_ehsize);
|
H_PUT_16 (abfd, src->e_phentsize, dst->e_phentsize);
|
H_PUT_16 (abfd, src->e_phentsize, dst->e_phentsize);
|
H_PUT_16 (abfd, src->e_phnum, dst->e_phnum);
|
H_PUT_16 (abfd, src->e_phnum, dst->e_phnum);
|
H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
|
H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
|
tmp = src->e_shnum;
|
tmp = src->e_shnum;
|
if (tmp >= SHN_LORESERVE)
|
if (tmp >= (SHN_LORESERVE & 0xffff))
|
tmp = SHN_UNDEF;
|
tmp = SHN_UNDEF;
|
H_PUT_16 (abfd, tmp, dst->e_shnum);
|
H_PUT_16 (abfd, tmp, dst->e_shnum);
|
tmp = src->e_shstrndx;
|
tmp = src->e_shstrndx;
|
if (tmp >= SHN_LORESERVE)
|
if (tmp >= (SHN_LORESERVE & 0xffff))
|
tmp = SHN_XINDEX;
|
tmp = SHN_XINDEX & 0xffff;
|
H_PUT_16 (abfd, tmp, dst->e_shstrndx);
|
H_PUT_16 (abfd, tmp, dst->e_shstrndx);
|
}
|
}
|
|
|
/* Translate an ELF section header table entry in external format into an
|
/* Translate an ELF section header table entry in external format into an
|
ELF section header table entry in internal format. */
|
ELF section header table entry in internal format. */
|
Line 435... |
Line 437... |
void
|
void
|
elf_swap_dyn_in (bfd *abfd,
|
elf_swap_dyn_in (bfd *abfd,
|
const void *p,
|
const void *p,
|
Elf_Internal_Dyn *dst)
|
Elf_Internal_Dyn *dst)
|
{
|
{
|
const Elf_External_Dyn *src = p;
|
const Elf_External_Dyn *src = (const Elf_External_Dyn *) p;
|
|
|
dst->d_tag = H_GET_WORD (abfd, src->d_tag);
|
dst->d_tag = H_GET_WORD (abfd, src->d_tag);
|
dst->d_un.d_val = H_GET_WORD (abfd, src->d_un.d_val);
|
dst->d_un.d_val = H_GET_WORD (abfd, src->d_un.d_val);
|
}
|
}
|
|
|
void
|
void
|
elf_swap_dyn_out (bfd *abfd,
|
elf_swap_dyn_out (bfd *abfd,
|
const Elf_Internal_Dyn *src,
|
const Elf_Internal_Dyn *src,
|
void *p)
|
void *p)
|
{
|
{
|
Elf_External_Dyn *dst = p;
|
Elf_External_Dyn *dst = (Elf_External_Dyn *) p;
|
|
|
H_PUT_WORD (abfd, src->d_tag, dst->d_tag);
|
H_PUT_WORD (abfd, src->d_tag, dst->d_tag);
|
H_PUT_WORD (abfd, src->d_un.d_val, dst->d_un.d_val);
|
H_PUT_WORD (abfd, src->d_un.d_val, dst->d_un.d_val);
|
}
|
}
|
|
|
Line 468... |
Line 470... |
&& (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1)
|
&& (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1)
|
&& (x_ehdrp->e_ident[EI_MAG2] == ELFMAG2)
|
&& (x_ehdrp->e_ident[EI_MAG2] == ELFMAG2)
|
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
|
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
|
}
|
}
|
|
|
/* Determines if a given section index is valid. */
|
|
|
|
static inline bfd_boolean
|
|
valid_section_index_p (unsigned index, unsigned num_sections)
|
|
{
|
|
/* Note: We allow SHN_UNDEF as a valid section index. */
|
|
if (index < SHN_LORESERVE || index > SHN_HIRESERVE)
|
|
return index < num_sections;
|
|
|
|
/* We disallow the use of reserved indcies, except for those
|
|
with OS or Application specific meaning. The test make use
|
|
of the knowledge that:
|
|
SHN_LORESERVE == SHN_LOPROC
|
|
and
|
|
SHN_HIPROC == SHN_LOOS - 1 */
|
|
/* XXX - Should we allow SHN_XINDEX as a valid index here ? */
|
|
return (index >= SHN_LOPROC && index <= SHN_HIOS);
|
|
}
|
|
|
|
/* Check to see if the file associated with ABFD matches the target vector
|
/* Check to see if the file associated with ABFD matches the target vector
|
that ABFD points to.
|
that ABFD points to.
|
|
|
Note that we may be called several times with the same ABFD, but different
|
Note that we may be called several times with the same ABFD, but different
|
target vectors, most of which will not match. We have to avoid leaving
|
target vectors, most of which will not match. We have to avoid leaving
|
Line 589... |
Line 572... |
/* Further sanity check. */
|
/* Further sanity check. */
|
if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0)
|
if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0)
|
goto got_wrong_format_error;
|
goto got_wrong_format_error;
|
|
|
ebd = get_elf_backend_data (abfd);
|
ebd = get_elf_backend_data (abfd);
|
|
if (ebd->s->arch_size != ARCH_SIZE)
|
|
goto got_wrong_format_error;
|
|
|
/* Check that the ELF e_machine field matches what this particular
|
/* Check that the ELF e_machine field matches what this particular
|
BFD format expects. */
|
BFD format expects. */
|
if (ebd->elf_machine_code != i_ehdrp->e_machine
|
if (ebd->elf_machine_code != i_ehdrp->e_machine
|
&& (ebd->elf_machine_alt1 == 0
|
&& (ebd->elf_machine_alt1 == 0
|
Line 610... |
Line 595... |
const struct elf_backend_data *back;
|
const struct elf_backend_data *back;
|
|
|
if ((*target_ptr)->flavour != bfd_target_elf_flavour)
|
if ((*target_ptr)->flavour != bfd_target_elf_flavour)
|
continue;
|
continue;
|
back = xvec_get_elf_backend_data (*target_ptr);
|
back = xvec_get_elf_backend_data (*target_ptr);
|
|
if (back->s->arch_size != ARCH_SIZE)
|
|
continue;
|
if (back->elf_machine_code == i_ehdrp->e_machine
|
if (back->elf_machine_code == i_ehdrp->e_machine
|
|| (back->elf_machine_alt1 != 0
|
|| (back->elf_machine_alt1 != 0
|
&& back->elf_machine_alt1 == i_ehdrp->e_machine)
|
&& back->elf_machine_alt1 == i_ehdrp->e_machine)
|
|| (back->elf_machine_alt2 != 0
|
|| (back->elf_machine_alt2 != 0
|
&& back->elf_machine_alt2 == i_ehdrp->e_machine))
|
&& back->elf_machine_alt2 == i_ehdrp->e_machine))
|
Line 705... |
Line 692... |
|| i_ehdrp->e_shnum == 0)
|
|| i_ehdrp->e_shnum == 0)
|
goto got_wrong_format_error;
|
goto got_wrong_format_error;
|
}
|
}
|
|
|
/* And similarly for the string table index. */
|
/* And similarly for the string table index. */
|
if (i_ehdrp->e_shstrndx == SHN_XINDEX)
|
if (i_ehdrp->e_shstrndx == (SHN_XINDEX & 0xffff))
|
{
|
{
|
i_ehdrp->e_shstrndx = i_shdr.sh_link;
|
i_ehdrp->e_shstrndx = i_shdr.sh_link;
|
if (i_ehdrp->e_shstrndx != i_shdr.sh_link)
|
if (i_ehdrp->e_shstrndx != i_shdr.sh_link)
|
goto got_wrong_format_error;
|
goto got_wrong_format_error;
|
}
|
}
|
Line 747... |
Line 734... |
{
|
{
|
Elf_Internal_Shdr *shdrp;
|
Elf_Internal_Shdr *shdrp;
|
unsigned int num_sec;
|
unsigned int num_sec;
|
|
|
amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum;
|
amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum;
|
i_shdrp = bfd_alloc (abfd, amt);
|
i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
|
if (!i_shdrp)
|
if (!i_shdrp)
|
goto got_no_match;
|
goto got_no_match;
|
num_sec = i_ehdrp->e_shnum;
|
num_sec = i_ehdrp->e_shnum;
|
if (num_sec > SHN_LORESERVE)
|
|
num_sec += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
elf_numsections (abfd) = num_sec;
|
elf_numsections (abfd) = num_sec;
|
amt = sizeof (i_shdrp) * num_sec;
|
amt = sizeof (i_shdrp) * num_sec;
|
elf_elfsections (abfd) = bfd_alloc (abfd, amt);
|
elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
|
if (!elf_elfsections (abfd))
|
if (!elf_elfsections (abfd))
|
goto got_no_match;
|
goto got_no_match;
|
|
|
memcpy (i_shdrp, &i_shdr, sizeof (*i_shdrp));
|
memcpy (i_shdrp, &i_shdr, sizeof (*i_shdrp));
|
shdrp = i_shdrp;
|
for (shdrp = i_shdrp, shindex = 0; shindex < num_sec; shindex++)
|
shindex = 0;
|
|
if (num_sec > SHN_LORESERVE)
|
|
{
|
|
for ( ; shindex < SHN_LORESERVE; shindex++)
|
|
elf_elfsections (abfd)[shindex] = shdrp++;
|
|
for ( ; shindex < SHN_HIRESERVE + 1; shindex++)
|
|
elf_elfsections (abfd)[shindex] = i_shdrp;
|
|
}
|
|
for ( ; shindex < num_sec; shindex++)
|
|
elf_elfsections (abfd)[shindex] = shdrp++;
|
elf_elfsections (abfd)[shindex] = shdrp++;
|
|
|
/* Read in the rest of the section header table and convert it
|
/* Read in the rest of the section header table and convert it
|
to internal form. */
|
to internal form. */
|
for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
|
for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
|
Line 781... |
Line 757... |
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
|
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
|
goto got_no_match;
|
goto got_no_match;
|
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
|
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
|
|
|
/* Sanity check sh_link and sh_info. */
|
/* Sanity check sh_link and sh_info. */
|
if (! valid_section_index_p (i_shdrp[shindex].sh_link, num_sec))
|
if (i_shdrp[shindex].sh_link >= num_sec)
|
|
{
|
|
/* PR 10478: Accept sparc binaries with a sh_link
|
|
field set to SHN_BEFORE or SHN_AFTER. */
|
|
switch (ebd->elf_machine_code)
|
|
{
|
|
case EM_OLD_SPARCV9:
|
|
case EM_SPARC32PLUS:
|
|
case EM_SPARCV9:
|
|
case EM_SPARC:
|
|
if (i_shdrp[shindex].sh_link == (SHN_LORESERVE & 0xffff) /* SHN_BEFORE */
|
|
|| i_shdrp[shindex].sh_link == ((SHN_LORESERVE + 1) & 0xffff) /* SHN_AFTER */)
|
|
break;
|
|
/* Otherwise fall through. */
|
|
default:
|
goto got_wrong_format_error;
|
goto got_wrong_format_error;
|
|
}
|
|
}
|
|
|
if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK)
|
if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK)
|
|| i_shdrp[shindex].sh_type == SHT_RELA
|
|| i_shdrp[shindex].sh_type == SHT_RELA
|
|| i_shdrp[shindex].sh_type == SHT_REL)
|
|| i_shdrp[shindex].sh_type == SHT_REL)
|
&& ! valid_section_index_p (i_shdrp[shindex].sh_info, num_sec))
|
&& i_shdrp[shindex].sh_info >= num_sec)
|
goto got_wrong_format_error;
|
goto got_wrong_format_error;
|
|
|
/* If the section is loaded, but not page aligned, clear
|
/* If the section is loaded, but not page aligned, clear
|
D_PAGED. */
|
D_PAGED. */
|
if (i_shdrp[shindex].sh_size != 0
|
if (i_shdrp[shindex].sh_size != 0
|
Line 805... |
Line 797... |
}
|
}
|
|
|
/* A further sanity check. */
|
/* A further sanity check. */
|
if (i_ehdrp->e_shnum != 0)
|
if (i_ehdrp->e_shnum != 0)
|
{
|
{
|
if (! valid_section_index_p (i_ehdrp->e_shstrndx, elf_numsections (abfd)))
|
if (i_ehdrp->e_shstrndx >= elf_numsections (abfd))
|
{
|
{
|
/* PR 2257:
|
/* PR 2257:
|
We used to just goto got_wrong_format_error here
|
We used to just goto got_wrong_format_error here
|
but there are binaries in existance for which this test
|
but there are binaries in existance for which this test
|
will prevent the binutils from working with them at all.
|
will prevent the binutils from working with them at all.
|
Line 829... |
Line 821... |
{
|
{
|
Elf_Internal_Phdr *i_phdr;
|
Elf_Internal_Phdr *i_phdr;
|
unsigned int i;
|
unsigned int i;
|
|
|
amt = i_ehdrp->e_phnum * sizeof (Elf_Internal_Phdr);
|
amt = i_ehdrp->e_phnum * sizeof (Elf_Internal_Phdr);
|
elf_tdata (abfd)->phdr = bfd_alloc (abfd, amt);
|
elf_tdata (abfd)->phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
|
if (elf_tdata (abfd)->phdr == NULL)
|
if (elf_tdata (abfd)->phdr == NULL)
|
goto got_no_match;
|
goto got_no_match;
|
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
|
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
|
goto got_no_match;
|
goto got_no_match;
|
i_phdr = elf_tdata (abfd)->phdr;
|
i_phdr = elf_tdata (abfd)->phdr;
|
Line 854... |
Line 846... |
/* Once all of the section headers have been read and converted, we
|
/* Once all of the section headers have been read and converted, we
|
can start processing them. Note that the first section header is
|
can start processing them. Note that the first section header is
|
a dummy placeholder entry, so we ignore it. */
|
a dummy placeholder entry, so we ignore it. */
|
num_sec = elf_numsections (abfd);
|
num_sec = elf_numsections (abfd);
|
for (shindex = 1; shindex < num_sec; shindex++)
|
for (shindex = 1; shindex < num_sec; shindex++)
|
{
|
|
if (! bfd_section_from_shdr (abfd, shindex))
|
if (! bfd_section_from_shdr (abfd, shindex))
|
goto got_no_match;
|
goto got_no_match;
|
if (shindex == SHN_LORESERVE - 1)
|
|
shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
}
|
|
|
|
/* Set up ELF sections for SHF_GROUP and SHF_LINK_ORDER. */
|
/* Set up ELF sections for SHF_GROUP and SHF_LINK_ORDER. */
|
if (! _bfd_elf_setup_sections (abfd))
|
if (! _bfd_elf_setup_sections (abfd))
|
goto got_wrong_format_error;
|
goto got_wrong_format_error;
|
}
|
}
|
Line 924... |
Line 912... |
/* Write out the relocs. */
|
/* Write out the relocs. */
|
|
|
void
|
void
|
elf_write_relocs (bfd *abfd, asection *sec, void *data)
|
elf_write_relocs (bfd *abfd, asection *sec, void *data)
|
{
|
{
|
bfd_boolean *failedp = data;
|
bfd_boolean *failedp = (bfd_boolean *) data;
|
Elf_Internal_Shdr *rela_hdr;
|
Elf_Internal_Shdr *rela_hdr;
|
bfd_vma addr_offset;
|
bfd_vma addr_offset;
|
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
|
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
|
size_t extsize;
|
size_t extsize;
|
bfd_byte *dst_rela;
|
bfd_byte *dst_rela;
|
Line 957... |
Line 945... |
return;
|
return;
|
|
|
rela_hdr = &elf_section_data (sec)->rel_hdr;
|
rela_hdr = &elf_section_data (sec)->rel_hdr;
|
|
|
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
|
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
|
rela_hdr->contents = bfd_alloc (abfd, rela_hdr->sh_size);
|
rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size);
|
if (rela_hdr->contents == NULL)
|
if (rela_hdr->contents == NULL)
|
{
|
{
|
*failedp = TRUE;
|
*failedp = TRUE;
|
return;
|
return;
|
}
|
}
|
Line 1079... |
Line 1067... |
|| bfd_bwrite (&x_ehdr, amt, abfd) != amt)
|
|| bfd_bwrite (&x_ehdr, amt, abfd) != amt)
|
return FALSE;
|
return FALSE;
|
|
|
/* Some fields in the first section header handle overflow of ehdr
|
/* Some fields in the first section header handle overflow of ehdr
|
fields. */
|
fields. */
|
if (i_ehdrp->e_shnum >= SHN_LORESERVE)
|
if (i_ehdrp->e_shnum >= (SHN_LORESERVE & 0xffff))
|
i_shdrp[0]->sh_size = i_ehdrp->e_shnum;
|
i_shdrp[0]->sh_size = i_ehdrp->e_shnum;
|
if (i_ehdrp->e_shstrndx >= SHN_LORESERVE)
|
if (i_ehdrp->e_shstrndx >= (SHN_LORESERVE & 0xffff))
|
i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
|
i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
|
|
|
/* at this point we've concocted all the ELF sections... */
|
/* at this point we've concocted all the ELF sections... */
|
amt = i_ehdrp->e_shnum;
|
amt = i_ehdrp->e_shnum;
|
amt *= sizeof (*x_shdrp);
|
amt *= sizeof (*x_shdrp);
|
x_shdrp = bfd_alloc (abfd, amt);
|
x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
|
if (!x_shdrp)
|
if (!x_shdrp)
|
return FALSE;
|
return FALSE;
|
|
|
for (count = 0; count < i_ehdrp->e_shnum; i_shdrp++, count++)
|
for (count = 0; count < i_ehdrp->e_shnum; i_shdrp++, count++)
|
{
|
{
|
#if DEBUG & 2
|
#if DEBUG & 2
|
elf_debug_section (count, *i_shdrp);
|
elf_debug_section (count, *i_shdrp);
|
#endif
|
#endif
|
elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count);
|
elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count);
|
|
|
if (count == SHN_LORESERVE - 1)
|
|
i_shdrp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
|
|
}
|
}
|
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
|
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
|
|| bfd_bwrite (x_shdrp, amt, abfd) != amt)
|
|| bfd_bwrite (x_shdrp, amt, abfd) != amt)
|
return FALSE;
|
return FALSE;
|
|
|
Line 1218... |
Line 1203... |
if (isymbuf == NULL)
|
if (isymbuf == NULL)
|
return -1;
|
return -1;
|
|
|
amt = symcount;
|
amt = symcount;
|
amt *= sizeof (elf_symbol_type);
|
amt *= sizeof (elf_symbol_type);
|
symbase = bfd_zalloc (abfd, amt);
|
symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
|
if (symbase == (elf_symbol_type *) NULL)
|
if (symbase == (elf_symbol_type *) NULL)
|
goto error_return;
|
goto error_return;
|
|
|
/* Read the raw ELF version symbol information. */
|
/* Read the raw ELF version symbol information. */
|
if (verhdr != NULL
|
if (verhdr != NULL
|
Line 1242... |
Line 1227... |
if (verhdr != NULL)
|
if (verhdr != NULL)
|
{
|
{
|
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
|
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
|
goto error_return;
|
goto error_return;
|
|
|
xverbuf = bfd_malloc (verhdr->sh_size);
|
xverbuf = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
|
if (xverbuf == NULL && verhdr->sh_size != 0)
|
if (xverbuf == NULL && verhdr->sh_size != 0)
|
goto error_return;
|
goto error_return;
|
|
|
if (bfd_bread (xverbuf, verhdr->sh_size, abfd) != verhdr->sh_size)
|
if (bfd_bread (xverbuf, verhdr->sh_size, abfd) != verhdr->sh_size)
|
goto error_return;
|
goto error_return;
|
Line 1268... |
Line 1253... |
|
|
if (isym->st_shndx == SHN_UNDEF)
|
if (isym->st_shndx == SHN_UNDEF)
|
{
|
{
|
sym->symbol.section = bfd_und_section_ptr;
|
sym->symbol.section = bfd_und_section_ptr;
|
}
|
}
|
else if (isym->st_shndx < SHN_LORESERVE
|
|
|| isym->st_shndx > SHN_HIRESERVE)
|
|
{
|
|
sym->symbol.section = bfd_section_from_elf_index (abfd,
|
|
isym->st_shndx);
|
|
if (sym->symbol.section == NULL)
|
|
{
|
|
/* This symbol is in a section for which we did not
|
|
create a BFD section. Just use bfd_abs_section,
|
|
although it is wrong. FIXME. */
|
|
sym->symbol.section = bfd_abs_section_ptr;
|
|
}
|
|
}
|
|
else if (isym->st_shndx == SHN_ABS)
|
else if (isym->st_shndx == SHN_ABS)
|
{
|
{
|
sym->symbol.section = bfd_abs_section_ptr;
|
sym->symbol.section = bfd_abs_section_ptr;
|
}
|
}
|
else if (isym->st_shndx == SHN_COMMON)
|
else if (isym->st_shndx == SHN_COMMON)
|
Line 1295... |
Line 1267... |
size in the value field, and doesn't care (at the
|
size in the value field, and doesn't care (at the
|
moment) about the alignment. */
|
moment) about the alignment. */
|
sym->symbol.value = isym->st_size;
|
sym->symbol.value = isym->st_size;
|
}
|
}
|
else
|
else
|
|
{
|
|
sym->symbol.section
|
|
= bfd_section_from_elf_index (abfd, isym->st_shndx);
|
|
if (sym->symbol.section == NULL)
|
|
{
|
|
/* This symbol is in a section for which we did not
|
|
create a BFD section. Just use bfd_abs_section,
|
|
although it is wrong. FIXME. */
|
sym->symbol.section = bfd_abs_section_ptr;
|
sym->symbol.section = bfd_abs_section_ptr;
|
|
}
|
|
}
|
|
|
/* If this is a relocatable file, then the symbol value is
|
/* If this is a relocatable file, then the symbol value is
|
already section relative. */
|
already section relative. */
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
|
sym->symbol.value -= sym->symbol.section->vma;
|
sym->symbol.value -= sym->symbol.section->vma;
|
Line 1314... |
Line 1296... |
sym->symbol.flags |= BSF_GLOBAL;
|
sym->symbol.flags |= BSF_GLOBAL;
|
break;
|
break;
|
case STB_WEAK:
|
case STB_WEAK:
|
sym->symbol.flags |= BSF_WEAK;
|
sym->symbol.flags |= BSF_WEAK;
|
break;
|
break;
|
|
case STB_GNU_UNIQUE:
|
|
sym->symbol.flags |= BSF_GNU_UNIQUE;
|
|
break;
|
}
|
}
|
|
|
switch (ELF_ST_TYPE (isym->st_info))
|
switch (ELF_ST_TYPE (isym->st_info))
|
{
|
{
|
case STT_SECTION:
|
case STT_SECTION:
|
Line 1343... |
Line 1328... |
sym->symbol.flags |= BSF_RELC;
|
sym->symbol.flags |= BSF_RELC;
|
break;
|
break;
|
case STT_SRELC:
|
case STT_SRELC:
|
sym->symbol.flags |= BSF_SRELC;
|
sym->symbol.flags |= BSF_SRELC;
|
break;
|
break;
|
|
case STT_GNU_IFUNC:
|
|
sym->symbol.flags |= BSF_GNU_INDIRECT_FUNCTION;
|
|
break;
|
}
|
}
|
|
|
if (dynamic)
|
if (dynamic)
|
sym->symbol.flags |= BSF_DYNAMIC;
|
sym->symbol.flags |= BSF_DYNAMIC;
|
|
|
Line 1428... |
Line 1416... |
if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
|
if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
|
|| (bfd_bread (allocated, rel_hdr->sh_size, abfd)
|
|| (bfd_bread (allocated, rel_hdr->sh_size, abfd)
|
!= rel_hdr->sh_size))
|
!= rel_hdr->sh_size))
|
goto error_return;
|
goto error_return;
|
|
|
native_relocs = allocated;
|
native_relocs = (bfd_byte *) allocated;
|
|
|
entsize = rel_hdr->sh_entsize;
|
entsize = rel_hdr->sh_entsize;
|
BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
|
BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
|
|| entsize == sizeof (Elf_External_Rela));
|
|| entsize == sizeof (Elf_External_Rela));
|
|
|
Line 1549... |
Line 1537... |
rel_hdr2 = NULL;
|
rel_hdr2 = NULL;
|
reloc_count2 = 0;
|
reloc_count2 = 0;
|
}
|
}
|
|
|
amt = (reloc_count + reloc_count2) * sizeof (arelent);
|
amt = (reloc_count + reloc_count2) * sizeof (arelent);
|
relents = bfd_alloc (abfd, amt);
|
relents = (arelent *) bfd_alloc (abfd, amt);
|
if (relents == NULL)
|
if (relents == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
if (!elf_slurp_reloc_table_from_section (abfd, asect,
|
if (!elf_slurp_reloc_table_from_section (abfd, asect,
|
rel_hdr, reloc_count,
|
rel_hdr, reloc_count,
|
Line 1700... |
Line 1688... |
{
|
{
|
bfd_set_error (bfd_error_wrong_format);
|
bfd_set_error (bfd_error_wrong_format);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
x_phdrs = bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
|
x_phdrs = (Elf_External_Phdr *)
|
|
bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
|
if (x_phdrs == NULL)
|
if (x_phdrs == NULL)
|
{
|
{
|
bfd_set_error (bfd_error_no_memory);
|
bfd_set_error (bfd_error_no_memory);
|
return NULL;
|
return NULL;
|
}
|
}
|
Line 1768... |
Line 1757... |
}
|
}
|
else
|
else
|
contents_size = last_phdr->p_offset + last_phdr->p_filesz;
|
contents_size = last_phdr->p_offset + last_phdr->p_filesz;
|
|
|
/* Now we know the size of the whole image we want read in. */
|
/* Now we know the size of the whole image we want read in. */
|
contents = bfd_zmalloc (contents_size);
|
contents = (bfd_byte *) bfd_zmalloc (contents_size);
|
if (contents == NULL)
|
if (contents == NULL)
|
{
|
{
|
free (x_phdrs);
|
free (x_phdrs);
|
bfd_set_error (bfd_error_no_memory);
|
bfd_set_error (bfd_error_no_memory);
|
return NULL;
|
return NULL;
|
Line 1813... |
Line 1802... |
/* This will normally have been in the first PT_LOAD segment. But it
|
/* This will normally have been in the first PT_LOAD segment. But it
|
conceivably could be missing, and we might have just changed it. */
|
conceivably could be missing, and we might have just changed it. */
|
memcpy (contents, &x_ehdr, sizeof x_ehdr);
|
memcpy (contents, &x_ehdr, sizeof x_ehdr);
|
|
|
/* Now we have a memory image of the ELF file contents. Make a BFD. */
|
/* Now we have a memory image of the ELF file contents. Make a BFD. */
|
bim = bfd_malloc (sizeof (struct bfd_in_memory));
|
bim = (struct bfd_in_memory *) bfd_malloc (sizeof (struct bfd_in_memory));
|
if (bim == NULL)
|
if (bim == NULL)
|
{
|
{
|
free (contents);
|
free (contents);
|
bfd_set_error (bfd_error_no_memory);
|
bfd_set_error (bfd_error_no_memory);
|
return NULL;
|
return NULL;
|