#include "bfd.h"
#include "sysdep.h"
#include "libiberty.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
#define Elf_External_Ehdr NAME(Elf,External_Ehdr)
#define Elf_External_Sym NAME(Elf,External_Sym)
#define Elf_External_Shdr NAME(Elf,External_Shdr)
#define Elf_External_Phdr NAME(Elf,External_Phdr)
#define Elf_External_Rel NAME(Elf,External_Rel)
#define Elf_External_Rela NAME(Elf,External_Rela)
#define Elf_External_Dyn NAME(Elf,External_Dyn)
#define elf_core_file_failing_command NAME(bfd_elf,core_file_failing_command)
#define elf_core_file_failing_signal NAME(bfd_elf,core_file_failing_signal)
#define elf_core_file_matches_executable_p \
NAME(bfd_elf,core_file_matches_executable_p)
#define elf_object_p NAME(bfd_elf,object_p)
#define elf_core_file_p NAME(bfd_elf,core_file_p)
#define elf_get_symtab_upper_bound NAME(bfd_elf,get_symtab_upper_bound)
#define elf_get_dynamic_symtab_upper_bound \
NAME(bfd_elf,get_dynamic_symtab_upper_bound)
#define elf_swap_reloc_in NAME(bfd_elf,swap_reloc_in)
#define elf_swap_reloca_in NAME(bfd_elf,swap_reloca_in)
#define elf_swap_reloc_out NAME(bfd_elf,swap_reloc_out)
#define elf_swap_reloca_out NAME(bfd_elf,swap_reloca_out)
#define elf_swap_symbol_in NAME(bfd_elf,swap_symbol_in)
#define elf_swap_symbol_out NAME(bfd_elf,swap_symbol_out)
#define elf_swap_phdr_in NAME(bfd_elf,swap_phdr_in)
#define elf_swap_phdr_out NAME(bfd_elf,swap_phdr_out)
#define elf_swap_dyn_in NAME(bfd_elf,swap_dyn_in)
#define elf_swap_dyn_out NAME(bfd_elf,swap_dyn_out)
#define elf_get_reloc_upper_bound NAME(bfd_elf,get_reloc_upper_bound)
#define elf_canonicalize_reloc NAME(bfd_elf,canonicalize_reloc)
#define elf_slurp_symbol_table NAME(bfd_elf,slurp_symbol_table)
#define elf_canonicalize_symtab NAME(bfd_elf,canonicalize_symtab)
#define elf_canonicalize_dynamic_symtab \
NAME(bfd_elf,canonicalize_dynamic_symtab)
#define elf_get_synthetic_symtab \
NAME(bfd_elf,get_synthetic_symtab)
#define elf_make_empty_symbol NAME(bfd_elf,make_empty_symbol)
#define elf_get_symbol_info NAME(bfd_elf,get_symbol_info)
#define elf_get_lineno NAME(bfd_elf,get_lineno)
#define elf_set_arch_mach NAME(bfd_elf,set_arch_mach)
#define elf_find_nearest_line NAME(bfd_elf,find_nearest_line)
#define elf_sizeof_headers NAME(bfd_elf,sizeof_headers)
#define elf_set_section_contents NAME(bfd_elf,set_section_contents)
#define elf_no_info_to_howto NAME(bfd_elf,no_info_to_howto)
#define elf_no_info_to_howto_rel NAME(bfd_elf,no_info_to_howto_rel)
#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_write_relocs NAME(bfd_elf,write_relocs)
#define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table)
#if ARCH_SIZE == 64
#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y)
#define ELF_R_SYM(X) ELF64_R_SYM(X)
#define ELF_R_TYPE(X) ELF64_R_TYPE(X)
#define ELFCLASS ELFCLASS64
#define FILE_ALIGN 8
#define LOG_FILE_ALIGN 3
#endif
#if ARCH_SIZE == 32
#define ELF_R_INFO(X,Y) ELF32_R_INFO(X,Y)
#define ELF_R_SYM(X) ELF32_R_SYM(X)
#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
#define ELFCLASS ELFCLASS32
#define FILE_ALIGN 4
#define LOG_FILE_ALIGN 2
#endif
#ifdef DEBUG
static void elf_debug_section (int, Elf_Internal_Shdr *);
static void elf_debug_file (Elf_Internal_Ehdr *);
static char *elf_symbol_flags (flagword);
#endif
#if ARCH_SIZE == 64
#define H_PUT_WORD H_PUT_64
#define H_PUT_SIGNED_WORD H_PUT_S64
#define H_GET_WORD H_GET_64
#define H_GET_SIGNED_WORD H_GET_S64
#endif
#if ARCH_SIZE == 32
#define H_PUT_WORD H_PUT_32
#define H_PUT_SIGNED_WORD H_PUT_S32
#define H_GET_WORD H_GET_32
#define H_GET_SIGNED_WORD H_GET_S32
#endif
void
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;
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
dst->st_name = H_GET_32 (abfd, src->st_name);
if (signed_vma)
dst->st_value = H_GET_SIGNED_WORD (abfd, src->st_value);
else
dst->st_value = H_GET_WORD (abfd, src->st_value);
dst->st_size = H_GET_WORD (abfd, src->st_size);
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 (shndx == NULL)
abort ();
dst->st_shndx = H_GET_32 (abfd, shndx->est_shndx);
}
}
void
elf_swap_symbol_out (bfd *abfd,
const Elf_Internal_Sym *src,
void *cdst,
void *shndx)
{
unsigned int tmp;
Elf_External_Sym *dst = 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 (shndx == NULL)
abort ();
H_PUT_32 (abfd, tmp, shndx);
tmp = SHN_XINDEX;
}
H_PUT_16 (abfd, tmp, dst->st_shndx);
}
static void
elf_swap_ehdr_in (bfd *abfd,
const Elf_External_Ehdr *src,
Elf_Internal_Ehdr *dst)
{
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
dst->e_type = H_GET_16 (abfd, src->e_type);
dst->e_machine = H_GET_16 (abfd, src->e_machine);
dst->e_version = H_GET_32 (abfd, src->e_version);
if (signed_vma)
dst->e_entry = H_GET_SIGNED_WORD (abfd, src->e_entry);
else
dst->e_entry = H_GET_WORD (abfd, src->e_entry);
dst->e_phoff = H_GET_WORD (abfd, src->e_phoff);
dst->e_shoff = H_GET_WORD (abfd, src->e_shoff);
dst->e_flags = H_GET_32 (abfd, src->e_flags);
dst->e_ehsize = H_GET_16 (abfd, src->e_ehsize);
dst->e_phentsize = H_GET_16 (abfd, src->e_phentsize);
dst->e_phnum = H_GET_16 (abfd, src->e_phnum);
dst->e_shentsize = H_GET_16 (abfd, src->e_shentsize);
dst->e_shnum = H_GET_16 (abfd, src->e_shnum);
dst->e_shstrndx = H_GET_16 (abfd, src->e_shstrndx);
}
static void
elf_swap_ehdr_out (bfd *abfd,
const Elf_Internal_Ehdr *src,
Elf_External_Ehdr *dst)
{
unsigned int tmp;
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
H_PUT_16 (abfd, src->e_type, dst->e_type);
H_PUT_16 (abfd, src->e_machine, dst->e_machine);
H_PUT_32 (abfd, src->e_version, dst->e_version);
if (signed_vma)
H_PUT_SIGNED_WORD (abfd, src->e_entry, dst->e_entry);
else
H_PUT_WORD (abfd, src->e_entry, dst->e_entry);
H_PUT_WORD (abfd, src->e_phoff, dst->e_phoff);
H_PUT_WORD (abfd, src->e_shoff, dst->e_shoff);
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);
H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
tmp = src->e_shnum;
if (tmp >= SHN_LORESERVE)
tmp = SHN_UNDEF;
H_PUT_16 (abfd, tmp, dst->e_shnum);
tmp = src->e_shstrndx;
if (tmp >= SHN_LORESERVE)
tmp = SHN_XINDEX;
H_PUT_16 (abfd, tmp, dst->e_shstrndx);
}
static void
elf_swap_shdr_in (bfd *abfd,
const Elf_External_Shdr *src,
Elf_Internal_Shdr *dst)
{
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
dst->sh_name = H_GET_32 (abfd, src->sh_name);
dst->sh_type = H_GET_32 (abfd, src->sh_type);
dst->sh_flags = H_GET_WORD (abfd, src->sh_flags);
if (signed_vma)
dst->sh_addr = H_GET_SIGNED_WORD (abfd, src->sh_addr);
else
dst->sh_addr = H_GET_WORD (abfd, src->sh_addr);
dst->sh_offset = H_GET_WORD (abfd, src->sh_offset);
dst->sh_size = H_GET_WORD (abfd, src->sh_size);
dst->sh_link = H_GET_32 (abfd, src->sh_link);
dst->sh_info = H_GET_32 (abfd, src->sh_info);
dst->sh_addralign = H_GET_WORD (abfd, src->sh_addralign);
dst->sh_entsize = H_GET_WORD (abfd, src->sh_entsize);
dst->bfd_section = NULL;
dst->contents = NULL;
}
static void
elf_swap_shdr_out (bfd *abfd,
const Elf_Internal_Shdr *src,
Elf_External_Shdr *dst)
{
H_PUT_32 (abfd, src->sh_name, dst->sh_name);
H_PUT_32 (abfd, src->sh_type, dst->sh_type);
H_PUT_WORD (abfd, src->sh_flags, dst->sh_flags);
H_PUT_WORD (abfd, src->sh_addr, dst->sh_addr);
H_PUT_WORD (abfd, src->sh_offset, dst->sh_offset);
H_PUT_WORD (abfd, src->sh_size, dst->sh_size);
H_PUT_32 (abfd, src->sh_link, dst->sh_link);
H_PUT_32 (abfd, src->sh_info, dst->sh_info);
H_PUT_WORD (abfd, src->sh_addralign, dst->sh_addralign);
H_PUT_WORD (abfd, src->sh_entsize, dst->sh_entsize);
}
void
elf_swap_phdr_in (bfd *abfd,
const Elf_External_Phdr *src,
Elf_Internal_Phdr *dst)
{
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
dst->p_type = H_GET_32 (abfd, src->p_type);
dst->p_flags = H_GET_32 (abfd, src->p_flags);
dst->p_offset = H_GET_WORD (abfd, src->p_offset);
if (signed_vma)
{
dst->p_vaddr = H_GET_SIGNED_WORD (abfd, src->p_vaddr);
dst->p_paddr = H_GET_SIGNED_WORD (abfd, src->p_paddr);
}
else
{
dst->p_vaddr = H_GET_WORD (abfd, src->p_vaddr);
dst->p_paddr = H_GET_WORD (abfd, src->p_paddr);
}
dst->p_filesz = H_GET_WORD (abfd, src->p_filesz);
dst->p_memsz = H_GET_WORD (abfd, src->p_memsz);
dst->p_align = H_GET_WORD (abfd, src->p_align);
}
void
elf_swap_phdr_out (bfd *abfd,
const Elf_Internal_Phdr *src,
Elf_External_Phdr *dst)
{
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, 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);
H_PUT_WORD (abfd, src->p_align, dst->p_align);
}
void
elf_swap_reloc_in (bfd *abfd,
const bfd_byte *s,
Elf_Internal_Rela *dst)
{
const Elf_External_Rel *src = (const Elf_External_Rel *) s;
dst->r_offset = H_GET_WORD (abfd, src->r_offset);
dst->r_info = H_GET_WORD (abfd, src->r_info);
dst->r_addend = 0;
}
void
elf_swap_reloca_in (bfd *abfd,
const bfd_byte *s,
Elf_Internal_Rela *dst)
{
const Elf_External_Rela *src = (const Elf_External_Rela *) s;
dst->r_offset = H_GET_WORD (abfd, src->r_offset);
dst->r_info = H_GET_WORD (abfd, src->r_info);
dst->r_addend = H_GET_SIGNED_WORD (abfd, src->r_addend);
}
void
elf_swap_reloc_out (bfd *abfd,
const Elf_Internal_Rela *src,
bfd_byte *d)
{
Elf_External_Rel *dst = (Elf_External_Rel *) d;
H_PUT_WORD (abfd, src->r_offset, dst->r_offset);
H_PUT_WORD (abfd, src->r_info, dst->r_info);
}
void
elf_swap_reloca_out (bfd *abfd,
const Elf_Internal_Rela *src,
bfd_byte *d)
{
Elf_External_Rela *dst = (Elf_External_Rela *) d;
H_PUT_WORD (abfd, src->r_offset, dst->r_offset);
H_PUT_WORD (abfd, src->r_info, dst->r_info);
H_PUT_SIGNED_WORD (abfd, src->r_addend, dst->r_addend);
}
void
elf_swap_dyn_in (bfd *abfd,
const void *p,
Elf_Internal_Dyn *dst)
{
const Elf_External_Dyn *src = 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);
}
void
elf_swap_dyn_out (bfd *abfd,
const Elf_Internal_Dyn *src,
void *p)
{
Elf_External_Dyn *dst = 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);
}
static inline bfd_boolean
elf_file_p (Elf_External_Ehdr *x_ehdrp)
{
return ((x_ehdrp->e_ident[EI_MAG0] == ELFMAG0)
&& (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1)
&& (x_ehdrp->e_ident[EI_MAG2] == ELFMAG2)
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
}
const bfd_target *
elf_object_p (bfd *abfd)
{
Elf_External_Ehdr x_ehdr;
Elf_Internal_Ehdr *i_ehdrp;
Elf_External_Shdr x_shdr;
Elf_Internal_Shdr i_shdr;
Elf_Internal_Shdr *i_shdrp;
unsigned int shindex;
const struct elf_backend_data *ebd;
struct bfd_preserve preserve;
asection *s;
bfd_size_type amt;
preserve.marker = NULL;
if (bfd_bread (&x_ehdr, sizeof (x_ehdr), abfd) != sizeof (x_ehdr))
{
if (bfd_get_error () != bfd_error_system_call)
goto got_wrong_format_error;
else
goto got_no_match;
}
if (! elf_file_p (&x_ehdr)
|| x_ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| x_ehdr.e_ident[EI_CLASS] != ELFCLASS)
goto got_wrong_format_error;
switch (x_ehdr.e_ident[EI_DATA])
{
case ELFDATA2MSB:
if (! bfd_header_big_endian (abfd))
goto got_wrong_format_error;
break;
case ELFDATA2LSB:
if (! bfd_header_little_endian (abfd))
goto got_wrong_format_error;
break;
case ELFDATANONE:
default:
goto got_wrong_format_error;
}
if (!bfd_preserve_save (abfd, &preserve))
goto got_no_match;
if (! (*abfd->xvec->_bfd_set_format[bfd_object]) (abfd))
goto got_no_match;
preserve.marker = elf_tdata (abfd);
i_ehdrp = elf_elfheader (abfd);
elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
#if DEBUG & 1
elf_debug_file (i_ehdrp);
#endif
if (i_ehdrp->e_type == ET_CORE)
goto got_wrong_format_error;
if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_type == ET_REL)
goto got_wrong_format_error;
if (i_ehdrp->e_shentsize != sizeof (x_shdr) && i_ehdrp->e_shnum != 0)
goto got_wrong_format_error;
if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0)
goto got_wrong_format_error;
ebd = get_elf_backend_data (abfd);
if (ebd->elf_machine_code != i_ehdrp->e_machine
&& (ebd->elf_machine_alt1 == 0
|| i_ehdrp->e_machine != ebd->elf_machine_alt1)
&& (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;
for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
{
const struct elf_backend_data *back;
if ((*target_ptr)->flavour != bfd_target_elf_flavour)
continue;
back = (const struct elf_backend_data *) (*target_ptr)->backend_data;
if (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))
{
goto got_wrong_format_error;
}
}
}
if (i_ehdrp->e_type == ET_EXEC)
abfd->flags |= EXEC_P;
else if (i_ehdrp->e_type == ET_DYN)
abfd->flags |= DYNAMIC;
if (i_ehdrp->e_phnum > 0)
abfd->flags |= D_PAGED;
if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0))
{
if (ebd->elf_machine_code != EM_NONE)
goto got_no_match;
}
bfd_set_start_address (abfd, i_ehdrp->e_entry);
if (i_ehdrp->e_shoff != 0)
{
bfd_signed_vma where = i_ehdrp->e_shoff;
if (where != (file_ptr) where)
goto got_wrong_format_error;
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
goto got_no_match;
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
goto got_no_match;
elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
if (i_ehdrp->e_shnum == SHN_UNDEF)
{
i_ehdrp->e_shnum = i_shdr.sh_size;
if (i_ehdrp->e_shnum != i_shdr.sh_size
|| i_ehdrp->e_shnum == 0)
goto got_wrong_format_error;
}
if (i_ehdrp->e_shstrndx == SHN_XINDEX)
{
i_ehdrp->e_shstrndx = i_shdr.sh_link;
if (i_ehdrp->e_shstrndx != i_shdr.sh_link)
goto got_wrong_format_error;
}
if (i_ehdrp->e_shnum != 1)
{
if (i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (x_shdr)
|| i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (i_shdr))
goto got_wrong_format_error;
where += (i_ehdrp->e_shnum - 1) * sizeof (x_shdr);
if (where != (file_ptr) where)
goto got_wrong_format_error;
if ((bfd_size_type) where <= i_ehdrp->e_shoff)
goto got_wrong_format_error;
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
goto got_no_match;
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
goto got_no_match;
where = i_ehdrp->e_shoff + sizeof (x_shdr);
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
goto got_no_match;
}
}
if (i_ehdrp->e_shnum != 0)
{
Elf_Internal_Shdr *shdrp;
unsigned int num_sec;
amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum;
i_shdrp = 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);
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++)
elf_elfsections (abfd)[shindex] = shdrp++;
for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
{
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
goto got_no_match;
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
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_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)))
goto got_wrong_format_error;
if (i_shdrp[shindex].sh_size != 0
&& (i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0
&& i_shdrp[shindex].sh_type != SHT_NOBITS
&& (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset)
% ebd->minpagesize)
!= 0))
abfd->flags &= ~D_PAGED;
}
}
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;
}
else if (i_ehdrp->e_shstrndx != 0)
goto got_wrong_format_error;
if (i_ehdrp->e_phnum == 0)
elf_tdata (abfd)->phdr = NULL;
else
{
Elf_Internal_Phdr *i_phdr;
unsigned int i;
amt = i_ehdrp->e_phnum * sizeof (Elf_Internal_Phdr);
elf_tdata (abfd)->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)
goto got_no_match;
i_phdr = elf_tdata (abfd)->phdr;
for (i = 0; i < i_ehdrp->e_phnum; i++, i_phdr++)
{
Elf_External_Phdr x_phdr;
if (bfd_bread (&x_phdr, sizeof x_phdr, abfd) != sizeof x_phdr)
goto got_no_match;
elf_swap_phdr_in (abfd, &x_phdr, i_phdr);
}
}
if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff != 0)
{
unsigned int num_sec;
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_elf_setup_group_pointers (abfd))
goto got_wrong_format_error;
}
if (ebd->elf_backend_object_p)
{
if (! (*ebd->elf_backend_object_p) (abfd))
goto got_wrong_format_error;
}
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((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_info > 0)
{
unsigned long targ_index;
asection *targ_sec;
targ_index = elf_section_data (s)->this_hdr.sh_info;
targ_sec = bfd_section_from_elf_index (abfd, targ_index);
if (targ_sec != NULL
&& (targ_sec->flags & SEC_DEBUGGING) != 0)
s->flags |= SEC_DEBUGGING;
}
}
bfd_preserve_finish (abfd, &preserve);
return abfd->xvec;
got_wrong_format_error:
bfd_set_error (bfd_error_wrong_format);
got_no_match:
if (preserve.marker != NULL)
bfd_preserve_restore (abfd, &preserve);
return NULL;
}
void
elf_write_relocs (bfd *abfd, asection *sec, void *data)
{
bfd_boolean *failedp = data;
Elf_Internal_Shdr *rela_hdr;
bfd_vma addr_offset;
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
size_t extsize;
bfd_byte *dst_rela;
unsigned int idx;
asymbol *last_sym;
int last_sym_idx;
if (*failedp)
return;
if ((sec->flags & SEC_RELOC) == 0)
return;
if (sec->reloc_count == 0)
return;
if (sec->orelocation == NULL)
return;
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);
if (rela_hdr->contents == NULL)
{
*failedp = TRUE;
return;
}
if (rela_hdr->sh_type == SHT_RELA)
{
swap_out = elf_swap_reloca_out;
extsize = sizeof (Elf_External_Rela);
}
else if (rela_hdr->sh_type == SHT_REL)
{
swap_out = elf_swap_reloc_out;
extsize = sizeof (Elf_External_Rel);
}
else
abort ();
addr_offset = 0;
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
addr_offset = sec->vma;
last_sym = 0;
last_sym_idx = 0;
dst_rela = rela_hdr->contents;
for (idx = 0; idx < sec->reloc_count; idx++, dst_rela += extsize)
{
Elf_Internal_Rela src_rela;
arelent *ptr;
asymbol *sym;
int n;
ptr = sec->orelocation[idx];
sym = *ptr->sym_ptr_ptr;
if (sym == last_sym)
n = last_sym_idx;
else if (bfd_is_abs_section (sym->section) && sym->value == 0)
n = STN_UNDEF;
else
{
last_sym = sym;
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
if (n < 0)
{
*failedp = TRUE;
return;
}
last_sym_idx = n;
}
if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
&& ! _bfd_elf_validate_reloc (abfd, ptr))
{
*failedp = TRUE;
return;
}
src_rela.r_offset = ptr->address + addr_offset;
src_rela.r_info = ELF_R_INFO (n, ptr->howto->type);
src_rela.r_addend = ptr->addend;
(*swap_out) (abfd, &src_rela, dst_rela);
}
}
int
elf_write_out_phdrs (bfd *abfd,
const Elf_Internal_Phdr *phdr,
unsigned int count)
{
while (count--)
{
Elf_External_Phdr extphdr;
elf_swap_phdr_out (abfd, phdr, &extphdr);
if (bfd_bwrite (&extphdr, sizeof (Elf_External_Phdr), abfd)
!= sizeof (Elf_External_Phdr))
return -1;
phdr++;
}
return 0;
}
bfd_boolean
elf_write_shdrs_and_ehdr (bfd *abfd)
{
Elf_External_Ehdr x_ehdr;
Elf_Internal_Ehdr *i_ehdrp;
Elf_External_Shdr *x_shdrp;
Elf_Internal_Shdr **i_shdrp;
unsigned int count;
bfd_size_type amt;
i_ehdrp = elf_elfheader (abfd);
i_shdrp = elf_elfsections (abfd);
#if DEBUG & 1
elf_debug_file (i_ehdrp);
#endif
elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr);
amt = sizeof (x_ehdr);
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
|| bfd_bwrite (&x_ehdr, amt, abfd) != amt)
return FALSE;
if (i_ehdrp->e_shnum >= SHN_LORESERVE)
i_shdrp[0]->sh_size = i_ehdrp->e_shnum;
if (i_ehdrp->e_shstrndx >= SHN_LORESERVE)
i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
amt = i_ehdrp->e_shnum;
amt *= sizeof (*x_shdrp);
x_shdrp = bfd_alloc (abfd, amt);
if (!x_shdrp)
return FALSE;
for (count = 0; count < i_ehdrp->e_shnum; i_shdrp++, count++)
{
#if DEBUG & 2
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 FALSE;
return TRUE;
}
long
elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
{
Elf_Internal_Shdr *hdr;
Elf_Internal_Shdr *verhdr;
unsigned long symcount;
elf_symbol_type *sym;
elf_symbol_type *symbase;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
Elf_Internal_Sym *isymbuf = NULL;
Elf_External_Versym *xver;
Elf_External_Versym *xverbuf = NULL;
const struct elf_backend_data *ebd;
bfd_size_type amt;
if (! dynamic)
{
hdr = &elf_tdata (abfd)->symtab_hdr;
verhdr = NULL;
}
else
{
hdr = &elf_tdata (abfd)->dynsymtab_hdr;
if (elf_dynversym (abfd) == 0)
verhdr = NULL;
else
verhdr = &elf_tdata (abfd)->dynversym_hdr;
if ((elf_tdata (abfd)->dynverdef_section != 0
&& elf_tdata (abfd)->verdef == NULL)
|| (elf_tdata (abfd)->dynverref_section != 0
&& elf_tdata (abfd)->verref == NULL))
{
if (!_bfd_elf_slurp_version_tables (abfd, FALSE))
return -1;
}
}
ebd = get_elf_backend_data (abfd);
symcount = hdr->sh_size / sizeof (Elf_External_Sym);
if (symcount == 0)
sym = symbase = NULL;
else
{
isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0,
NULL, NULL, NULL);
if (isymbuf == NULL)
return -1;
amt = symcount;
amt *= sizeof (elf_symbol_type);
symbase = bfd_zalloc (abfd, amt);
if (symbase == (elf_symbol_type *) NULL)
goto error_return;
if (verhdr != NULL
&& verhdr->sh_size / sizeof (Elf_External_Versym) != symcount)
{
(*_bfd_error_handler)
(_("%s: version count (%ld) does not match symbol count (%ld)"),
abfd->filename,
(long) (verhdr->sh_size / sizeof (Elf_External_Versym)),
symcount);
verhdr = NULL;
}
if (verhdr != NULL)
{
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
goto error_return;
xverbuf = bfd_malloc (verhdr->sh_size);
if (xverbuf == NULL && verhdr->sh_size != 0)
goto error_return;
if (bfd_bread (xverbuf, verhdr->sh_size, abfd) != verhdr->sh_size)
goto error_return;
}
xver = xverbuf;
if (xver != NULL)
++xver;
isymend = isymbuf + symcount;
for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++)
{
memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym));
sym->symbol.the_bfd = abfd;
sym->symbol.name = bfd_elf_sym_name (abfd, hdr, isym, NULL);
sym->symbol.value = isym->st_value;
if (isym->st_shndx == SHN_UNDEF)
{
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)
{
sym->symbol.section = bfd_abs_section_ptr;
}
}
else if (isym->st_shndx == SHN_ABS)
{
sym->symbol.section = bfd_abs_section_ptr;
}
else if (isym->st_shndx == SHN_COMMON)
{
sym->symbol.section = bfd_com_section_ptr;
sym->symbol.value = isym->st_size;
}
else
sym->symbol.section = bfd_abs_section_ptr;
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
sym->symbol.value -= sym->symbol.section->vma;
switch (ELF_ST_BIND (isym->st_info))
{
case STB_LOCAL:
sym->symbol.flags |= BSF_LOCAL;
break;
case STB_GLOBAL:
if (isym->st_shndx != SHN_UNDEF && isym->st_shndx != SHN_COMMON)
sym->symbol.flags |= BSF_GLOBAL;
break;
case STB_WEAK:
sym->symbol.flags |= BSF_WEAK;
break;
}
switch (ELF_ST_TYPE (isym->st_info))
{
case STT_SECTION:
sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING;
break;
case STT_FILE:
sym->symbol.flags |= BSF_FILE | BSF_DEBUGGING;
break;
case STT_FUNC:
sym->symbol.flags |= BSF_FUNCTION;
break;
case STT_OBJECT:
sym->symbol.flags |= BSF_OBJECT;
break;
case STT_TLS:
sym->symbol.flags |= BSF_THREAD_LOCAL;
break;
}
if (dynamic)
sym->symbol.flags |= BSF_DYNAMIC;
if (xver != NULL)
{
Elf_Internal_Versym iversym;
_bfd_elf_swap_versym_in (abfd, xver, &iversym);
sym->version = iversym.vs_vers;
xver++;
}
if (ebd->elf_backend_symbol_processing)
(*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
}
}
if (ebd->elf_backend_symbol_table_processing)
(*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
symcount = sym - symbase;
if (symptrs)
{
long l = symcount;
sym = symbase;
while (l-- > 0)
{
*symptrs++ = &sym->symbol;
sym++;
}
*symptrs = 0;
}
if (xverbuf != NULL)
free (xverbuf);
if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf)
free (isymbuf);
return symcount;
error_return:
if (xverbuf != NULL)
free (xverbuf);
if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf)
free (isymbuf);
return -1;
}
static bfd_boolean
elf_slurp_reloc_table_from_section (bfd *abfd,
asection *asect,
Elf_Internal_Shdr *rel_hdr,
bfd_size_type reloc_count,
arelent *relents,
asymbol **symbols,
bfd_boolean dynamic)
{
const struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
void *allocated = NULL;
bfd_byte *native_relocs;
arelent *relent;
unsigned int i;
int entsize;
unsigned int symcount;
allocated = bfd_malloc (rel_hdr->sh_size);
if (allocated == NULL)
goto error_return;
if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
|| (bfd_bread (allocated, rel_hdr->sh_size, abfd)
!= rel_hdr->sh_size))
goto error_return;
native_relocs = allocated;
entsize = rel_hdr->sh_entsize;
BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
|| entsize == sizeof (Elf_External_Rela));
if (dynamic)
symcount = bfd_get_dynamic_symcount (abfd);
else
symcount = bfd_get_symcount (abfd);
for (i = 0, relent = relents;
i < reloc_count;
i++, relent++, native_relocs += entsize)
{
Elf_Internal_Rela rela;
if (entsize == sizeof (Elf_External_Rela))
elf_swap_reloca_in (abfd, native_relocs, &rela);
else
elf_swap_reloc_in (abfd, native_relocs, &rela);
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
relent->address = rela.r_offset;
else
relent->address = rela.r_offset - asect->vma;
if (ELF_R_SYM (rela.r_info) == 0)
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
else if (ELF_R_SYM (rela.r_info) > symcount)
{
(*_bfd_error_handler)
(_("%s(%s): relocation %d has invalid symbol index %ld"),
abfd->filename, asect->name, i, ELF_R_SYM (rela.r_info));
relent->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
}
else
{
asymbol **ps, *s;
ps = symbols + ELF_R_SYM (rela.r_info) - 1;
s = *ps;
relent->sym_ptr_ptr = ps;
}
relent->addend = rela.r_addend;
if ((entsize == sizeof (Elf_External_Rela)
&& ebd->elf_info_to_howto != NULL)
|| ebd->elf_info_to_howto_rel == NULL)
(*ebd->elf_info_to_howto) (abfd, relent, &rela);
else
(*ebd->elf_info_to_howto_rel) (abfd, relent, &rela);
}
if (allocated != NULL)
free (allocated);
return TRUE;
error_return:
if (allocated != NULL)
free (allocated);
return FALSE;
}
bfd_boolean
elf_slurp_reloc_table (bfd *abfd,
asection *asect,
asymbol **symbols,
bfd_boolean dynamic)
{
struct bfd_elf_section_data * const d = elf_section_data (asect);
Elf_Internal_Shdr *rel_hdr;
Elf_Internal_Shdr *rel_hdr2;
bfd_size_type reloc_count;
bfd_size_type reloc_count2;
arelent *relents;
bfd_size_type amt;
if (asect->relocation != NULL)
return TRUE;
if (! dynamic)
{
if ((asect->flags & SEC_RELOC) == 0
|| asect->reloc_count == 0)
return TRUE;
rel_hdr = &d->rel_hdr;
reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
rel_hdr2 = d->rel_hdr2;
reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0);
BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
|| (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
}
else
{
if (asect->size == 0)
return TRUE;
rel_hdr = &d->this_hdr;
reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
rel_hdr2 = NULL;
reloc_count2 = 0;
}
amt = (reloc_count + reloc_count2) * sizeof (arelent);
relents = bfd_alloc (abfd, amt);
if (relents == NULL)
return FALSE;
if (!elf_slurp_reloc_table_from_section (abfd, asect,
rel_hdr, reloc_count,
relents,
symbols, dynamic))
return FALSE;
if (rel_hdr2
&& !elf_slurp_reloc_table_from_section (abfd, asect,
rel_hdr2, reloc_count2,
relents + reloc_count,
symbols, dynamic))
return FALSE;
asect->relocation = relents;
return TRUE;
}
#ifdef DEBUG
static void
elf_debug_section (int num, Elf_Internal_Shdr *hdr)
{
fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num,
hdr->bfd_section != NULL ? hdr->bfd_section->name : "",
(long) hdr);
fprintf (stderr,
"sh_name = %ld\tsh_type = %ld\tsh_flags = %ld\n",
(long) hdr->sh_name,
(long) hdr->sh_type,
(long) hdr->sh_flags);
fprintf (stderr,
"sh_addr = %ld\tsh_offset = %ld\tsh_size = %ld\n",
(long) hdr->sh_addr,
(long) hdr->sh_offset,
(long) hdr->sh_size);
fprintf (stderr,
"sh_link = %ld\tsh_info = %ld\tsh_addralign = %ld\n",
(long) hdr->sh_link,
(long) hdr->sh_info,
(long) hdr->sh_addralign);
fprintf (stderr, "sh_entsize = %ld\n",
(long) hdr->sh_entsize);
fflush (stderr);
}
static void
elf_debug_file (Elf_Internal_Ehdr *ehdrp)
{
fprintf (stderr, "e_entry = 0x%.8lx\n", (long) ehdrp->e_entry);
fprintf (stderr, "e_phoff = %ld\n", (long) ehdrp->e_phoff);
fprintf (stderr, "e_phnum = %ld\n", (long) ehdrp->e_phnum);
fprintf (stderr, "e_phentsize = %ld\n", (long) ehdrp->e_phentsize);
fprintf (stderr, "e_shoff = %ld\n", (long) ehdrp->e_shoff);
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
bfd *
NAME(_bfd_elf,bfd_from_remote_memory)
(bfd *templ,
bfd_vma ehdr_vma,
bfd_vma *loadbasep,
int (*target_read_memory) (bfd_vma, bfd_byte *, int))
{
Elf_External_Ehdr x_ehdr;
Elf_Internal_Ehdr i_ehdr;
Elf_External_Phdr *x_phdrs;
Elf_Internal_Phdr *i_phdrs, *last_phdr;
bfd *nbfd;
struct bfd_in_memory *bim;
int contents_size;
bfd_byte *contents;
int err;
unsigned int i;
bfd_vma loadbase;
err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr);
if (err)
{
bfd_set_error (bfd_error_system_call);
errno = err;
return NULL;
}
if (! elf_file_p (&x_ehdr)
|| x_ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| x_ehdr.e_ident[EI_CLASS] != ELFCLASS)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
switch (x_ehdr.e_ident[EI_DATA])
{
case ELFDATA2MSB:
if (! bfd_header_big_endian (templ))
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
break;
case ELFDATA2LSB:
if (! bfd_header_little_endian (templ))
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
break;
case ELFDATANONE:
default:
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
elf_swap_ehdr_in (templ, &x_ehdr, &i_ehdr);
if (i_ehdr.e_phentsize != sizeof (Elf_External_Phdr) || i_ehdr.e_phnum == 0)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
x_phdrs = bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
if (x_phdrs == NULL)
{
bfd_set_error (bfd_error_no_memory);
return NULL;
}
err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs,
i_ehdr.e_phnum * sizeof x_phdrs[0]);
if (err)
{
free (x_phdrs);
bfd_set_error (bfd_error_system_call);
errno = err;
return NULL;
}
i_phdrs = (Elf_Internal_Phdr *) &x_phdrs[i_ehdr.e_phnum];
contents_size = 0;
last_phdr = NULL;
loadbase = ehdr_vma;
for (i = 0; i < i_ehdr.e_phnum; ++i)
{
elf_swap_phdr_in (templ, &x_phdrs[i], &i_phdrs[i]);
if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
{
bfd_vma segment_end;
segment_end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
+ i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align;
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);
last_phdr = &i_phdrs[i];
}
}
if (last_phdr == NULL)
{
free (x_phdrs);
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if ((bfd_vma) contents_size > last_phdr->p_offset + last_phdr->p_filesz
&& (bfd_vma) contents_size >= (i_ehdr.e_shoff
+ i_ehdr.e_shnum * i_ehdr.e_shentsize))
{
contents_size = last_phdr->p_offset + last_phdr->p_filesz;
if ((bfd_vma) contents_size < (i_ehdr.e_shoff
+ i_ehdr.e_shnum * i_ehdr.e_shentsize))
contents_size = i_ehdr.e_shoff + i_ehdr.e_shnum * i_ehdr.e_shentsize;
}
else
contents_size = last_phdr->p_offset + last_phdr->p_filesz;
contents = bfd_zmalloc (contents_size);
if (contents == NULL)
{
free (x_phdrs);
bfd_set_error (bfd_error_no_memory);
return NULL;
}
for (i = 0; i < i_ehdr.e_phnum; ++i)
if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
{
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
+ i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align;
if (end > (bfd_vma) contents_size)
end = contents_size;
err = target_read_memory ((loadbase + i_phdrs[i].p_vaddr)
& -i_phdrs[i].p_align,
contents + start, end - start);
if (err)
{
free (x_phdrs);
free (contents);
bfd_set_error (bfd_error_system_call);
errno = err;
return NULL;
}
}
free (x_phdrs);
if ((bfd_vma) contents_size < (i_ehdr.e_shoff
+ i_ehdr.e_shnum * i_ehdr.e_shentsize))
{
memset (&x_ehdr.e_shoff, 0, sizeof x_ehdr.e_shoff);
memset (&x_ehdr.e_shnum, 0, sizeof x_ehdr.e_shnum);
memset (&x_ehdr.e_shstrndx, 0, sizeof x_ehdr.e_shstrndx);
}
memcpy (contents, &x_ehdr, sizeof x_ehdr);
bim = bfd_malloc (sizeof (struct bfd_in_memory));
if (bim == NULL)
{
free (contents);
bfd_set_error (bfd_error_no_memory);
return NULL;
}
nbfd = _bfd_new_bfd ();
if (nbfd == NULL)
{
free (bim);
free (contents);
bfd_set_error (bfd_error_no_memory);
return NULL;
}
nbfd->filename = "<in-memory>";
nbfd->xvec = templ->xvec;
bim->size = contents_size;
bim->buffer = contents;
nbfd->iostream = bim;
nbfd->flags = BFD_IN_MEMORY;
nbfd->direction = read_direction;
nbfd->mtime = time (NULL);
nbfd->mtime_set = TRUE;
if (loadbasep)
*loadbasep = loadbase;
return nbfd;
}
#include "elfcore.h"
const struct elf_size_info NAME(_bfd_elf,size_info) = {
sizeof (Elf_External_Ehdr),
sizeof (Elf_External_Phdr),
sizeof (Elf_External_Shdr),
sizeof (Elf_External_Rel),
sizeof (Elf_External_Rela),
sizeof (Elf_External_Sym),
sizeof (Elf_External_Dyn),
sizeof (Elf_External_Note),
4,
1,
ARCH_SIZE, LOG_FILE_ALIGN,
ELFCLASS, EV_CURRENT,
elf_write_out_phdrs,
elf_write_shdrs_and_ehdr,
elf_write_relocs,
elf_swap_symbol_in,
elf_swap_symbol_out,
elf_slurp_reloc_table,
elf_slurp_symbol_table,
elf_swap_dyn_in,
elf_swap_dyn_out,
elf_swap_reloc_in,
elf_swap_reloc_out,
elf_swap_reloca_in,
elf_swap_reloca_out
};