📄 elf.c
字号:
/* ELF executable support for BFD. Copyright 1991, 1992 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and Programming Support Tools". Sufficient support for gdb. Rewritten by Mark Eichin @ Cygnus Support, from information published in "System V Application Binary Interface", chapters 4 and 5, as well as the various "Processor Supplement" documents derived from it. Added support for assembler and other object file utilities. This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /**************************************** WARNING This is only a partial ELF implementation, incorporating only those parts that are required to get gdb up and running. It is expected that it will be expanded to a full ELF implementation at some future date. Unimplemented stubs call abort() to ensure that they get proper attention if they are ever called. The stubs are here since this version was hacked from the COFF version, and thus they will probably go away or get expanded appropriately in a future version. fnf@cygnus.com *****************************************//* Problems and other issues to resolve. (1) BFD expects there to be some fixed number of "sections" in the object file. I.E. there is a "section_count" variable in the bfd structure which contains the number of sections. However, ELF supports multiple "views" of a file. In particular, with current implementations, executable files typically have two tables, a program header table and a section header table, both of which partition the executable. In ELF-speak, the "linking view" of the file uses the section header table to access "sections" within the file, and the "execution view" uses the program header table to access "segments" within the file. "Segments" typically may contain all the data from one or more "sections". Note that the section header table is optional in ELF executables, but it is this information that is most useful to gdb. If the section header table is missing, then gdb should probably try to make do with the program header table. (FIXME)*/#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "obstack.h"#include "elf/common.h"#include "elf/internal.h"#include "elf/external.h"#ifdef HAVE_PROCFS /* Some core file support requires host /proc files */#include <sys/procfs.h>#else#define bfd_prstatus(abfd, descdata, descsz, filepos) /* Define away */#define bfd_fpregset(abfd, descdata, descsz, filepos) /* Define away */#define bfd_prpsinfo(abfd, descdata, descsz, filepos) /* Define away */#endif/* Forward data declarations */extern bfd_target elf_little_vec, elf_big_vec;/* Currently the elf_symbol_type struct just contains the generic bfd symbol structure. */typedef struct{ asymbol symbol;} elf_symbol_type;/* Some private data is stashed away for future use using the tdata pointer in the bfd structure. */struct elf_obj_tdata{ Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */ Elf_Internal_Shdr *elf_sect_ptr; struct strtab *strtab_ptr; int symtab_section; void *prstatus; /* The raw /proc prstatus structure */ void *prpsinfo; /* The raw /proc prpsinfo structure */};#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header)#define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr)#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr)#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section)#define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo)#define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus)/* Translate an ELF symbol in external format into an ELF symbol in internal format. */static voidDEFUN(elf_swap_symbol_in,(abfd, src, dst), bfd *abfd AND Elf_External_Sym *src AND Elf_Internal_Sym *dst){ dst -> st_name = bfd_h_get_32 (abfd, (bfd_byte *) src -> st_name); dst -> st_value = bfd_h_get_32 (abfd, (bfd_byte *) src -> st_value); dst -> st_size = bfd_h_get_32 (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);}/* Translate an ELF symbol in internal format into an ELF symbol in external format. */static voidDEFUN(elf_swap_symbol_out,(abfd, src, dst), bfd *abfd AND Elf_Internal_Sym *src AND Elf_External_Sym *dst){ bfd_h_put_32 (abfd, src->st_name, dst->st_name); bfd_h_put_32 (abfd, src->st_value, dst->st_value); bfd_h_put_32 (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);}/* Translate an ELF file header in external format into an ELF file header in internal format. */static voidDEFUN(elf_swap_ehdr_in,(abfd, src, dst), bfd *abfd AND Elf_External_Ehdr *src AND Elf_Internal_Ehdr *dst){ 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_entry = bfd_h_get_32 (abfd, (bfd_byte *) src -> e_entry); dst -> e_phoff = bfd_h_get_32 (abfd, (bfd_byte *) src -> e_phoff); dst -> e_shoff = bfd_h_get_32 (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);}/* Translate an ELF file header in internal format into an ELF file header in external format. */static voidDEFUN(elf_swap_ehdr_out,(abfd, src, dst), bfd *abfd AND Elf_Internal_Ehdr *src AND Elf_External_Ehdr *dst){ 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); bfd_h_put_32 (abfd, src->e_entry, dst->e_entry); bfd_h_put_32 (abfd, src->e_phoff, dst->e_phoff); bfd_h_put_32 (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);}/* Translate an ELF section header table entry in external format into an ELF section header table entry in internal format. */static voidDEFUN(elf_swap_shdr_in,(abfd, src, dst), bfd *abfd AND Elf_External_Shdr *src AND Elf_Internal_Shdr *dst){ 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 = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_flags); dst->sh_addr = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_addr); dst->sh_offset = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_offset); dst->sh_size = bfd_h_get_32 (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 = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_addralign); dst->sh_entsize = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_entsize); /* we haven't done any processing on it yet, so... */ dst->rawdata = (void*)0;}/* Translate an ELF section header table entry in internal format into an ELF section header table entry in external format. */static voidDEFUN(elf_swap_shdr_out,(abfd, src, dst), bfd *abfd AND Elf_Internal_Shdr *src AND 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); bfd_h_put_32 (abfd, src->sh_flags, dst->sh_flags); bfd_h_put_32 (abfd, src->sh_addr, dst->sh_addr); bfd_h_put_32 (abfd, src->sh_offset, dst->sh_offset); bfd_h_put_32 (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); bfd_h_put_32 (abfd, src->sh_addralign, dst->sh_addralign); bfd_h_put_32 (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. */static voidDEFUN(elf_swap_phdr_in,(abfd, src, dst), bfd *abfd AND Elf_External_Phdr *src AND Elf_Internal_Phdr *dst){ dst->p_type = bfd_h_get_32 (abfd, (bfd_byte *) src->p_type); dst->p_offset = bfd_h_get_32 (abfd, (bfd_byte *) src->p_offset); dst->p_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) src->p_vaddr); dst->p_paddr = bfd_h_get_32 (abfd, (bfd_byte *) src->p_paddr); dst->p_filesz = bfd_h_get_32 (abfd, (bfd_byte *) src->p_filesz); dst->p_memsz = bfd_h_get_32 (abfd, (bfd_byte *) src->p_memsz); dst->p_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->p_flags); dst->p_align = bfd_h_get_32 (abfd, (bfd_byte *) src->p_align);}/* Translate an ELF reloc from external format to internal format. */static voidDEFUN(elf_swap_reloc_in,(abfd, src, dst), bfd *abfd AND Elf_External_Rel *src AND Elf_Internal_Rel *dst){ dst->r_offset = bfd_h_get_32 (abfd, (bfd_byte *) src->r_offset); dst->r_info = bfd_h_get_32 (abfd, (bfd_byte *) src->r_info);}static voidDEFUN(elf_swap_reloca_in,(abfd, src, dst), bfd *abfd AND Elf_External_Rela *src AND Elf_Internal_Rela *dst){ dst->r_offset = bfd_h_get_32 (abfd, (bfd_byte *) src->r_offset); dst->r_info = bfd_h_get_32 (abfd, (bfd_byte *) src->r_info); dst->r_addend = bfd_h_get_32 (abfd, (bfd_byte *) src->r_addend);}/* Translate an ELF reloc from internal format to external format. */static voidDEFUN(elf_swap_reloc_out,(abfd, src, dst), bfd *abfd AND Elf_Internal_Rel *src AND Elf_External_Rel *dst){ bfd_h_put_32 (abfd, src->r_offset, dst->r_offset); bfd_h_put_32 (abfd, src->r_info, dst->r_info);}static voidDEFUN(elf_swap_reloca_out,(abfd, src, dst), bfd *abfd AND Elf_Internal_Rela *src AND Elf_External_Rela *dst){ bfd_h_put_32 (abfd, src->r_offset, dst->r_offset); bfd_h_put_32 (abfd, src->r_info, dst->r_info); bfd_h_put_32 (abfd, src->r_addend, dst->r_addend);}static char *EXFUN(elf_read, (bfd *, long, int));static struct sec * EXFUN(section_from_elf_index, (bfd *, int));static int EXFUN(elf_section_from_bfd_section, (bfd *, struct sec *));static boolean EXFUN(elf_slurp_symbol_table, (bfd *, asymbol **));static void EXFUN(elf_info_to_howto, (bfd *, arelent *, Elf_Internal_Rela *));static char *EXFUN(elf_get_str_section, (bfd *, unsigned int)); /* INTERNAL_FUNCTION bfd_elf_find_sectionSYNOPSIS struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name);DESCRIPTION Helper functions for GDB to locate the string tables. Since BFD hides string tables from callers, GDB needs to use an internal hook to find them. Sun's .stabstr, in particular, isn't even pointed to by the .stab section, so ordinary mechanisms wouldn't work to find it, even if we had some.*/struct elf_internal_shdr *DEFUN(bfd_elf_find_section, (abfd, name), bfd *abfd AND char *name){ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); char *shstrtab = elf_get_str_section (abfd, elf_elfheader (abfd)->e_shstrndx); unsigned int max = elf_elfheader (abfd)->e_shnum; unsigned int i; for (i = 1; i < max; i++) if (!strcmp (&shstrtab[i_shdrp[i].sh_name], name)) return &i_shdrp[i]; return 0;}/* End of GDB support. */static char *DEFUN(elf_get_str_section, (abfd, shindex), bfd *abfd AND unsigned int shindex){ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); unsigned int shstrtabsize = i_shdrp[shindex].sh_size; unsigned int offset = i_shdrp[shindex].sh_offset; char *shstrtab = i_shdrp[shindex].rawdata; if (shstrtab) return shstrtab; if ((shstrtab = elf_read (abfd, offset, shstrtabsize)) == NULL) { return (NULL); } i_shdrp[shindex].rawdata = (void*)shstrtab; return shstrtab;}static char *DEFUN(elf_string_from_elf_section, (abfd, shindex, strindex), bfd *abfd AND unsigned int shindex AND unsigned int strindex){ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); Elf_Internal_Shdr *hdr = i_shdrp + shindex; if (! hdr->rawdata) { if (elf_get_str_section (abfd, shindex) == NULL) { return NULL; } } return ((char*)hdr->rawdata)+strindex;}#define elf_string_from_elf_strtab(abfd, strindex) \ elf_string_from_elf_section (abfd, elf_elfheader(abfd)->e_shstrndx, strindex)/* Create a new bfd section from an ELF section header. */static booleanDEFUN(bfd_section_from_shdr, (abfd, shindex), bfd *abfd AND unsigned int shindex){ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); Elf_Internal_Shdr *hdr = i_shdrp + shindex; asection *newsect; char *name; name = hdr->sh_name ? elf_string_from_elf_strtab (abfd, hdr->sh_name) : "unnamed"; switch(hdr->sh_type) { case SHT_NULL: /* inactive section. Throw it away. */ return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -