/* ELF executable support for BFD.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
in "UNIX System V Release 4, Programmers Guide: ANSI C and
Meissner (Open Software Foundation), and Peter Hoogenboom (University
of Utah) to finish and extend this.
-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
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* Problems and other issues to resolve.
it's cast in stone.
*/
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libiberty.h"
#include "bfdlink.h"
#include "libbfd.h"
#define elf_find_section NAME(bfd_elf,find_section)
#define elf_write_shdrs_and_ehdr NAME(bfd_elf,write_shdrs_and_ehdr)
#define elf_write_out_phdrs NAME(bfd_elf,write_out_phdrs)
+#define elf_checksum_contents NAME(bfd_elf,checksum_contents)
#define elf_write_relocs NAME(bfd_elf,write_relocs)
#define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table)
#define LOG_FILE_ALIGN 2
#endif
-#ifdef DEBUG
+#if DEBUG & 2
static void elf_debug_section (int, Elf_Internal_Shdr *);
+#endif
+#if DEBUG & 1
static void elf_debug_file (Elf_Internal_Ehdr *);
-static char *elf_symbol_flags (flagword);
#endif
\f
/* Structure swapping routines */
/* Translate an ELF symbol in external format into an ELF symbol in internal
format. */
-void
+bfd_boolean
elf_swap_symbol_in (bfd *abfd,
const void *psrc,
const void *pshn,
Elf_Internal_Sym *dst)
{
- const Elf_External_Sym *src = psrc;
- const Elf_External_Sym_Shndx *shndx = pshn;
+ const Elf_External_Sym *src = (const Elf_External_Sym *) psrc;
+ const Elf_External_Sym_Shndx *shndx = (const Elf_External_Sym_Shndx *) pshn;
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
dst->st_name = H_GET_32 (abfd, src->st_name);
dst->st_info = H_GET_8 (abfd, src->st_info);
dst->st_other = H_GET_8 (abfd, src->st_other);
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)
- abort ();
+ return FALSE;
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;
}
/* Translate an ELF symbol in internal format into an ELF symbol in external
void *shndx)
{
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_WORD (abfd, src->st_value, dst->st_value);
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_other, dst->st_other);
tmp = src->st_shndx;
- if (tmp > SHN_HIRESERVE)
+ if (tmp >= (SHN_LORESERVE & 0xffff) && tmp < SHN_LORESERVE)
{
if (shndx == NULL)
abort ();
H_PUT_32 (abfd, tmp, shndx);
- tmp = SHN_XINDEX;
+ tmp = SHN_XINDEX & 0xffff;
}
H_PUT_16 (abfd, tmp, dst->st_shndx);
}
H_PUT_32 (abfd, src->e_flags, dst->e_flags);
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_phnum, dst->e_phnum);
+ tmp = src->e_phnum;
+ if (tmp > PN_XNUM)
+ tmp = PN_XNUM;
+ H_PUT_16 (abfd, tmp, dst->e_phnum);
H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
tmp = src->e_shnum;
- if (tmp >= SHN_LORESERVE)
+ if (tmp >= (SHN_LORESERVE & 0xffff))
tmp = SHN_UNDEF;
H_PUT_16 (abfd, tmp, dst->e_shnum);
tmp = src->e_shstrndx;
- if (tmp >= SHN_LORESERVE)
- tmp = SHN_XINDEX;
+ if (tmp >= (SHN_LORESERVE & 0xffff))
+ tmp = SHN_XINDEX & 0xffff;
H_PUT_16 (abfd, tmp, dst->e_shstrndx);
}
const Elf_Internal_Phdr *src,
Elf_External_Phdr *dst)
{
+ const struct elf_backend_data *bed;
+ bfd_vma p_paddr;
+
+ bed = get_elf_backend_data (abfd);
+ p_paddr = bed->want_p_paddr_set_to_zero ? 0 : src->p_paddr;
+
/* note that all elements of dst are *arrays of unsigned char* already... */
H_PUT_32 (abfd, src->p_type, dst->p_type);
H_PUT_WORD (abfd, src->p_offset, dst->p_offset);
H_PUT_WORD (abfd, src->p_vaddr, dst->p_vaddr);
- H_PUT_WORD (abfd, src->p_paddr, dst->p_paddr);
+ H_PUT_WORD (abfd, p_paddr, dst->p_paddr);
H_PUT_WORD (abfd, src->p_filesz, dst->p_filesz);
H_PUT_WORD (abfd, src->p_memsz, dst->p_memsz);
H_PUT_32 (abfd, src->p_flags, dst->p_flags);
const void *p,
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_un.d_val = H_GET_WORD (abfd, src->d_un.d_val);
const Elf_Internal_Dyn *src,
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_un.d_val, dst->d_un.d_val);
struct bfd_preserve preserve;
asection *s;
bfd_size_type amt;
+ const bfd_target *target;
+ const bfd_target * const *target_ptr;
preserve.marker = NULL;
if (!bfd_preserve_save (abfd, &preserve))
goto got_no_match;
+ target = abfd->xvec;
+
/* Allocate an instance of the elf_obj_tdata structure and hook it up to
the tdata pointer in the bfd. */
- if (! (*abfd->xvec->_bfd_set_format[bfd_object]) (abfd))
+ if (! (*target->_bfd_set_format[bfd_object]) (abfd))
goto got_no_match;
preserve.marker = elf_tdata (abfd);
if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_type == ET_REL)
goto got_wrong_format_error;
- /* As a simple sanity check, verify that the what BFD thinks is the
+ /* As a simple sanity check, verify that what BFD thinks is the
size of each section header table entry actually matches the size
recorded in the file, but only if there are any sections. */
if (i_ehdrp->e_shentsize != sizeof (x_shdr) && i_ehdrp->e_shnum != 0)
goto got_wrong_format_error;
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
BFD format expects. */
&& (ebd->elf_machine_alt2 == 0
|| i_ehdrp->e_machine != ebd->elf_machine_alt2))
{
- const bfd_target * const *target_ptr;
-
if (ebd->elf_machine_code != EM_NONE)
goto got_wrong_format_error;
if ((*target_ptr)->flavour != bfd_target_elf_flavour)
continue;
- back = (const struct elf_backend_data *) (*target_ptr)->backend_data;
+ 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
|| (back->elf_machine_alt1 != 0
&& back->elf_machine_alt1 == i_ehdrp->e_machine)
goto got_no_match;
}
- /* Remember the entry point specified in the ELF file header. */
- bfd_set_start_address (abfd, i_ehdrp->e_entry);
+ if (ebd->elf_machine_code != EM_NONE
+ && i_ehdrp->e_ident[EI_OSABI] != ebd->elf_osabi)
+ {
+ if (ebd->elf_osabi != ELFOSABI_NONE)
+ goto got_wrong_format_error;
+
+ /* This is an ELFOSABI_NONE ELF target. Let it match any ELF
+ target of the compatible machine for which we do not have a
+ backend with matching ELFOSABI. */
+ for (target_ptr = bfd_target_vector;
+ *target_ptr != NULL;
+ target_ptr++)
+ {
+ const struct elf_backend_data *back;
+
+ /* Skip this target and targets with incompatible byte
+ order. */
+ if (*target_ptr == target
+ || (*target_ptr)->flavour != bfd_target_elf_flavour
+ || (*target_ptr)->byteorder != target->byteorder
+ || ((*target_ptr)->header_byteorder
+ != target->header_byteorder))
+ continue;
+
+ back = xvec_get_elf_backend_data (*target_ptr);
+ if (back->elf_osabi == i_ehdrp->e_ident[EI_OSABI]
+ && (back->elf_machine_code == i_ehdrp->e_machine
+ || (back->elf_machine_alt1 != 0
+ && back->elf_machine_alt1 == i_ehdrp->e_machine)
+ || (back->elf_machine_alt2 != 0
+ && back->elf_machine_alt2 == i_ehdrp->e_machine)))
+ {
+ /* target_ptr is an ELF backend which matches this
+ object file, so reject the ELFOSABI_NONE ELF target. */
+ goto got_wrong_format_error;
+ }
+ }
+ }
if (i_ehdrp->e_shoff != 0)
{
}
/* 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;
if (i_ehdrp->e_shstrndx != i_shdr.sh_link)
goto got_wrong_format_error;
}
+ /* And program headers. */
+ if (i_ehdrp->e_phnum == PN_XNUM && i_shdr.sh_info != 0)
+ {
+ i_ehdrp->e_phnum = i_shdr.sh_info;
+ if (i_ehdrp->e_phnum != i_shdr.sh_info)
+ goto got_wrong_format_error;
+ }
+
/* Sanity check that we can read all of the section headers.
It ought to be good enough to just read the last one. */
if (i_ehdrp->e_shnum != 1)
unsigned int num_sec;
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)
goto got_no_match;
num_sec = i_ehdrp->e_shnum;
- if (num_sec > SHN_LORESERVE)
- num_sec += SHN_HIRESERVE + 1 - SHN_LORESERVE;
elf_numsections (abfd) = 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))
goto got_no_match;
memcpy (i_shdrp, &i_shdr, sizeof (*i_shdrp));
- shdrp = i_shdrp;
- 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++)
+ for (shdrp = i_shdrp, shindex = 0; shindex < num_sec; shindex++)
elf_elfsections (abfd)[shindex] = shdrp++;
/* Read in the rest of the section header table and convert it
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
/* Sanity check sh_link and sh_info. */
- if (i_shdrp[shindex].sh_link >= num_sec
- || (i_shdrp[shindex].sh_link >= SHN_LORESERVE
- && i_shdrp[shindex].sh_link <= SHN_HIRESERVE))
- goto got_wrong_format_error;
+ if (i_shdrp[shindex].sh_link >= num_sec)
+ {
+ /* PR 10478: Accept Solaris binaries with a sh_link
+ field set to SHN_BEFORE or SHN_AFTER. */
+ switch (ebd->elf_machine_code)
+ {
+ case EM_386:
+ case EM_486:
+ case EM_X86_64:
+ 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;
+ }
+ }
if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK)
|| i_shdrp[shindex].sh_type == SHT_RELA
|| i_shdrp[shindex].sh_type == SHT_REL)
- && (i_shdrp[shindex].sh_info >= num_sec
- || (i_shdrp[shindex].sh_info >= SHN_LORESERVE
- && i_shdrp[shindex].sh_info <= SHN_HIRESERVE)))
+ && i_shdrp[shindex].sh_info >= num_sec)
goto got_wrong_format_error;
/* If the section is loaded, but not page aligned, clear
/* A further sanity check. */
if (i_ehdrp->e_shnum != 0)
{
- if (i_ehdrp->e_shstrndx >= elf_numsections (abfd)
- || (i_ehdrp->e_shstrndx >= SHN_LORESERVE
- && i_ehdrp->e_shstrndx <= SHN_HIRESERVE))
- goto got_wrong_format_error;
+ if (i_ehdrp->e_shstrndx >= elf_numsections (abfd))
+ {
+ /* PR 2257:
+ We used to just goto got_wrong_format_error here
+ but there are binaries in existance for which this test
+ will prevent the binutils from working with them at all.
+ So we are kind, and reset the string index value to 0
+ so that at least some processing can be done. */
+ i_ehdrp->e_shstrndx = SHN_UNDEF;
+ _bfd_error_handler (_("warning: %s has a corrupt string table index - ignoring"), abfd->filename);
+ }
}
- else if (i_ehdrp->e_shstrndx != 0)
+ else if (i_ehdrp->e_shstrndx != SHN_UNDEF)
goto got_wrong_format_error;
/* Read in the program headers. */
unsigned int i;
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)
goto got_no_match;
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
a dummy placeholder entry, so we ignore it. */
num_sec = elf_numsections (abfd);
for (shindex = 1; shindex < num_sec; shindex++)
- {
- if (! bfd_section_from_shdr (abfd, shindex))
- goto got_no_match;
- if (shindex == SHN_LORESERVE - 1)
- shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE;
- }
+ if (!bfd_section_from_shdr (abfd, shindex))
+ goto got_no_match;
/* Set up ELF sections for SHF_GROUP and SHF_LINK_ORDER. */
if (! _bfd_elf_setup_sections (abfd))
goto got_wrong_format_error;
}
+ /* Remember the entry point specified in the ELF file header. */
+ bfd_set_start_address (abfd, i_ehdrp->e_entry);
+
/* If we have created any reloc sections that are associated with
debugging sections, mark the reloc sections as debugging as well. */
for (s = abfd->sections; s != NULL; s = s->next)
}
bfd_preserve_finish (abfd, &preserve);
- return abfd->xvec;
+ return target;
got_wrong_format_error:
/* There is way too much undoing of half-known state here. The caller,
void
elf_write_relocs (bfd *abfd, asection *sec, void *data)
{
- bfd_boolean *failedp = data;
+ bfd_boolean *failedp = (bfd_boolean *) data;
Elf_Internal_Shdr *rela_hdr;
bfd_vma addr_offset;
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
rela_hdr = &elf_section_data (sec)->rel_hdr;
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)
{
*failedp = TRUE;
/* Some fields in the first section header handle overflow of ehdr
fields. */
- if (i_ehdrp->e_shnum >= SHN_LORESERVE)
+ if (i_ehdrp->e_phnum >= PN_XNUM)
+ i_shdrp[0]->sh_info = i_ehdrp->e_phnum;
+ if (i_ehdrp->e_shnum >= (SHN_LORESERVE & 0xffff))
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;
/* at this point we've concocted all the ELF sections... */
amt = i_ehdrp->e_shnum;
amt *= sizeof (*x_shdrp);
- x_shdrp = bfd_alloc (abfd, amt);
+ x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
if (!x_shdrp)
return FALSE;
elf_debug_section (count, *i_shdrp);
#endif
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
|| bfd_bwrite (x_shdrp, amt, abfd) != amt)
return TRUE;
}
+bfd_boolean
+elf_checksum_contents (bfd *abfd,
+ void (*process) (const void *, size_t, void *),
+ void *arg)
+{
+ Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+ Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
+ Elf_Internal_Phdr *i_phdrp = elf_tdata (abfd)->phdr;
+ unsigned int count, num;
+
+ {
+ Elf_External_Ehdr x_ehdr;
+ Elf_Internal_Ehdr i_ehdr;
+
+ i_ehdr = *i_ehdrp;
+ i_ehdr.e_phoff = i_ehdr.e_shoff = 0;
+ elf_swap_ehdr_out (abfd, &i_ehdr, &x_ehdr);
+ (*process) (&x_ehdr, sizeof x_ehdr, arg);
+ }
+
+ num = i_ehdrp->e_phnum;
+ for (count = 0; count < num; count++)
+ {
+ Elf_External_Phdr x_phdr;
+ elf_swap_phdr_out (abfd, &i_phdrp[count], &x_phdr);
+ (*process) (&x_phdr, sizeof x_phdr, arg);
+ }
+
+ num = elf_numsections (abfd);
+ for (count = 0; count < num; count++)
+ {
+ Elf_Internal_Shdr i_shdr;
+ Elf_External_Shdr x_shdr;
+
+ i_shdr = *i_shdrp[count];
+ i_shdr.sh_offset = 0;
+
+ elf_swap_shdr_out (abfd, &i_shdr, &x_shdr);
+ (*process) (&x_shdr, sizeof x_shdr, arg);
+
+ if (i_shdr.contents)
+ (*process) (i_shdr.contents, i_shdr.sh_size, arg);
+ }
+
+ return TRUE;
+}
+
long
elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
{
amt = symcount;
amt *= sizeof (elf_symbol_type);
- symbase = bfd_zalloc (abfd, amt);
+ symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
if (symbase == (elf_symbol_type *) NULL)
goto error_return;
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
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)
goto error_return;
{
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)
{
sym->symbol.section = bfd_abs_section_ptr;
sym->symbol.value = isym->st_size;
}
else
- sym->symbol.section = bfd_abs_section_ptr;
+ {
+ 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;
+ }
+ }
/* If this is a relocatable file, then the symbol value is
already section relative. */
case STB_WEAK:
sym->symbol.flags |= BSF_WEAK;
break;
+ case STB_GNU_UNIQUE:
+ sym->symbol.flags |= BSF_GNU_UNIQUE;
+ break;
}
switch (ELF_ST_TYPE (isym->st_info))
case STT_FUNC:
sym->symbol.flags |= BSF_FUNCTION;
break;
+ case STT_COMMON:
+ /* FIXME: Do we have to put the size field into the value field
+ as we do with symbols in SHN_COMMON sections (see above) ? */
+ /* Fall through. */
case STT_OBJECT:
sym->symbol.flags |= BSF_OBJECT;
break;
case STT_TLS:
sym->symbol.flags |= BSF_THREAD_LOCAL;
break;
+ case STT_RELC:
+ sym->symbol.flags |= BSF_RELC;
+ break;
+ case STT_SRELC:
+ sym->symbol.flags |= BSF_SRELC;
+ break;
+ case STT_GNU_IFUNC:
+ sym->symbol.flags |= BSF_GNU_INDIRECT_FUNCTION;
+ break;
}
if (dynamic)
!= rel_hdr->sh_size))
goto error_return;
- native_relocs = allocated;
+ native_relocs = (bfd_byte *) allocated;
entsize = rel_hdr->sh_entsize;
BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
}
else
{
- asymbol **ps, *s;
+ asymbol **ps;
ps = symbols + ELF_R_SYM (rela.r_info) - 1;
- s = *ps;
relent->sym_ptr_ptr = ps;
}
}
amt = (reloc_count + reloc_count2) * sizeof (arelent);
- relents = bfd_alloc (abfd, amt);
+ relents = (arelent *) bfd_alloc (abfd, amt);
if (relents == NULL)
return FALSE;
return TRUE;
}
-#ifdef DEBUG
+#if DEBUG & 2
static void
elf_debug_section (int num, Elf_Internal_Shdr *hdr)
{
(long) hdr->sh_entsize);
fflush (stderr);
}
+#endif
+#if DEBUG & 1
static void
elf_debug_file (Elf_Internal_Ehdr *ehdrp)
{
fprintf (stderr, "e_shnum = %ld\n", (long) ehdrp->e_shnum);
fprintf (stderr, "e_shentsize = %ld\n", (long) ehdrp->e_shentsize);
}
-
-static char *
-elf_symbol_flags (flagword flags)
-{
- static char buffer[1024];
-
- buffer[0] = '\0';
- if (flags & BSF_LOCAL)
- strcat (buffer, " local");
-
- if (flags & BSF_GLOBAL)
- strcat (buffer, " global");
-
- if (flags & BSF_DEBUGGING)
- strcat (buffer, " debug");
-
- if (flags & BSF_FUNCTION)
- strcat (buffer, " function");
-
- if (flags & BSF_KEEP)
- strcat (buffer, " keep");
-
- if (flags & BSF_KEEP_G)
- strcat (buffer, " keep_g");
-
- if (flags & BSF_WEAK)
- strcat (buffer, " weak");
-
- if (flags & BSF_SECTION_SYM)
- strcat (buffer, " section-sym");
-
- if (flags & BSF_OLD_COMMON)
- strcat (buffer, " old-common");
-
- if (flags & BSF_NOT_AT_END)
- strcat (buffer, " not-at-end");
-
- if (flags & BSF_CONSTRUCTOR)
- strcat (buffer, " constructor");
-
- if (flags & BSF_WARNING)
- strcat (buffer, " warning");
-
- if (flags & BSF_INDIRECT)
- strcat (buffer, " indirect");
-
- if (flags & BSF_FILE)
- strcat (buffer, " file");
-
- if (flags & DYNAMIC)
- strcat (buffer, " dynamic");
-
- if (flags & ~(BSF_LOCAL
- | BSF_GLOBAL
- | BSF_DEBUGGING
- | BSF_FUNCTION
- | BSF_KEEP
- | BSF_KEEP_G
- | BSF_WEAK
- | BSF_SECTION_SYM
- | BSF_OLD_COMMON
- | BSF_NOT_AT_END
- | BSF_CONSTRUCTOR
- | BSF_WARNING
- | BSF_INDIRECT
- | BSF_FILE
- | BSF_DYNAMIC))
- strcat (buffer, " unknown-bits");
-
- return buffer;
-}
#endif
\f
/* Create a new BFD as if by bfd_openr. Rather than opening a file,
int err;
unsigned int i;
bfd_vma loadbase;
+ bfd_boolean loadbase_set;
/* Read in the ELF header in external format. */
err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr);
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)
{
bfd_set_error (bfd_error_no_memory);
contents_size = 0;
last_phdr = NULL;
loadbase = ehdr_vma;
+ loadbase_set = FALSE;
for (i = 0; i < i_ehdr.e_phnum; ++i)
{
elf_swap_phdr_in (templ, &x_phdrs[i], &i_phdrs[i]);
- /* IA-64 vDSO may have two mappings for one segment, where one mapping
- is executable only, and one is read only. We must not use the
- executable one. */
- if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
+ if (i_phdrs[i].p_type == PT_LOAD)
{
bfd_vma segment_end;
segment_end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
if (segment_end > (bfd_vma) contents_size)
contents_size = segment_end;
- if ((i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
- loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
+ /* LOADADDR is the `Base address' from the gELF specification:
+ `lowest p_vaddr value for a PT_LOAD segment' is P_VADDR from the
+ first PT_LOAD as PT_LOADs are ordered by P_VADDR. */
+ if (!loadbase_set && (i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
+ {
+ loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
+ loadbase_set = TRUE;
+ }
last_phdr = &i_phdrs[i];
}
contents_size = last_phdr->p_offset + last_phdr->p_filesz;
/* 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)
{
free (x_phdrs);
}
for (i = 0; i < i_ehdr.e_phnum; ++i)
- /* IA-64 vDSO may have two mappings for one segment, where one mapping
- is executable only, and one is read only. We must not use the
- executable one. */
- if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
+ if (i_phdrs[i].p_type == PT_LOAD)
{
bfd_vma start = i_phdrs[i].p_offset & -i_phdrs[i].p_align;
bfd_vma end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
memcpy (contents, &x_ehdr, sizeof x_ehdr);
/* 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)
{
free (contents);
bim->buffer = contents;
nbfd->iostream = bim;
nbfd->flags = BFD_IN_MEMORY;
+ nbfd->iovec = &_bfd_memory_iovec;
+ nbfd->origin = 0;
nbfd->direction = read_direction;
nbfd->mtime = time (NULL);
nbfd->mtime_set = TRUE;
ELFCLASS, EV_CURRENT,
elf_write_out_phdrs,
elf_write_shdrs_and_ehdr,
+ elf_checksum_contents,
elf_write_relocs,
elf_swap_symbol_in,
elf_swap_symbol_out,