X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felfcode.h;h=7ab97bfce96e8444674ac0b7c511fb94f830e288;hb=a3f5b945e4f0b4d88255cefd84b9b3181bf47d84;hp=d9f3e059dcb01238c6c5fa1e3ae3916a76b8ae95;hpb=d9bc7a4499c25b26971d80e2392a6da6e84cbe21;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfcode.h b/bfd/elfcode.h index d9f3e059dc..7ab97bfce9 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1,6 +1,6 @@ /* ELF executable support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and @@ -102,9 +102,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #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_get_symtab NAME(bfd_elf,get_symtab) +#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) @@ -115,26 +117,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #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_bfd_link_add_symbols NAME(bfd_elf,bfd_link_add_symbols) -#define elf_add_dynamic_entry NAME(bfd_elf,add_dynamic_entry) #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) -#define elf_link_create_dynamic_sections \ - NAME(bfd_elf,link_create_dynamic_sections) -#define elf_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol -#define elf_bfd_final_link NAME(bfd_elf,bfd_final_link) -#define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section) -#define elf_finish_pointer_linker_section NAME(bfd_elf,finish_pointer_linker_section) -#define elf_gc_sections NAME(_bfd_elf,gc_sections) -#define elf_gc_common_finalize_got_offsets \ - NAME(_bfd_elf,gc_common_finalize_got_offsets) -#define elf_gc_common_final_link NAME(_bfd_elf,gc_common_final_link) -#define elf_gc_record_vtinherit NAME(_bfd_elf,gc_record_vtinherit) -#define elf_gc_record_vtentry NAME(_bfd_elf,gc_record_vtentry) -#define elf_link_record_local_dynamic_symbol \ - NAME(_bfd_elf,link_record_local_dynamic_symbol) #if ARCH_SIZE == 64 #define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y) @@ -153,31 +139,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define LOG_FILE_ALIGN 2 #endif -/* Static functions */ - -static void elf_swap_ehdr_in - PARAMS ((bfd *, const Elf_External_Ehdr *, Elf_Internal_Ehdr *)); -static void elf_swap_ehdr_out - PARAMS ((bfd *, const Elf_Internal_Ehdr *, Elf_External_Ehdr *)); -static void elf_swap_shdr_in - PARAMS ((bfd *, const Elf_External_Shdr *, Elf_Internal_Shdr *)); -static void elf_swap_shdr_out - PARAMS ((bfd *, const Elf_Internal_Shdr *, Elf_External_Shdr *)); - -#define elf_stringtab_init _bfd_elf_stringtab_init - -#define section_from_elf_index bfd_section_from_elf_index - -static boolean elf_slurp_reloc_table_from_section - PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, - arelent *, asymbol **, boolean)); - -static boolean elf_file_p PARAMS ((Elf_External_Ehdr *)); - #ifdef DEBUG -static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *)); -static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *)); -static char *elf_symbol_flags PARAMS ((flagword)); +static void elf_debug_section (int, Elf_Internal_Shdr *); +static void elf_debug_file (Elf_Internal_Ehdr *); +static char *elf_symbol_flags (flagword); #endif /* Structure swapping routines */ @@ -185,141 +150,162 @@ static char *elf_symbol_flags PARAMS ((flagword)); /* Should perhaps use put_offset, put_word, etc. For now, the two versions can be handled by explicitly specifying 32 bits or "the long type". */ #if ARCH_SIZE == 64 -#define put_word bfd_h_put_64 -#define put_signed_word bfd_h_put_signed_64 -#define get_word bfd_h_get_64 -#define get_signed_word bfd_h_get_signed_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 put_word bfd_h_put_32 -#define put_signed_word bfd_h_put_signed_32 -#define get_word bfd_h_get_32 -#define get_signed_word bfd_h_get_signed_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 /* Translate an ELF symbol in external format into an ELF symbol in internal format. */ void -elf_swap_symbol_in (abfd, src, dst) - bfd *abfd; - const Elf_External_Sym *src; - Elf_Internal_Sym *dst; +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 = bfd_h_get_32 (abfd, (bfd_byte *) src->st_name); + dst->st_name = H_GET_32 (abfd, src->st_name); if (signed_vma) - dst->st_value = get_signed_word (abfd, (bfd_byte *) src->st_value); + dst->st_value = H_GET_SIGNED_WORD (abfd, src->st_value); else - dst->st_value = get_word (abfd, (bfd_byte *) src->st_value); - dst->st_size = get_word (abfd, (bfd_byte *) src->st_size); - dst->st_info = bfd_h_get_8 (abfd, (bfd_byte *) src->st_info); - dst->st_other = bfd_h_get_8 (abfd, (bfd_byte *) src->st_other); - dst->st_shndx = bfd_h_get_16 (abfd, (bfd_byte *) src->st_shndx); + 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); + } } /* Translate an ELF symbol in internal format into an ELF symbol in external format. */ void -elf_swap_symbol_out (abfd, src, cdst) - bfd *abfd; - const Elf_Internal_Sym *src; - PTR cdst; +elf_swap_symbol_out (bfd *abfd, + const Elf_Internal_Sym *src, + void *cdst, + void *shndx) { - Elf_External_Sym *dst = (Elf_External_Sym *) cdst; - bfd_h_put_32 (abfd, src->st_name, dst->st_name); - put_word (abfd, src->st_value, dst->st_value); - put_word (abfd, src->st_size, dst->st_size); - bfd_h_put_8 (abfd, src->st_info, dst->st_info); - bfd_h_put_8 (abfd, src->st_other, dst->st_other); - bfd_h_put_16 (abfd, src->st_shndx, dst->st_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); } /* Translate an ELF file header in external format into an ELF file header in internal format. */ static void -elf_swap_ehdr_in (abfd, src, dst) - bfd *abfd; - const Elf_External_Ehdr *src; - Elf_Internal_Ehdr *dst; +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 = bfd_h_get_16 (abfd, (bfd_byte *) src->e_type); - dst->e_machine = bfd_h_get_16 (abfd, (bfd_byte *) src->e_machine); - dst->e_version = bfd_h_get_32 (abfd, (bfd_byte *) src->e_version); + 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 = get_signed_word (abfd, (bfd_byte *) src->e_entry); + dst->e_entry = H_GET_SIGNED_WORD (abfd, src->e_entry); else - dst->e_entry = get_word (abfd, (bfd_byte *) src->e_entry); - dst->e_phoff = get_word (abfd, (bfd_byte *) src->e_phoff); - dst->e_shoff = get_word (abfd, (bfd_byte *) src->e_shoff); - dst->e_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->e_flags); - dst->e_ehsize = bfd_h_get_16 (abfd, (bfd_byte *) src->e_ehsize); - dst->e_phentsize = bfd_h_get_16 (abfd, (bfd_byte *) src->e_phentsize); - dst->e_phnum = bfd_h_get_16 (abfd, (bfd_byte *) src->e_phnum); - dst->e_shentsize = bfd_h_get_16 (abfd, (bfd_byte *) src->e_shentsize); - dst->e_shnum = bfd_h_get_16 (abfd, (bfd_byte *) src->e_shnum); - dst->e_shstrndx = bfd_h_get_16 (abfd, (bfd_byte *) src->e_shstrndx); + 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); } /* Translate an ELF file header in internal format into an ELF file header in external format. */ static void -elf_swap_ehdr_out (abfd, src, dst) - bfd *abfd; - const Elf_Internal_Ehdr *src; - Elf_External_Ehdr *dst; +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); /* note that all elements of dst are *arrays of unsigned char* already... */ - bfd_h_put_16 (abfd, src->e_type, dst->e_type); - bfd_h_put_16 (abfd, src->e_machine, dst->e_machine); - bfd_h_put_32 (abfd, src->e_version, dst->e_version); + 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) - put_signed_word (abfd, src->e_entry, dst->e_entry); + H_PUT_SIGNED_WORD (abfd, src->e_entry, dst->e_entry); else - put_word (abfd, src->e_entry, dst->e_entry); - put_word (abfd, src->e_phoff, dst->e_phoff); - put_word (abfd, src->e_shoff, dst->e_shoff); - bfd_h_put_32 (abfd, src->e_flags, dst->e_flags); - bfd_h_put_16 (abfd, src->e_ehsize, dst->e_ehsize); - bfd_h_put_16 (abfd, src->e_phentsize, dst->e_phentsize); - bfd_h_put_16 (abfd, src->e_phnum, dst->e_phnum); - bfd_h_put_16 (abfd, src->e_shentsize, dst->e_shentsize); - bfd_h_put_16 (abfd, src->e_shnum, dst->e_shnum); - bfd_h_put_16 (abfd, src->e_shstrndx, dst->e_shstrndx); + 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); } /* Translate an ELF section header table entry in external format into an ELF section header table entry in internal format. */ static void -elf_swap_shdr_in (abfd, src, dst) - bfd *abfd; - const Elf_External_Shdr *src; - Elf_Internal_Shdr *dst; +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 = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_name); - dst->sh_type = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_type); - dst->sh_flags = get_word (abfd, (bfd_byte *) src->sh_flags); + 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 = get_signed_word (abfd, (bfd_byte *) src->sh_addr); + dst->sh_addr = H_GET_SIGNED_WORD (abfd, src->sh_addr); else - dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr); - dst->sh_offset = get_word (abfd, (bfd_byte *) src->sh_offset); - dst->sh_size = get_word (abfd, (bfd_byte *) src->sh_size); - dst->sh_link = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_link); - dst->sh_info = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_info); - dst->sh_addralign = get_word (abfd, (bfd_byte *) src->sh_addralign); - dst->sh_entsize = get_word (abfd, (bfd_byte *) src->sh_entsize); + 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; } @@ -328,136 +314,132 @@ elf_swap_shdr_in (abfd, src, dst) ELF section header table entry in external format. */ static void -elf_swap_shdr_out (abfd, src, dst) - bfd *abfd; - const Elf_Internal_Shdr *src; - Elf_External_Shdr *dst; +elf_swap_shdr_out (bfd *abfd, + const Elf_Internal_Shdr *src, + Elf_External_Shdr *dst) { /* note that all elements of dst are *arrays of unsigned char* already... */ - bfd_h_put_32 (abfd, src->sh_name, dst->sh_name); - bfd_h_put_32 (abfd, src->sh_type, dst->sh_type); - put_word (abfd, src->sh_flags, dst->sh_flags); - put_word (abfd, src->sh_addr, dst->sh_addr); - put_word (abfd, src->sh_offset, dst->sh_offset); - put_word (abfd, src->sh_size, dst->sh_size); - bfd_h_put_32 (abfd, src->sh_link, dst->sh_link); - bfd_h_put_32 (abfd, src->sh_info, dst->sh_info); - put_word (abfd, src->sh_addralign, dst->sh_addralign); - put_word (abfd, src->sh_entsize, dst->sh_entsize); + 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); } /* Translate an ELF program header table entry in external format into an ELF program header table entry in internal format. */ void -elf_swap_phdr_in (abfd, src, dst) - bfd *abfd; - const Elf_External_Phdr *src; - Elf_Internal_Phdr *dst; +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 = bfd_h_get_32 (abfd, (bfd_byte *) src->p_type); - dst->p_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->p_flags); - dst->p_offset = get_word (abfd, (bfd_byte *) src->p_offset); + 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 = get_signed_word (abfd, (bfd_byte *) src->p_vaddr); - dst->p_paddr = get_signed_word (abfd, (bfd_byte *) src->p_paddr); + 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 = get_word (abfd, (bfd_byte *) src->p_vaddr); - dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr); + dst->p_vaddr = H_GET_WORD (abfd, src->p_vaddr); + dst->p_paddr = H_GET_WORD (abfd, src->p_paddr); } - dst->p_filesz = get_word (abfd, (bfd_byte *) src->p_filesz); - dst->p_memsz = get_word (abfd, (bfd_byte *) src->p_memsz); - dst->p_align = get_word (abfd, (bfd_byte *) src->p_align); + 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 (abfd, src, dst) - bfd *abfd; - const Elf_Internal_Phdr *src; - Elf_External_Phdr *dst; +elf_swap_phdr_out (bfd *abfd, + const Elf_Internal_Phdr *src, + Elf_External_Phdr *dst) { /* note that all elements of dst are *arrays of unsigned char* already... */ - bfd_h_put_32 (abfd, src->p_type, dst->p_type); - put_word (abfd, src->p_offset, dst->p_offset); - put_word (abfd, src->p_vaddr, dst->p_vaddr); - put_word (abfd, src->p_paddr, dst->p_paddr); - put_word (abfd, src->p_filesz, dst->p_filesz); - put_word (abfd, src->p_memsz, dst->p_memsz); - bfd_h_put_32 (abfd, src->p_flags, dst->p_flags); - put_word (abfd, src->p_align, dst->p_align); + 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); } /* Translate an ELF reloc from external format to internal format. */ -INLINE void -elf_swap_reloc_in (abfd, src, dst) - bfd *abfd; - const Elf_External_Rel *src; - Elf_Internal_Rel *dst; +void +elf_swap_reloc_in (bfd *abfd, + const bfd_byte *s, + Elf_Internal_Rela *dst) { - dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset); - dst->r_info = get_word (abfd, (bfd_byte *) src->r_info); + 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; } -INLINE void -elf_swap_reloca_in (abfd, src, dst) - bfd *abfd; - const Elf_External_Rela *src; - Elf_Internal_Rela *dst; +void +elf_swap_reloca_in (bfd *abfd, + const bfd_byte *s, + Elf_Internal_Rela *dst) { - dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset); - dst->r_info = get_word (abfd, (bfd_byte *) src->r_info); - dst->r_addend = get_signed_word (abfd, (bfd_byte *) src->r_addend); + 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); } /* Translate an ELF reloc from internal format to external format. */ -INLINE void -elf_swap_reloc_out (abfd, src, dst) - bfd *abfd; - const Elf_Internal_Rel *src; - Elf_External_Rel *dst; +void +elf_swap_reloc_out (bfd *abfd, + const Elf_Internal_Rela *src, + bfd_byte *d) { - put_word (abfd, src->r_offset, dst->r_offset); - put_word (abfd, src->r_info, dst->r_info); + 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); } -INLINE void -elf_swap_reloca_out (abfd, src, dst) - bfd *abfd; - const Elf_Internal_Rela *src; - Elf_External_Rela *dst; +void +elf_swap_reloca_out (bfd *abfd, + const Elf_Internal_Rela *src, + bfd_byte *d) { - put_word (abfd, src->r_offset, dst->r_offset); - put_word (abfd, src->r_info, dst->r_info); - put_signed_word (abfd, src->r_addend, dst->r_addend); + 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); } -INLINE void -elf_swap_dyn_in (abfd, p, dst) - bfd *abfd; - const PTR p; - Elf_Internal_Dyn *dst; +void +elf_swap_dyn_in (bfd *abfd, + const void *p, + Elf_Internal_Dyn *dst) { - const Elf_External_Dyn *src = (const Elf_External_Dyn *) p; + const Elf_External_Dyn *src = p; - dst->d_tag = get_word (abfd, src->d_tag); - dst->d_un.d_val = get_word (abfd, src->d_un.d_val); + dst->d_tag = H_GET_WORD (abfd, src->d_tag); + dst->d_un.d_val = H_GET_WORD (abfd, src->d_un.d_val); } -INLINE void -elf_swap_dyn_out (abfd, src, p) - bfd *abfd; - const Elf_Internal_Dyn *src; - PTR p; +void +elf_swap_dyn_out (bfd *abfd, + const Elf_Internal_Dyn *src, + void *p) { - Elf_External_Dyn *dst = (Elf_External_Dyn *) p; + Elf_External_Dyn *dst = p; - put_word (abfd, src->d_tag, dst->d_tag); - put_word (abfd, src->d_un.d_val, dst->d_un.d_val); + H_PUT_WORD (abfd, src->d_tag, dst->d_tag); + H_PUT_WORD (abfd, src->d_un.d_val, dst->d_un.d_val); } /* ELF .o/exec file reading */ @@ -467,9 +449,8 @@ elf_swap_dyn_out (abfd, src, p) First we validate the file by reading in the ELF header and checking the magic number. */ -static INLINE boolean -elf_file_p (x_ehdrp) - Elf_External_Ehdr *x_ehdrp; +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) @@ -486,32 +467,25 @@ elf_file_p (x_ehdrp) file does not match the target vector. */ const bfd_target * -elf_object_p (abfd) - bfd *abfd; +elf_object_p (bfd *abfd) { Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ Elf_External_Shdr x_shdr; /* Section header table entry, external form */ - Elf_Internal_Shdr *i_shdrp = NULL; /* Section header table, internal form */ + Elf_Internal_Shdr i_shdr; + Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ unsigned int shindex; char *shstrtab; /* Internal copy of section header stringtab */ - struct elf_backend_data *ebd; - struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd); - struct sec *preserved_sections = abfd->sections; - unsigned int preserved_section_count = abfd->section_count; - enum bfd_architecture previous_arch = bfd_get_arch (abfd); - unsigned long previous_mach = bfd_get_mach (abfd); - struct elf_obj_tdata *new_tdata = NULL; + const struct elf_backend_data *ebd; + struct bfd_preserve preserve; asection *s; + bfd_size_type amt; - /* Clear section information, since there might be a recognized bfd that - we now check if we can replace, and we don't want to append to it. */ - abfd->sections = NULL; - abfd->section_count = 0; + preserve.marker = NULL; /* Read in the ELF header in external format. */ - if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) + 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; @@ -525,9 +499,9 @@ elf_object_p (abfd) section header table (FIXME: See comments re sections at top of this file). */ - if ((elf_file_p (&x_ehdr) == false) || - (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) || - (x_ehdr.e_ident[EI_CLASS] != ELFCLASS)) + 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; /* Check that file's byte order matches xvec's */ @@ -546,14 +520,15 @@ elf_object_p (abfd) goto got_wrong_format_error; } + if (!bfd_preserve_save (abfd, &preserve)) + goto got_no_match; + /* Allocate an instance of the elf_obj_tdata structure and hook it up to the tdata pointer in the bfd. */ - new_tdata = ((struct elf_obj_tdata *) - bfd_zalloc (abfd, sizeof (struct elf_obj_tdata))); - if (new_tdata == NULL) + if (! (*abfd->xvec->_bfd_set_format[bfd_object]) (abfd)) goto got_no_match; - elf_tdata (abfd) = new_tdata; + preserve.marker = elf_tdata (abfd); /* Now that we know the byte order, swap in the rest of the header */ i_ehdrp = elf_elfheader (abfd); @@ -566,14 +541,19 @@ elf_object_p (abfd) if (i_ehdrp->e_type == ET_CORE) goto got_wrong_format_error; - /* If there is no section header table, we're hosed. */ - if (i_ehdrp->e_shoff == 0) + /* If this is a relocatable file and there is no section header + table, then we're hosed. */ + 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 size of each section header table entry actually matches the size - recorded in the file. */ - if (i_ehdrp->e_shentsize != sizeof (x_shdr)) + 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; + + /* Further sanity check. */ + if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0) goto got_wrong_format_error; ebd = get_elf_backend_data (abfd); @@ -581,8 +561,10 @@ elf_object_p (abfd) /* Check that the ELF e_machine field matches what this particular BFD format expects. */ 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)) + && (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; @@ -593,11 +575,11 @@ elf_object_p (abfd) for which we do not have a specific backend. */ for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++) { - struct elf_backend_data *back; + const struct elf_backend_data *back; if ((*target_ptr)->flavour != bfd_target_elf_flavour) continue; - back = (struct elf_backend_data *) (*target_ptr)->backend_data; + 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) @@ -629,35 +611,82 @@ elf_object_p (abfd) /* Remember the entry point specified in the ELF file header. */ bfd_set_start_address (abfd, i_ehdrp->e_entry); + if (i_ehdrp->e_shoff != 0) + { + /* Seek to the section header table in the file. */ + if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0) + goto got_no_match; + + /* Read the first section header at index 0, and convert to internal + form. */ + 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 the section count is zero, the actual count is in the first + section header. */ + if (i_ehdrp->e_shnum == SHN_UNDEF) + i_ehdrp->e_shnum = i_shdr.sh_size; + + /* And similarly for the string table index. */ + if (i_ehdrp->e_shstrndx == SHN_XINDEX) + i_ehdrp->e_shstrndx = i_shdr.sh_link; + } + /* Allocate space for a copy of the section header table in - internal form, seek to the section header table in the file, - read it in, and convert it to internal form. */ - i_shdrp = ((Elf_Internal_Shdr *) - bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum)); - elf_elfsections (abfd) = ((Elf_Internal_Shdr **) - bfd_alloc (abfd, - sizeof (i_shdrp) * i_ehdrp->e_shnum)); - if (!i_shdrp || !elf_elfsections (abfd)) - goto got_no_match; - if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) != 0) - goto got_no_match; - for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++) + internal form. */ + if (i_ehdrp->e_shnum != 0) { - if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd) != sizeof (x_shdr)) + 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; - elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); - elf_elfsections (abfd)[shindex] = i_shdrp + shindex; - - /* If the section is loaded, but not page aligned, clear - D_PAGED. */ - if ((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->maxpagesize) - != 0)) - abfd->flags &= ~D_PAGED; + + 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++; + + /* Read in the rest of the section header table and convert it + to internal form. */ + 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 the section is loaded, but not page aligned, clear + D_PAGED. */ + 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->maxpagesize) + != 0)) + abfd->flags &= ~D_PAGED; + } } - if (i_ehdrp->e_shstrndx) + + if (i_ehdrp->e_shstrndx && i_ehdrp->e_shoff) { if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx)) goto got_no_match; @@ -671,21 +700,18 @@ elf_object_p (abfd) Elf_Internal_Phdr *i_phdr; unsigned int i; - elf_tdata (abfd)->phdr = ((Elf_Internal_Phdr *) - bfd_alloc (abfd, - (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); if (elf_tdata (abfd)->phdr == NULL) goto got_no_match; - if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) != 0) + 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_read ((PTR) &x_phdr, sizeof x_phdr, 1, abfd) - != sizeof 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); } @@ -697,25 +723,36 @@ elf_object_p (abfd) bfd_section_from_shdr with it (since this particular strtab is used to find all of the ELF section names.) */ - shstrtab = bfd_elf_get_str_section (abfd, i_ehdrp->e_shstrndx); - if (!shstrtab) - goto got_no_match; - - /* Once all of the section headers have been read and converted, we - can start processing them. Note that the first section header is - a dummy placeholder entry, so we ignore it. */ - - for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++) + if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff) { - if (! bfd_section_from_shdr (abfd, shindex)) + unsigned int num_sec; + + shstrtab = bfd_elf_get_str_section (abfd, i_ehdrp->e_shstrndx); + if (!shstrtab) goto got_no_match; + + /* Once all of the section headers have been read and converted, we + can start processing them. Note that the first section header is + 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; + } + + /* Set up group pointers. */ + if (! _bfd_elf_setup_group_pointers (abfd)) + goto got_wrong_format_error; } /* Let the backend double check the format and override global information. */ if (ebd->elf_backend_object_p) { - if ((*ebd->elf_backend_object_p) (abfd) == false) + if (! (*ebd->elf_backend_object_p) (abfd)) goto got_wrong_format_error; } @@ -738,7 +775,8 @@ elf_object_p (abfd) } } - return (abfd->xvec); + bfd_preserve_finish (abfd, &preserve); + return abfd->xvec; got_wrong_format_error: /* There is way too much undoing of half-known state here. The caller, @@ -750,20 +788,12 @@ elf_object_p (abfd) target-specific elf_backend_object_p function. Note that saving the whole bfd here and restoring it would be even worse; the first thing you notice is that the cached bfd file position gets out of sync. */ - bfd_default_set_arch_mach (abfd, previous_arch, previous_mach); bfd_set_error (bfd_error_wrong_format); + got_no_match: - if (new_tdata != NULL - && new_tdata->elf_sect_ptr != NULL) - bfd_release (abfd, new_tdata->elf_sect_ptr); - if (i_shdrp != NULL) - bfd_release (abfd, i_shdrp); - if (new_tdata != NULL) - bfd_release (abfd, new_tdata); - elf_tdata (abfd) = preserved_tdata; - abfd->sections = preserved_sections; - abfd->section_count = preserved_section_count; - return (NULL); + if (preserve.marker != NULL) + bfd_preserve_restore (abfd, &preserve); + return NULL; } /* ELF .o/exec file writing */ @@ -771,19 +801,17 @@ elf_object_p (abfd) /* Write out the relocs. */ void -elf_write_relocs (abfd, sec, data) - bfd *abfd; - asection *sec; - PTR data; +elf_write_relocs (bfd *abfd, asection *sec, void *data) { - boolean *failedp = (boolean *) data; + bfd_boolean *failedp = data; Elf_Internal_Shdr *rela_hdr; - Elf_External_Rela *outbound_relocas; - Elf_External_Rel *outbound_relocs; + bfd_vma addr_offset; + void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); + size_t extsize; + bfd_byte *dst_rela; unsigned int idx; - int use_rela_p; - asymbol *last_sym = 0; - int last_sym_idx = 0; + asymbol *last_sym; + int last_sym_idx; /* If we have already failed, don't do anything. */ if (*failedp) @@ -802,147 +830,93 @@ elf_write_relocs (abfd, sec, data) rela_hdr = &elf_section_data (sec)->rel_hdr; rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; - rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); + rela_hdr->contents = bfd_alloc (abfd, rela_hdr->sh_size); if (rela_hdr->contents == NULL) { - *failedp = true; + *failedp = TRUE; return; } /* Figure out whether the relocations are RELA or REL relocations. */ if (rela_hdr->sh_type == SHT_RELA) - use_rela_p = true; + { + swap_out = elf_swap_reloca_out; + extsize = sizeof (Elf_External_Rela); + } else if (rela_hdr->sh_type == SHT_REL) - use_rela_p = false; + { + swap_out = elf_swap_reloc_out; + extsize = sizeof (Elf_External_Rel); + } else /* Every relocation section should be either an SHT_RELA or an SHT_REL section. */ abort (); + /* The address of an ELF reloc is section relative for an object + file, and absolute for an executable file or shared library. + The address of a BFD reloc is always section relative. */ + addr_offset = 0; + if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) + addr_offset = sec->vma; + /* orelocation has the data, reloc_count has the count... */ - if (use_rela_p) - { - outbound_relocas = (Elf_External_Rela *) rela_hdr->contents; + last_sym = 0; + last_sym_idx = 0; + dst_rela = rela_hdr->contents; - for (idx = 0; idx < sec->reloc_count; idx++) + 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 { - Elf_Internal_Rela dst_rela; - Elf_External_Rela *src_rela; - arelent *ptr; - asymbol *sym; - int n; - - ptr = sec->orelocation[idx]; - src_rela = outbound_relocas + idx; - - /* The address of an ELF reloc is section relative for an object - file, and absolute for an executable file or shared library. - The address of a BFD reloc is always section relative. */ - if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) - dst_rela.r_offset = ptr->address; - else - dst_rela.r_offset = ptr->address + sec->vma; - - 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) { - 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; + *failedp = TRUE; return; } - - dst_rela.r_info = ELF_R_INFO (n, ptr->howto->type); - - dst_rela.r_addend = ptr->addend; - elf_swap_reloca_out (abfd, &dst_rela, src_rela); + last_sym_idx = n; } - } - else - /* REL relocations */ - { - outbound_relocs = (Elf_External_Rel *) rela_hdr->contents; - for (idx = 0; idx < sec->reloc_count; idx++) + if ((*ptr->sym_ptr_ptr)->the_bfd != NULL + && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec + && ! _bfd_elf_validate_reloc (abfd, ptr)) { - Elf_Internal_Rel dst_rel; - Elf_External_Rel *src_rel; - arelent *ptr; - int n; - asymbol *sym; - - ptr = sec->orelocation[idx]; - sym = *ptr->sym_ptr_ptr; - src_rel = outbound_relocs + idx; - - /* The address of an ELF reloc is section relative for an object - file, and absolute for an executable file or shared library. - The address of a BFD reloc is always section relative. */ - if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) - dst_rel.r_offset = ptr->address; - else - dst_rel.r_offset = ptr->address + sec->vma; - - 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; - } - - dst_rel.r_info = ELF_R_INFO (n, ptr->howto->type); - - elf_swap_reloc_out (abfd, &dst_rel, src_rel); + *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); } } /* Write out the program headers. */ int -elf_write_out_phdrs (abfd, phdr, count) - bfd *abfd; - const Elf_Internal_Phdr *phdr; - int count; +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_write (&extphdr, sizeof (Elf_External_Phdr), 1, abfd) + if (bfd_bwrite (&extphdr, sizeof (Elf_External_Phdr), abfd) != sizeof (Elf_External_Phdr)) return -1; phdr++; @@ -952,15 +926,15 @@ elf_write_out_phdrs (abfd, phdr, count) /* Write out the section headers and the ELF file header. */ -boolean -elf_write_shdrs_and_ehdr (abfd) - bfd *abfd; +bfd_boolean +elf_write_shdrs_and_ehdr (bfd *abfd) { Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ Elf_External_Shdr *x_shdrp; /* Section header table, external form */ Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ unsigned int count; + bfd_size_type amt; i_ehdrp = elf_elfheader (abfd); i_shdrp = elf_elfsections (abfd); @@ -971,48 +945,59 @@ elf_write_shdrs_and_ehdr (abfd) 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_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) - != sizeof (x_ehdr))) - return false; + || bfd_bwrite (&x_ehdr, amt, abfd) != amt) + return FALSE; + + /* Some fields in the first section header handle overflow of ehdr + fields. */ + 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; /* at this point we've concocted all the ELF sections... */ - x_shdrp = (Elf_External_Shdr *) - bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum)); + amt = i_ehdrp->e_shnum; + amt *= sizeof (*x_shdrp); + x_shdrp = bfd_alloc (abfd, amt); if (!x_shdrp) - return false; + return FALSE; - for (count = 0; count < i_ehdrp->e_shnum; count++) + for (count = 0; count < i_ehdrp->e_shnum; i_shdrp++, count++) { #if DEBUG & 2 - elf_debug_section (count, i_shdrp[count]); + elf_debug_section (count, *i_shdrp); #endif - elf_swap_shdr_out (abfd, i_shdrp[count], 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 - || (bfd_write ((PTR) x_shdrp, sizeof (*x_shdrp), i_ehdrp->e_shnum, abfd) - != sizeof (*x_shdrp) * i_ehdrp->e_shnum)) - return false; + || bfd_bwrite (x_shdrp, amt, abfd) != amt) + return FALSE; /* need to dump the string table too... */ - return true; + return TRUE; } long -elf_slurp_symbol_table (abfd, symptrs, dynamic) - bfd *abfd; - asymbol **symptrs; /* Buffer for generated bfd symbols */ - boolean dynamic; +elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) { Elf_Internal_Shdr *hdr; Elf_Internal_Shdr *verhdr; unsigned long symcount; /* Number of external ELF symbols */ elf_symbol_type *sym; /* Pointer to current bfd symbol */ elf_symbol_type *symbase; /* Buffer for generated bfd symbols */ - Elf_Internal_Sym i_sym; - Elf_External_Sym *x_symp = NULL; - Elf_External_Versym *x_versymp = NULL; + 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; /* Read each raw ELF symbol, converting from external ELF form to internal ELF form, and then using the information to create a @@ -1046,38 +1031,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) } } - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) - return -1; - + ebd = get_elf_backend_data (abfd); symcount = hdr->sh_size / sizeof (Elf_External_Sym); - if (symcount == 0) sym = symbase = NULL; else { - unsigned long i; - - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) + isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) return -1; - symbase = ((elf_symbol_type *) - bfd_zalloc (abfd, symcount * sizeof (elf_symbol_type))); + amt = symcount; + amt *= sizeof (elf_symbol_type); + symbase = bfd_zalloc (abfd, amt); if (symbase == (elf_symbol_type *) NULL) - return -1; - sym = symbase; - - /* Temporarily allocate room for the raw ELF symbols. */ - x_symp = ((Elf_External_Sym *) - bfd_malloc (symcount * sizeof (Elf_External_Sym))); - if (x_symp == NULL && symcount != 0) - goto error_return; - - if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd) - != symcount * sizeof (Elf_External_Sym)) goto error_return; /* Read the raw ELF version symbol information. */ - if (verhdr != NULL && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount) { @@ -1097,35 +1068,39 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0) goto error_return; - x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size); - if (x_versymp == NULL && verhdr->sh_size != 0) + xverbuf = bfd_malloc (verhdr->sh_size); + if (xverbuf == NULL && verhdr->sh_size != 0) goto error_return; - if (bfd_read ((PTR) x_versymp, 1, verhdr->sh_size, abfd) - != verhdr->sh_size) + if (bfd_bread (xverbuf, verhdr->sh_size, abfd) != verhdr->sh_size) goto error_return; } /* Skip first symbol, which is a null dummy. */ - for (i = 1; i < symcount; i++) + xver = xverbuf; + if (xver != NULL) + ++xver; + isymend = isymbuf + symcount; + for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++) { - elf_swap_symbol_in (abfd, x_symp + i, &i_sym); - memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym)); -#ifdef ELF_KEEP_EXTSYM - memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym)); -#endif + memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym)); sym->symbol.the_bfd = abfd; sym->symbol.name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, - i_sym.st_name); + isym->st_name); - sym->symbol.value = i_sym.st_value; + sym->symbol.value = isym->st_value; - if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERVE) + if (isym->st_shndx == SHN_UNDEF) { - sym->symbol.section = section_from_elf_index (abfd, - i_sym.st_shndx); + 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 @@ -1134,39 +1109,34 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) sym->symbol.section = bfd_abs_section_ptr; } } - else if (i_sym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) { sym->symbol.section = bfd_abs_section_ptr; } - else if (i_sym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) { sym->symbol.section = bfd_com_section_ptr; /* Elf puts the alignment into the `value' field, and the size into the `size' field. BFD wants to see the size in the value field, and doesn't care (at the moment) about the alignment. */ - sym->symbol.value = i_sym.st_size; - } - else if (i_sym.st_shndx == SHN_UNDEF) - { - sym->symbol.section = bfd_und_section_ptr; + sym->symbol.value = isym->st_size; } else sym->symbol.section = bfd_abs_section_ptr; - /* If this is a relocateable file, then the symbol value is + /* If this is a relocatable file, then the symbol value is already section relative. */ if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) sym->symbol.value -= sym->symbol.section->vma; - switch (ELF_ST_BIND (i_sym.st_info)) + switch (ELF_ST_BIND (isym->st_info)) { case STB_LOCAL: sym->symbol.flags |= BSF_LOCAL; break; case STB_GLOBAL: - if (i_sym.st_shndx != SHN_UNDEF - && i_sym.st_shndx != SHN_COMMON) + if (isym->st_shndx != SHN_UNDEF && isym->st_shndx != SHN_COMMON) sym->symbol.flags |= BSF_GLOBAL; break; case STB_WEAK: @@ -1174,7 +1144,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) break; } - switch (ELF_ST_TYPE (i_sym.st_info)) + switch (ELF_ST_TYPE (isym->st_info)) { case STT_SECTION: sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING; @@ -1193,31 +1163,24 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (dynamic) sym->symbol.flags |= BSF_DYNAMIC; - if (x_versymp != NULL) + if (xver != NULL) { Elf_Internal_Versym iversym; - _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym); + _bfd_elf_swap_versym_in (abfd, xver, &iversym); sym->version = iversym.vs_vers; + xver++; } /* Do some backend-specific processing on this symbol. */ - { - struct elf_backend_data *ebd = get_elf_backend_data (abfd); - if (ebd->elf_backend_symbol_processing) - (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol); - } - - sym++; + if (ebd->elf_backend_symbol_processing) + (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol); } } /* Do some backend-specific processing on this symbol table. */ - { - struct elf_backend_data *ebd = get_elf_backend_data (abfd); - if (ebd->elf_backend_symbol_table_processing) - (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount); - } + if (ebd->elf_backend_symbol_table_processing) + (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount); /* We rely on the zalloc to clear out the final symbol entry. */ @@ -1237,71 +1200,70 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) *symptrs = 0; /* Final null pointer */ } - if (x_versymp != NULL) - free (x_versymp); - if (x_symp != NULL) - free (x_symp); + if (xverbuf != NULL) + free (xverbuf); + if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return symcount; + error_return: - if (x_versymp != NULL) - free (x_versymp); - if (x_symp != NULL) - free (x_symp); + if (xverbuf != NULL) + free (xverbuf); + if (isymbuf != NULL && hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); return -1; } /* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of them. */ -static boolean -elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count, - relents, symbols, dynamic) - bfd *abfd; - asection *asect; - Elf_Internal_Shdr *rel_hdr; - bfd_size_type reloc_count; - arelent *relents; - asymbol **symbols; - boolean dynamic; +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) { - struct elf_backend_data * const ebd = get_elf_backend_data (abfd); - PTR allocated = NULL; + 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 = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size); + 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_read (allocated, 1, rel_hdr->sh_size, abfd) + || (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size)) goto error_return; - native_relocs = (bfd_byte *) allocated; + 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; - Elf_Internal_Rel rel; if (entsize == sizeof (Elf_External_Rela)) - elf_swap_reloca_in (abfd, (Elf_External_Rela *) native_relocs, &rela); + elf_swap_reloca_in (abfd, native_relocs, &rela); else - { - elf_swap_reloc_in (abfd, (Elf_External_Rel *) native_relocs, &rel); - rela.r_offset = rel.r_offset; - rela.r_info = rel.r_info; - rela.r_addend = 0; - } + elf_swap_reloc_in (abfd, native_relocs, &rela); /* The address of an ELF reloc is section relative for an object file, and absolute for an executable file or shared library. @@ -1314,6 +1276,13 @@ elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count, 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; @@ -1330,31 +1299,32 @@ elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count, relent->addend = rela.r_addend; - if (entsize == sizeof (Elf_External_Rela)) + 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, &rel); + (*ebd->elf_info_to_howto_rel) (abfd, relent, &rela); } if (allocated != NULL) free (allocated); - return true; + return TRUE; error_return: if (allocated != NULL) free (allocated); - return false; + return FALSE; } /* Read in and swap the external relocs. */ -boolean -elf_slurp_reloc_table (abfd, asect, symbols, dynamic) - bfd *abfd; - asection *asect; - asymbol **symbols; - boolean dynamic; +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; @@ -1362,15 +1332,16 @@ elf_slurp_reloc_table (abfd, asect, symbols, dynamic) bfd_size_type reloc_count; bfd_size_type reloc_count2; arelent *relents; + bfd_size_type amt; if (asect->relocation != NULL) - return true; + return TRUE; if (! dynamic) { if ((asect->flags & SEC_RELOC) == 0 || asect->reloc_count == 0) - return true; + return TRUE; rel_hdr = &d->rel_hdr; reloc_count = NUM_SHDR_ENTRIES (rel_hdr); @@ -1388,8 +1359,8 @@ elf_slurp_reloc_table (abfd, asect, symbols, dynamic) case because relocations against this section may use the dynamic symbol table, and in that case bfd_section_from_shdr in elf.c does not update the RELOC_COUNT. */ - if (asect->_raw_size == 0) - return true; + if (asect->size == 0) + return TRUE; rel_hdr = &d->this_hdr; reloc_count = NUM_SHDR_ENTRIES (rel_hdr); @@ -1397,34 +1368,31 @@ elf_slurp_reloc_table (abfd, asect, symbols, dynamic) reloc_count2 = 0; } - relents = ((arelent *) - bfd_alloc (abfd, - (reloc_count + reloc_count2) * sizeof (arelent))); + amt = (reloc_count + reloc_count2) * sizeof (arelent); + relents = bfd_alloc (abfd, amt); if (relents == NULL) - return false; + return FALSE; if (!elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count, relents, symbols, dynamic)) - return false; + return FALSE; if (rel_hdr2 && !elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr2, reloc_count2, relents + reloc_count, symbols, dynamic)) - return false; + return FALSE; asect->relocation = relents; - return true; + return TRUE; } #ifdef DEBUG static void -elf_debug_section (num, hdr) - int num; - Elf_Internal_Shdr *hdr; +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 : "", @@ -1450,8 +1418,7 @@ elf_debug_section (num, hdr) } static void -elf_debug_file (ehdrp) - Elf_Internal_Ehdr *ehdrp; +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); @@ -1463,8 +1430,7 @@ elf_debug_file (ehdrp) } static char * -elf_symbol_flags (flags) - flagword flags; +elf_symbol_flags (flagword flags) { static char buffer[1024]; @@ -1535,8 +1501,230 @@ elf_symbol_flags (flags) } #endif +/* Create a new BFD as if by bfd_openr. Rather than opening a file, + reconstruct an ELF file by reading the segments out of remote memory + based on the ELF file header at EHDR_VMA and the ELF program headers it + points to. If not null, *LOADBASEP is filled in with the difference + between the VMAs from which the segments were read, and the VMAs the + file headers (and hence BFD's idea of each section's VMA) put them at. + + The function TARGET_READ_MEMORY is called to copy LEN bytes from the + remote memory at target address VMA into the local buffer at MYADDR; it + should return zero on success or an `errno' code on failure. TEMPL must + be a BFD for a target with the word size and byte order found in the + remote memory. */ + +bfd * +NAME(_bfd_elf,bfd_from_remote_memory) + (bfd *templ, + bfd_vma ehdr_vma, + bfd_vma *loadbasep, + int (*target_read_memory) (bfd_vma, char *, int)) +{ + Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ + Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ + Elf_External_Phdr *x_phdrs; + Elf_Internal_Phdr *i_phdrs, *last_phdr; + bfd *nbfd; + struct bfd_in_memory *bim; + int contents_size; + char *contents; + int err; + unsigned int i; + bfd_vma loadbase; + + /* Read in the ELF header in external format. */ + err = target_read_memory (ehdr_vma, (char *) &x_ehdr, sizeof x_ehdr); + if (err) + { + bfd_set_error (bfd_error_system_call); + errno = err; + return NULL; + } + + /* Now check to see if we have a valid ELF file, and one that BFD can + make use of. The magic number must match, the address size ('class') + and byte-swapping must match our XVEC entry. */ + + 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; + } + + /* Check that file's byte order matches xvec's */ + switch (x_ehdr.e_ident[EI_DATA]) + { + case ELFDATA2MSB: /* Big-endian */ + if (! bfd_header_big_endian (templ)) + { + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + break; + case ELFDATA2LSB: /* Little-endian */ + if (! bfd_header_little_endian (templ)) + { + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + break; + case ELFDATANONE: /* No data encoding specified */ + default: /* Unknown data encoding specified */ + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + elf_swap_ehdr_in (templ, &x_ehdr, &i_ehdr); + + /* The file header tells where to find the program headers. + These are what we use to actually choose what to read. */ + + 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, (char *) 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) + { + 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) + { + /* There were no PT_LOAD segments, so we don't have anything to read. */ + free (x_phdrs); + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + /* Trim the last segment so we don't bother with zeros in the last page + that are off the end of the file. However, if the extra bit in that + page includes the section headers, keep them. */ + 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; + + /* Now we know the size of the whole image we want read in. */ + 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) + { + 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 the segments visible in memory didn't include the section headers, + then clear them from the file header. */ + 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); + } + + /* This will normally have been in the first PT_LOAD segment. But it + conceivably could be missing, and we might have just changed it. */ + 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)); + 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 = ""; + 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" -#include "elflink.h" /* Size-dependent data and functions. */ const struct elf_size_info NAME(_bfd_elf,size_info) = { @@ -1550,18 +1738,19 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = { sizeof (Elf_External_Note), 4, 1, - ARCH_SIZE, FILE_ALIGN, + 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, - NULL, - NULL, - NULL, - NULL + elf_swap_reloc_in, + elf_swap_reloc_out, + elf_swap_reloca_in, + elf_swap_reloca_out };