美文网首页
获取android bin、so文件符号偏移或者内存地址

获取android bin、so文件符号偏移或者内存地址

作者: 处于蒙比阶段的小白 | 来源:发表于2018-11-21 21:25 被阅读0次

    代码

    直接晒代码

    • external.h
    /*
     * external.h
     *
     *  Created on: 2016年12月7日
     *      Author: lyz
     */
    
    #ifndef BASE_ELF_READER_EXTERNAL_H_
    #define BASE_ELF_READER_EXTERNAL_H_
    
    /* ELF support for BFD.
       Copyright 1991, 1992, 1993, 1995, 1997, 1998, 1999, 2001, 2003, 2005,
       2008 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".
    
    This file is part of BFD, the Binary File Descriptor library.
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
    
    
    /* This file is part of ELF support for BFD, and contains the portions
       that describe how ELF is represented externally by the BFD library.
       I.E. it describes the in-file representation of ELF.  It requires
       the elf/common.h file which contains the portions that are common to
       both the internal and external representations. */
    
    /* The 64-bit stuff is kind of random.  Perhaps someone will publish a
       spec someday.  */
    /* Special section indices, which may show up in st_shndx fields, among
       other places.  */
    
    #define SHN_LORESERVE   0xFF00      /* Begin range of reserved indices */
    #define SHN_LOPROC  0xFF00      /* Begin range of appl-specific */
    #define SHN_HIPROC  0xFF1F      /* End range of appl-specific */
    #define SHN_LOOS    0xFF20      /* OS specific semantics, lo */
    #define SHN_HIOS    0xFF3F      /* OS specific semantics, hi */
    #define SHN_ABS     0xFFF1      /* Associated symbol is absolute */
    #define SHN_COMMON  0xFFF2      /* Associated symbol is in common */
    #define SHN_XINDEX  0xFFFF      /* Section index is held elsewhere */
    #define SHN_HIRESERVE   0xFFFF      /* End range of reserved indices */
    
    /* ELF Header (32-bit implementations) */
    
    typedef struct {
        unsigned char   e_ident[16];        /* ELF "magic number" */
        unsigned char   e_type[2];      /* Identifies object file type */
        unsigned char   e_machine[2];       /* Specifies required architecture */
        unsigned char   e_version[4];       /* Identifies object file version */
        unsigned char   e_entry[4];     /* Entry point virtual address */
        unsigned char   e_phoff[4];     /* Program header table file offset */
        unsigned char   e_shoff[4];     /* Section header table file offset */
        unsigned char   e_flags[4];     /* Processor-specific flags */
        unsigned char   e_ehsize[2];        /* ELF header size in bytes */
        unsigned char   e_phentsize[2];     /* Program header table entry size */
        unsigned char   e_phnum[2];     /* Program header table entry count */
        unsigned char   e_shentsize[2];     /* Section header table entry size */
        unsigned char   e_shnum[2];     /* Section header table entry count */
        unsigned char   e_shstrndx[2];      /* Section header string table index */
    } Elf32_External_Ehdr;
    
    typedef struct {
        unsigned char   e_ident[16];        /* ELF "magic number" */
        unsigned char   e_type[2];      /* Identifies object file type */
        unsigned char   e_machine[2];       /* Specifies required architecture */
        unsigned char   e_version[4];       /* Identifies object file version */
        unsigned char   e_entry[8];     /* Entry point virtual address */
        unsigned char   e_phoff[8];     /* Program header table file offset */
        unsigned char   e_shoff[8];     /* Section header table file offset */
        unsigned char   e_flags[4];     /* Processor-specific flags */
        unsigned char   e_ehsize[2];        /* ELF header size in bytes */
        unsigned char   e_phentsize[2];     /* Program header table entry size */
        unsigned char   e_phnum[2];     /* Program header table entry count */
        unsigned char   e_shentsize[2];     /* Section header table entry size */
        unsigned char   e_shnum[2];     /* Section header table entry count */
        unsigned char   e_shstrndx[2];      /* Section header string table index */
    } Elf64_External_Ehdr;
    
    /* Program header */
    
    typedef struct {
        unsigned char   p_type[4];      /* Identifies program segment type */
        unsigned char   p_offset[4];        /* Segment file offset */
        unsigned char   p_vaddr[4];     /* Segment virtual address */
        unsigned char   p_paddr[4];     /* Segment physical address */
        unsigned char   p_filesz[4];        /* Segment size in file */
        unsigned char   p_memsz[4];     /* Segment size in memory */
        unsigned char   p_flags[4];     /* Segment flags */
        unsigned char   p_align[4];     /* Segment alignment, file & memory */
    } Elf32_External_Phdr;
    
    typedef struct {
        unsigned char   p_type[4];      /* Identifies program segment type */
        unsigned char   p_flags[4];     /* Segment flags */
        unsigned char   p_offset[8];        /* Segment file offset */
        unsigned char   p_vaddr[8];     /* Segment virtual address */
        unsigned char   p_paddr[8];     /* Segment physical address */
        unsigned char   p_filesz[8];        /* Segment size in file */
        unsigned char   p_memsz[8];     /* Segment size in memory */
        unsigned char   p_align[8];     /* Segment alignment, file & memory */
    } Elf64_External_Phdr;
    
    /* Section header */
    
    typedef struct {
        unsigned char   sh_name[4];     /* Section name, index in string tbl */
        unsigned char   sh_type[4];     /* Type of section */
        unsigned char   sh_flags[4];        /* Miscellaneous section attributes */
        unsigned char   sh_addr[4];     /* Section virtual addr at execution */
        unsigned char   sh_offset[4];       /* Section file offset */
        unsigned char   sh_size[4];     /* Size of section in bytes */
        unsigned char   sh_link[4];     /* Index of another section */
        unsigned char   sh_info[4];     /* Additional section information */
        unsigned char   sh_addralign[4];    /* Section alignment */
        unsigned char   sh_entsize[4];      /* Entry size if section holds table */
    } Elf32_External_Shdr;
    
    typedef struct {
        unsigned char   sh_name[4];     /* Section name, index in string tbl */
        unsigned char   sh_type[4];     /* Type of section */
        unsigned char   sh_flags[8];        /* Miscellaneous section attributes */
        unsigned char   sh_addr[8];     /* Section virtual addr at execution */
        unsigned char   sh_offset[8];       /* Section file offset */
        unsigned char   sh_size[8];     /* Size of section in bytes */
        unsigned char   sh_link[4];     /* Index of another section */
        unsigned char   sh_info[4];     /* Additional section information */
        unsigned char   sh_addralign[8];    /* Section alignment */
        unsigned char   sh_entsize[8];      /* Entry size if section holds table */
    } Elf64_External_Shdr;
    
    /* Symbol table entry */
    
    typedef struct {
        unsigned char   st_name[4];     /* Symbol name, index in string tbl */
        unsigned char   st_value[4];        /* Value of the symbol */
        unsigned char   st_size[4];     /* Associated symbol size */
        unsigned char   st_info[1];     /* Type and binding attributes */
        unsigned char   st_other[1];        /* No defined meaning, 0 */
        unsigned char   st_shndx[2];        /* Associated section index */
    } Elf32_External_Sym;
    
    typedef struct {
        unsigned char   st_name[4];     /* Symbol name, index in string tbl */
        unsigned char   st_info[1];     /* Type and binding attributes */
        unsigned char   st_other[1];        /* No defined meaning, 0 */
        unsigned char   st_shndx[2];        /* Associated section index */
        unsigned char   st_value[8];        /* Value of the symbol */
        unsigned char   st_size[8];     /* Associated symbol size */
    } Elf64_External_Sym;
    
    typedef struct {
        unsigned char est_shndx[4];     /* Section index */
    } Elf_External_Sym_Shndx;
    
    /* Note segments */
    
    typedef struct {
        unsigned char   namesz[4];      /* Size of entry's owner string */
        unsigned char   descsz[4];      /* Size of the note descriptor */
        unsigned char   type[4];        /* Interpretation of the descriptor */
        char        name[1];        /* Start of the name+desc data */
    } Elf_External_Note;
    
    /* Relocation Entries */
    typedef struct {
        unsigned char r_offset[4];  /* Location at which to apply the action */
        unsigned char   r_info[4];  /* index and type of relocation */
    } Elf32_External_Rel;
    
    typedef struct {
        unsigned char r_offset[4];  /* Location at which to apply the action */
        unsigned char   r_info[4];  /* index and type of relocation */
        unsigned char   r_addend[4];    /* Constant addend used to compute value */
    } Elf32_External_Rela;
    
    typedef struct {
        unsigned char r_offset[8];  /* Location at which to apply the action */
        unsigned char   r_info[8];  /* index and type of relocation */
    } Elf64_External_Rel;
    
    typedef struct {
        unsigned char r_offset[8];  /* Location at which to apply the action */
        unsigned char   r_info[8];  /* index and type of relocation */
        unsigned char   r_addend[8];    /* Constant addend used to compute value */
    } Elf64_External_Rela;
    
    /* dynamic section structure */
    
    typedef struct {
        unsigned char   d_tag[4];       /* entry tag value */
        union {
            unsigned char   d_val[4];
            unsigned char   d_ptr[4];
        } d_un;
    } Elf32_External_Dyn;
    
    typedef struct {
        unsigned char   d_tag[8];       /* entry tag value */
        union {
            unsigned char   d_val[8];
            unsigned char   d_ptr[8];
        } d_un;
    } Elf64_External_Dyn;
    
    /* The version structures are currently size independent.  They are
       named without a 32 or 64.  If that ever changes, these structures
       will need to be renamed.  */
    
    /* This structure appears in a SHT_GNU_verdef section.  */
    
    typedef struct {
        unsigned char       vd_version[2];
        unsigned char       vd_flags[2];
        unsigned char       vd_ndx[2];
        unsigned char       vd_cnt[2];
        unsigned char       vd_hash[4];
        unsigned char       vd_aux[4];
        unsigned char       vd_next[4];
    } Elf_External_Verdef;
    
    /* This structure appears in a SHT_GNU_verdef section.  */
    
    typedef struct {
        unsigned char       vda_name[4];
        unsigned char       vda_next[4];
    } Elf_External_Verdaux;
    
    /* This structure appears in a SHT_GNU_verneed section.  */
    
    typedef struct {
        unsigned char       vn_version[2];
        unsigned char       vn_cnt[2];
        unsigned char       vn_file[4];
        unsigned char       vn_aux[4];
        unsigned char       vn_next[4];
    } Elf_External_Verneed;
    
    /* This structure appears in a SHT_GNU_verneed section.  */
    
    typedef struct {
        unsigned char       vna_hash[4];
        unsigned char       vna_flags[2];
        unsigned char       vna_other[2];
        unsigned char       vna_name[4];
        unsigned char       vna_next[4];
    } Elf_External_Vernaux;
    
    
    
    /* Structure for syminfo section.  */
    typedef struct
    {
        unsigned char       si_boundto[2];
        unsigned char       si_flags[2];
    } Elf_External_Syminfo;
    
    
    /* This structure appears on the stack and in NT_AUXV core file notes.  */
    typedef struct
    {
        unsigned char       a_type[4];
        unsigned char       a_val[4];
    } Elf32_External_Auxv;
    
    typedef struct
    {
        unsigned char       a_type[8];
        unsigned char       a_val[8];
    } Elf64_External_Auxv;
    
    /* Size of SHT_GROUP section entry.  */
    
    #define GRP_ENTRY_SIZE      4
    
    
    
    #define EI_NIDENT   16      /* Size of e_ident[] */
    
    typedef unsigned long bfd_vma;
    typedef unsigned long bfd_size_type;
    typedef unsigned long file_ptr;
    
    typedef struct elf_internal_ehdr {
        unsigned char       e_ident[EI_NIDENT]; /* ELF "magic number" */
        unsigned long       e_phoff;    /* Program header table file offset */
        unsigned long       e_shoff;    /* Section header table file offset */
        unsigned long       e_version;  /* Identifies object file version */
        unsigned long       e_flags;    /* Processor-specific flags */
        unsigned short  e_type;     /* Identifies object file type */
        unsigned short  e_machine;  /* Specifies required architecture */
        unsigned int        e_ehsize;   /* ELF header size in bytes */
        unsigned int        e_phentsize;    /* Program header table entry size */
        unsigned int        e_phnum;    /* Program header table entry count */
        unsigned int        e_shentsize;    /* Section header table entry size */
        unsigned int        e_shnum;    /* Section header table entry count */
        unsigned int        e_shstrndx; /* Section header string table index */
    } Elf_Internal_Ehdr;
    
    
    typedef struct elf_internal_shdr {
        unsigned int    sh_name;        /* Section name, index in string tbl */
        unsigned int    sh_type;        /* Type of section */
        bfd_vma sh_flags;       /* Miscellaneous section attributes */
        bfd_vma sh_addr;        /* Section virtual addr at execution */
        file_ptr    sh_offset;      /* Section file offset */
        bfd_size_type   sh_size;        /* Size of section in bytes */
        unsigned int    sh_link;        /* Index of another section */
        unsigned int    sh_info;        /* Additional section information */
        bfd_vma sh_addralign;       /* Section alignment */
        bfd_size_type   sh_entsize;     /* Entry size if section holds table */
    
        /* The internal rep also has some cached info associated with it. */
        unsigned char *contents;        /* Section contents.  */
    } Elf_Internal_Shdr;
    
    
    struct elf_internal_phdr {
        unsigned long   p_type;         /* Identifies program segment type */
        unsigned long   p_flags;        /* Segment flags */
        bfd_vma p_offset;       /* Segment file offset */
        bfd_vma p_vaddr;        /* Segment virtual address */
        bfd_vma p_paddr;        /* Segment physical address */
        bfd_vma p_filesz;       /* Segment size in file */
        bfd_vma p_memsz;        /* Segment size in memory */
        bfd_vma p_align;        /* Segment alignment, file & memory */
    };
    
    typedef struct elf_internal_phdr Elf_Internal_Phdr;
    
    #define BYTE_GET(field)    byte_get (field, sizeof (field))
    
    
    typedef unsigned long long dwarf_vma;
    typedef unsigned long long dwarf_size_type;
    
    struct elf_internal_sym {
        bfd_vma st_value;       /* Value of the symbol */
        bfd_vma st_size;        /* Associated symbol size */
        unsigned long   st_name;        /* Symbol name, index in string tbl */
        unsigned char   st_info;        /* Type and binding attributes */
        unsigned char   st_other;       /* Visibilty, and target specific */
        unsigned int  st_shndx;     /* Associated section index */
    };
    
    typedef struct elf_internal_sym Elf_Internal_Sym;
    
    
    #define GET_ELF_SYMBOLS(file, section)          \
      (is_32bit_elf ? get_32bit_elf_symbols (file, section) \
       : get_64bit_elf_symbols (file, section))
    
    
    
    #endif /* BASE_ELF_READER_EXTERNAL_H_ */
    
    • LibraryReader.h
    /**
    * @ name unpacker
    * @ author xiaobaiyey
    * @ email xiaobaiyey@outlook.com
    * @ time 2018/11/20 5:04 PM
    * @ class describe
    */
    
    #ifndef UNPACKER_LIBRARYREADER_H
    #define UNPACKER_LIBRARYREADER_H
    
    #include <string>
    #include "external.h"
    #include <map>
    #include <elf.h>
    
    enum LIBRARYTYPE {
        FROMFILE,
        FROMMEMORY
    };
    
    /**
     *so文件太大 个人感觉,在主线程中可能不能太适用
     * 具体没试过时间消耗
     */
    class LibraryReader {
    public:
        LibraryReader(const char *path, LIBRARYTYPE= FROMFILE);
    
        LibraryReader();
    
        unsigned long get_symbol_offset(const char *symbol);
    
        unsigned long get_symbol_address(const char *symbol);
    
        void print_symbol();
    
        static unsigned long get_so_address(const char *sopath);
    
        static uint32_t calculate_elf_hash(const char *name);
    
    private:
        LIBRARYTYPE librarytype;
        std::string path;
        int is_32bit_elf;
        bool elf_parse_pass;
        bool _lock = true;
        unsigned long min_vaddr = 0xffffffff;
        Elf_Internal_Ehdr elf_header;
        Elf_Internal_Phdr *program_headers;
        Elf_Internal_Shdr *section_headers;
        Elf_Internal_Shdr *symtab_shndx_hdr;
        std::map<std::string, bfd_vma> symbol_maps;
    private:
        //读取头文件
        bool read_elf_file_header(FILE *file);
    
        //读取program_headers
        bool process_program_headers(FILE *file);
    
        bool read_program_headers(FILE *file);
    
        bool get_32bit_program_headers(FILE *file, Elf_Internal_Phdr *program_headers);
    
        bool get_64bit_program_headers(FILE *file, Elf_Internal_Phdr *program_headers);
    
        //读取section_headers
        bool process_section_headers(FILE *file);
    
        bool get_32bit_section_headers(FILE *file, unsigned int num);
    
        bool get_64bit_section_headers(FILE *file, unsigned int num);
    
        //读取解析数据
        bool process_symbol_table(FILE *file);
    
        Elf_Internal_Sym *get_32bit_elf_symbols(FILE *file, Elf_Internal_Shdr *section);
    
        Elf_Internal_Sym *get_64bit_elf_symbols(FILE *file, Elf_Internal_Shdr *section);
    
    
    };
    
    
    #endif //UNPACKER_LIBRARYREADER_H
    
    
    • LibraryReader.cpp
    /**
    * @ name unpacker
    * @ author xiaobaiyey
    * @ email xiaobaiyey@outlook.com
    * @ time 2018/11/20 5:04 PM
    * @ class describe
    */
    
    #include "LibraryReader.h"
    #include <elf.h>
    #include <thread>
    
    #define DEBUG
    
    #ifdef DEBUG
    #define LOGI(...) printf(__VA_ARGS__);printf("\n")
    #define LOGW(...) printf(__VA_ARGS__);printf("\n")
    #define LOGE(...) printf(__VA_ARGS__);printf("\n")
    #define LOGD(...)
    #else
    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, __FUNCTION__, __VA_ARGS__))
    #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, __FUNCTION__, __VA_ARGS__))
    #define LOGD(...)
    #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, __FUNCTION__, __VA_ARGS__))
    #endif
    
    
    #define ABORT(...)
    
    
    static dwarf_vma byte_get_little_endian(unsigned char *field, int size) {
        switch (size) {
    
            case 1:
                return *field;
    
            case 2:
                return ((unsigned int) (field[0])) | (((unsigned int) (field[1])) << 8);
    
            case 4:
                return ((unsigned long) (field[0])) | (((unsigned long) (field[1])) << 8) |
                       (((unsigned long) (field[2])) << 16) | (((unsigned long) (field[3])) << 24);
    
            case 8:
                if (sizeof(dwarf_vma) == 8)
                    return ((dwarf_vma) (field[0])) | (((dwarf_vma) (field[1])) << 8) |
                           (((dwarf_vma) (field[2])) << 16) | (((dwarf_vma) (field[3])) << 24)
                           | (((dwarf_vma) (field[4])) << 32) | (((dwarf_vma) (field[5])) << 40) |
                           (((dwarf_vma) (field[6])) << 48) | (((dwarf_vma) (field[7])) << 56);
                else if (sizeof(dwarf_vma) == 4)
                    /* We want to extract data from an 8 byte wide field and
                     place it into a 4 byte wide field.  Since this is a little
                     endian source we can just use the 4 byte extraction code.  */
                    return ((unsigned long) (field[0])) | (((unsigned long) (field[1])) << 8) |
                           (((unsigned long) (field[2])) << 16)
                           | (((unsigned long) (field[3])) << 24);
                else {
                    ABORT("error size (%d)", size);
                }
    
            default:
                ABORT("error size (%d)", size);
        }
        return *field;
    }
    
    static dwarf_vma byte_get_big_endian(unsigned char *field, int size) {
        switch (size) {
            case 1:
                return *field;
    
            case 2:
                return ((unsigned int) (field[1])) | (((int) (field[0])) << 8);
    
            case 4:
                return ((unsigned long) (field[3])) | (((unsigned long) (field[2])) << 8) |
                       (((unsigned long) (field[1])) << 16) | (((unsigned long) (field[0])) << 24);
    
            case 8:
                if (sizeof(dwarf_vma) == 8)
                    return ((dwarf_vma) (field[7])) | (((dwarf_vma) (field[6])) << 8) |
                           (((dwarf_vma) (field[5])) << 16) | (((dwarf_vma) (field[4])) << 24)
                           | (((dwarf_vma) (field[3])) << 32) | (((dwarf_vma) (field[2])) << 40) |
                           (((dwarf_vma) (field[1])) << 48) | (((dwarf_vma) (field[0])) << 56);
                else if (sizeof(dwarf_vma) == 4) {
                    /* Although we are extracing data from an 8 byte wide field,
                     we are returning only 4 bytes of data.  */
                    field += 4;
                    return ((unsigned long) (field[3])) | (((unsigned long) (field[2])) << 8) |
                           (((unsigned long) (field[1])) << 16)
                           | (((unsigned long) (field[0])) << 24);
                } else {
                    ABORT("error size (%d)", size);
                }
    
            default:
                //error (_("Unhandled data length: %d\n"), size);
                ABORT("error size (%d)", size);
        }
        return *field;
    }
    
    static void *
    get_data(void *var, FILE *file, long offset, size_t size, size_t nmemb, const char *reason) {
        void *mvar;
    
        if (size == 0 || nmemb == 0)
            return NULL;
    
        if (fseek(file, offset, SEEK_SET)) {
            LOGE("Unable to seek to 0x%lx for %s\n", (unsigned long) offset, reason);
            return NULL;
        }
    
        mvar = var;
        if (mvar == NULL) {
            /* Check for overflow.  */
            if (nmemb < (~(size_t) 0 - 1) / size)
                /* + 1 so that we can '\0' terminate invalid string table sections.  */
                mvar = malloc(size * nmemb + 1);
    
            if (mvar == NULL) {
                LOGE("Out of memory allocating 0x%lx bytes for %s\n", (unsigned long) (size * nmemb),
                     reason);
                return NULL;
            }
    
            ((char *) mvar)[size * nmemb] = '\0';
        }
    
        if (fread(mvar, size, nmemb, file) != nmemb) {
            LOGE("Unable to read in 0x%lx bytes of %s\n", (unsigned long) (size * nmemb), reason);
            if (mvar != var)
                free(mvar);
            return NULL;
        }
    
        return mvar;
    }
    
    
    dwarf_vma (*byte_get)(unsigned char *, int);
    
    
    LibraryReader::LibraryReader(const char *path, LIBRARYTYPE librarytype) {
        this->librarytype = librarytype;
        this->path = path;
        if (this->librarytype == FROMFILE) {
            FILE *file = fopen(path, "rb");
            if (file == nullptr) {
                LOGE("read %s fail", path);
                elf_parse_pass = false;
                return;
            }
            LOGD("read file over");
            if (!read_elf_file_header(file)) {
                LOGE("read_elf_file_header fail");
                elf_parse_pass = false;
            }
            LOGD("read_elf_file_header over");
            if (!process_program_headers(file)) {
                LOGE("process_program_headers fail");
                elf_parse_pass = false;
            }
            LOGD("process_program_headers over");
            if (!process_section_headers(file)) {
                LOGE("process_section_headers fail");
                elf_parse_pass = false;
            }
            LOGD("process_section_headers over");
            if (!process_symbol_table(file)) {
                LOGE("process_symbol_table fail");
                elf_parse_pass = false;
            }
            LOGD("process_symbol_table over");
            fclose(file);
            elf_parse_pass = true;
        } else {
    
        }
    }
    
    bool LibraryReader::read_elf_file_header(FILE *file) {
        unsigned char e_ident[EI_NIDENT];
        if (fread(e_ident, EI_NIDENT, 1, file) != 1) {
            LOGE("read EI_NIDENT fail");
            return false;
        }
    
        switch (e_ident[EI_DATA]) {
            default: /* fall through */
            case ELFDATANONE: /* fall through */
            case ELFDATA2LSB:
                byte_get = byte_get_little_endian;
                break;
            case ELFDATA2MSB:
                byte_get = byte_get_big_endian;
                break;
        }
        is_32bit_elf = (e_ident[EI_CLASS] != ELFCLASS64);
        if (is_32bit_elf) {
            Elf32_External_Ehdr ehdr32;
            if (fread(ehdr32.e_type, sizeof(ehdr32) - EI_NIDENT, 1, file) != 1) {
                LOGE("read ehdr32.e_type fail");
                return false;
            }
            elf_header.e_type = BYTE_GET(ehdr32.e_type);
            elf_header.e_machine = BYTE_GET(ehdr32.e_machine);
            elf_header.e_version = BYTE_GET(ehdr32.e_version);
            elf_header.e_phoff = BYTE_GET(ehdr32.e_phoff);
            elf_header.e_shoff = BYTE_GET(ehdr32.e_shoff);
            elf_header.e_flags = BYTE_GET(ehdr32.e_flags);
            elf_header.e_ehsize = BYTE_GET(ehdr32.e_ehsize);
            elf_header.e_phentsize = BYTE_GET(ehdr32.e_phentsize);
            elf_header.e_phnum = BYTE_GET(ehdr32.e_phnum);
            elf_header.e_shentsize = BYTE_GET(ehdr32.e_shentsize);
            elf_header.e_shnum = BYTE_GET(ehdr32.e_shnum);
            elf_header.e_shstrndx = BYTE_GET(ehdr32.e_shstrndx);
    
        } else {
            Elf64_External_Ehdr ehdr64;
            if (fread(ehdr64.e_type, sizeof(ehdr64) - EI_NIDENT, 1, file) != 1) {
                LOGE("read ehdr64.e_type fail");
                return false;
            }
            elf_header.e_type = BYTE_GET(ehdr64.e_type);
            elf_header.e_machine = BYTE_GET(ehdr64.e_machine);
            elf_header.e_version = BYTE_GET(ehdr64.e_version);
            elf_header.e_phoff = BYTE_GET(ehdr64.e_phoff);
            elf_header.e_shoff = BYTE_GET(ehdr64.e_shoff);
            elf_header.e_flags = BYTE_GET(ehdr64.e_flags);
            elf_header.e_ehsize = BYTE_GET(ehdr64.e_ehsize);
            elf_header.e_phentsize = BYTE_GET(ehdr64.e_phentsize);
            elf_header.e_phnum = BYTE_GET(ehdr64.e_phnum);
            elf_header.e_shentsize = BYTE_GET(ehdr64.e_shentsize);
            elf_header.e_shnum = BYTE_GET(ehdr64.e_shnum);
            elf_header.e_shstrndx = BYTE_GET(ehdr64.e_shstrndx);
        }
        return true;
    }
    
    bool LibraryReader::read_program_headers(FILE *file) {
        Elf_Internal_Phdr *phdrs;
        /* Check cache of prior read.  */
        if (program_headers != NULL)
            return true;
    
        phdrs = (Elf_Internal_Phdr *) malloc(elf_header.e_phnum * sizeof(Elf_Internal_Phdr));
    
        if (phdrs == NULL) {
            return false;
        }
    
        if (is_32bit_elf ? get_32bit_program_headers(file, phdrs) : get_64bit_program_headers(file,
                                                                                              phdrs)) {
            program_headers = phdrs;
            return true;
        }
    
        free(phdrs);
        return false;
    }
    
    bool LibraryReader::get_32bit_program_headers(FILE *file, Elf_Internal_Phdr *program_headers) {
        Elf32_External_Phdr *phdrs;
        Elf32_External_Phdr *external;
        Elf_Internal_Phdr *internal;
        unsigned int i;
    
        phdrs = (Elf32_External_Phdr *) get_data(NULL, file, elf_header.e_phoff, elf_header.e_phentsize,
                                                 elf_header.e_phnum, "program headers");
    
        if (!phdrs)
            return false;
    
        for (i = 0, internal = program_headers, external = phdrs;
             i < elf_header.e_phnum; i++, internal++, external++) {
            internal->p_type = BYTE_GET(external->p_type);
            internal->p_offset = BYTE_GET(external->p_offset);
            internal->p_vaddr = BYTE_GET(external->p_vaddr);
            internal->p_paddr = BYTE_GET(external->p_paddr);
            internal->p_filesz = BYTE_GET(external->p_filesz);
            internal->p_memsz = BYTE_GET(external->p_memsz);
            internal->p_flags = BYTE_GET(external->p_flags);
            internal->p_align = BYTE_GET(external->p_align);
        }
    
        free(phdrs);
    
        return true;
    }
    
    bool LibraryReader::get_64bit_program_headers(FILE *file, Elf_Internal_Phdr *program_headers) {
        Elf64_External_Phdr *phdrs;
        Elf64_External_Phdr *external;
        Elf_Internal_Phdr *internal;
        unsigned int i;
    
        phdrs = (Elf64_External_Phdr *) get_data(NULL, file, elf_header.e_phoff, elf_header.e_phentsize,
                                                 elf_header.e_phnum, "program headers");
        if (!phdrs)
            return false;
    
        for (i = 0, internal = program_headers, external = phdrs;
             i < elf_header.e_phnum; i++, internal++, external++) {
            internal->p_type = BYTE_GET(external->p_type);
            internal->p_flags = BYTE_GET(external->p_flags);
            internal->p_offset = BYTE_GET(external->p_offset);
            internal->p_vaddr = BYTE_GET(external->p_vaddr);
            internal->p_paddr = BYTE_GET(external->p_paddr);
            internal->p_filesz = BYTE_GET(external->p_filesz);
            internal->p_memsz = BYTE_GET(external->p_memsz);
            internal->p_align = BYTE_GET(external->p_align);
        }
    
        free(phdrs);
    
        return true;
    }
    
    bool LibraryReader::process_program_headers(FILE *file) {
        Elf_Internal_Phdr *segment;
        unsigned int i;
    
        if (elf_header.e_phnum == 0) {
            return 0;
        }
    
        if (!read_program_headers(file))
            return false;
    
        for (i = 0, segment = program_headers; i < elf_header.e_phnum; i++, segment++) {
    
            if (segment->p_type == PT_LOAD) {
    
                if ((unsigned long) segment->p_vaddr < min_vaddr) {
    
                    min_vaddr = (unsigned long) segment->p_vaddr;
                }
            }
    
        }
    
        return true;
    }
    
    bool LibraryReader::get_32bit_section_headers(FILE *file, unsigned int num) {
        Elf32_External_Shdr *shdrs;
        Elf_Internal_Shdr *internal;
        unsigned int i;
    
        shdrs = (Elf32_External_Shdr *) get_data(NULL, file, elf_header.e_shoff, elf_header.e_shentsize,
                                                 num, "section headers");
        if (!shdrs)
            return false;
    
        section_headers = (Elf_Internal_Shdr *) malloc(num * sizeof(Elf_Internal_Shdr));
    
        if (section_headers == NULL) {
            LOGE("Out of memory\n");
            return false;
        }
    
        for (i = 0, internal = section_headers; i < num; i++, internal++) {
            internal->sh_name = BYTE_GET(shdrs[i].sh_name);
            internal->sh_type = BYTE_GET(shdrs[i].sh_type);
            internal->sh_flags = BYTE_GET(shdrs[i].sh_flags);
            internal->sh_addr = BYTE_GET(shdrs[i].sh_addr);
            internal->sh_offset = BYTE_GET(shdrs[i].sh_offset);
            internal->sh_size = BYTE_GET(shdrs[i].sh_size);
            internal->sh_link = BYTE_GET(shdrs[i].sh_link);
            internal->sh_info = BYTE_GET(shdrs[i].sh_info);
            internal->sh_addralign = BYTE_GET(shdrs[i].sh_addralign);
            internal->sh_entsize = BYTE_GET(shdrs[i].sh_entsize);
        }
    
        free(shdrs);
    
        return true;
    }
    
    bool LibraryReader::get_64bit_section_headers(FILE *file, unsigned int num) {
        Elf64_External_Shdr *shdrs;
        Elf_Internal_Shdr *internal;
        unsigned int i;
    
        shdrs = (Elf64_External_Shdr *) get_data(NULL, file, elf_header.e_shoff, elf_header.e_shentsize,
                                                 num, "section headers");
        if (!shdrs)
            return false;
    
        section_headers = (Elf_Internal_Shdr *) malloc(num * sizeof(Elf_Internal_Shdr));
    
        if (section_headers == NULL) {
            LOGE("Out of memory\n");
            return false;
        }
    
        for (i = 0, internal = section_headers; i < num; i++, internal++) {
            internal->sh_name = BYTE_GET(shdrs[i].sh_name);
            internal->sh_type = BYTE_GET(shdrs[i].sh_type);
            internal->sh_flags = BYTE_GET(shdrs[i].sh_flags);
            internal->sh_addr = BYTE_GET(shdrs[i].sh_addr);
            internal->sh_size = BYTE_GET(shdrs[i].sh_size);
            internal->sh_entsize = BYTE_GET(shdrs[i].sh_entsize);
            internal->sh_link = BYTE_GET(shdrs[i].sh_link);
            internal->sh_info = BYTE_GET(shdrs[i].sh_info);
            internal->sh_offset = BYTE_GET(shdrs[i].sh_offset);
            internal->sh_addralign = BYTE_GET(shdrs[i].sh_addralign);
        }
    
        free(shdrs);
    
        return true;
    }
    
    bool LibraryReader::process_section_headers(FILE *file) {
        if (elf_header.e_shoff) {
            /* There may be some extensions in the first section header.  Don't
             bomb if we can't read it.  */
            if (is_32bit_elf)
                return get_32bit_section_headers(file, elf_header.e_shnum);
            else
                return get_64bit_section_headers(file, elf_header.e_shnum);
        }
    
        return false;
    }
    
    
    bool LibraryReader::process_symbol_table(FILE *file) {
        unsigned int i;
        Elf_Internal_Shdr *section;
        unsigned long result = 0;
        for (i = 0, section = section_headers; i < elf_header.e_shnum; i++, section++) {
            unsigned int si;
            char *strtab = NULL;
            unsigned long int strtab_size = 0;
            Elf_Internal_Sym *symtab;
            Elf_Internal_Sym *psym;
    
            if (section->sh_type != SHT_SYMTAB && section->sh_type != SHT_DYNSYM) {
                continue;
            }
    
            symtab = GET_ELF_SYMBOLS(file, section);
    
            if (symtab == NULL)
                continue;
    
    
            if (section->sh_link == elf_header.e_shstrndx) {
    
                continue;
            } else if (section->sh_link < elf_header.e_shnum) {
    
                Elf_Internal_Shdr *string_sec;
    
                string_sec = section_headers + section->sh_link;
    
                strtab = (char *) get_data(NULL, file, string_sec->sh_offset, 1, string_sec->sh_size,
                                           "string table");
                strtab_size = strtab != NULL ? string_sec->sh_size : 0;
            }
    
            int number = section->sh_size / section->sh_entsize;
            for (si = 0, psym = symtab; si < number; si++, psym++) {
    
                const char *name = psym->st_name < strtab_size ? strtab + psym->st_name : "<corrupt>";
                if (name != nullptr && strlen(name) > 0 && psym->st_value != 0) {
                    symbol_maps.insert(std::make_pair(std::string(name), psym->st_value));
                }
            }
            free(symtab);
        }
        return true;
    }
    
    Elf_Internal_Sym *LibraryReader::get_32bit_elf_symbols(FILE *file, Elf_Internal_Shdr *section) {
        unsigned long number;
        Elf32_External_Sym *esyms;
        Elf_External_Sym_Shndx *shndx;
        Elf_Internal_Sym *isyms;
        Elf_Internal_Sym *psym;
        unsigned int j;
    
        esyms = (Elf32_External_Sym *) get_data(NULL, file, section->sh_offset, 1, section->sh_size,
                                                "symbols");
        if (!esyms)
            return NULL;
    
        shndx = NULL;
        if (symtab_shndx_hdr != NULL &&
            (symtab_shndx_hdr->sh_link == (unsigned long) (section - section_headers))) {
            shndx = (Elf_External_Sym_Shndx *) get_data(NULL, file, symtab_shndx_hdr->sh_offset, 1,
                                                        symtab_shndx_hdr->sh_size, "symtab shndx");
            if (!shndx) {
                free(esyms);
                return NULL;
            }
        }
    
        number = section->sh_size / section->sh_entsize;
        isyms = (Elf_Internal_Sym *) malloc(number * sizeof(Elf_Internal_Sym));
    
        if (isyms == NULL) {
            LOGE("Out of memory\n");
            if (shndx)
                free(shndx);
            free(esyms);
            return NULL;
        }
    
        for (j = 0, psym = isyms; j < number; j++, psym++) {
            psym->st_name = BYTE_GET(esyms[j].st_name);
            psym->st_value = BYTE_GET(esyms[j].st_value);
            psym->st_size = BYTE_GET(esyms[j].st_size);
            psym->st_shndx = BYTE_GET(esyms[j].st_shndx);
            if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
                psym->st_shndx = byte_get((unsigned char *) &shndx[j], sizeof(shndx[j]));
            else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
                psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
            psym->st_info = BYTE_GET(esyms[j].st_info);
            psym->st_other = BYTE_GET(esyms[j].st_other);
        }
    
        if (shndx)
            free(shndx);
        free(esyms);
        return isyms;
    }
    
    Elf_Internal_Sym *LibraryReader::get_64bit_elf_symbols(FILE *file, Elf_Internal_Shdr *section) {
        unsigned long number;
        Elf64_External_Sym *esyms;
        Elf_External_Sym_Shndx *shndx;
        Elf_Internal_Sym *isyms;
        Elf_Internal_Sym *psym;
        unsigned int j;
    
        esyms = (Elf64_External_Sym *) get_data(NULL, file, section->sh_offset, 1, section->sh_size,
                                                "symbols");
        if (!esyms)
            return NULL;
    
        shndx = NULL;
        if (symtab_shndx_hdr != NULL &&
            (symtab_shndx_hdr->sh_link == (unsigned long) (section - section_headers))) {
            shndx = (Elf_External_Sym_Shndx *) get_data(NULL, file, symtab_shndx_hdr->sh_offset, 1,
                                                        symtab_shndx_hdr->sh_size, "symtab shndx");
            if (!shndx) {
                free(esyms);
                return NULL;
            }
        }
    
        number = section->sh_size / section->sh_entsize;
        isyms = (Elf_Internal_Sym *) malloc(number * sizeof(Elf_Internal_Sym));
    
        if (isyms == NULL) {
            LOGE("Out of memory\n");
            if (shndx)
                free(shndx);
            free(esyms);
            return NULL;
        }
    
        for (j = 0, psym = isyms; j < number; j++, psym++) {
            psym->st_name = BYTE_GET(esyms[j].st_name);
            psym->st_info = BYTE_GET(esyms[j].st_info);
            psym->st_other = BYTE_GET(esyms[j].st_other);
            psym->st_shndx = BYTE_GET(esyms[j].st_shndx);
            if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
                psym->st_shndx = byte_get((unsigned char *) &shndx[j], sizeof(shndx[j]));
            else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
                psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
            psym->st_value = BYTE_GET(esyms[j].st_value);
            psym->st_size = BYTE_GET(esyms[j].st_size);
        }
    
        if (shndx)
            free(shndx);
        free(esyms);
    
        return isyms;
    }
    
    void LibraryReader::print_symbol() {
        if (!elf_parse_pass) {
            LOGE("elf_parse_pass false");
            return;
        }
        std::map<std::string, bfd_vma>::iterator iterator;
        for (iterator = symbol_maps.begin(); iterator != symbol_maps.end(); iterator++) {
            std::string symbol = iterator->first;
            bfd_vma bfd_vma1 = iterator->second;
            LOGI("symbol:%s offset:0x%x", symbol.c_str(), bfd_vma1);
        }
    }
    
    
    unsigned long LibraryReader::get_symbol_offset(const char *symbol) {
        if (!elf_parse_pass) {
            LOGE("elf_parse_pass false");
            return 0;
        }
        // clock_t start =clock();
        std::string str(symbol);
        auto it = symbol_maps.find(str);
        if (it == symbol_maps.end()) {
            return 0;
        }
    
        /* clock_t end = clock();
         clock_t duration = (end - start);
         //LOGI( "%ld seconds", duration );*/
        return it->second;
    
    }
    
    LibraryReader::LibraryReader() {
    
    }
    
    unsigned long LibraryReader::get_so_address(const char *sopath) {
    
        char line[1024] = {0};
        FILE *fp;
        unsigned long addr = 0;
        char *pch;
        if ((fp = fopen("/proc/self/maps", "r")) == NULL) {
            LOGE("/proc/self/maps open failed (%s)", strerror(errno));
            return 0;
        }
        while (fgets(line, sizeof(line), fp)) {
            if (strstr(line, sopath)) {
                pch = strtok(line, "-");
                addr = strtoul(pch, NULL, 16);
                break;
            }
        }
        fclose(fp);
        return addr;
    }
    
    unsigned long LibraryReader::get_symbol_address(const char *symbol) {
        if (!elf_parse_pass) {
            LOGE("elf_parse_pass false");
            return 0;
        }
        // clock_t start =clock();
        std::string str(symbol);
        auto it = symbol_maps.find(str);
        if (it == symbol_maps.end()) {
            return 0;
        }
    
        /* clock_t end = clock();
         clock_t duration = (end - start);
         //LOGI( "%ld seconds", duration );*/
        return it->second + get_so_address(this->path.c_str());
    }
    
    uint32_t LibraryReader::calculate_elf_hash(const char *name) {
        const uint8_t *name_bytes = reinterpret_cast<const uint8_t *>(name);
        uint32_t h = 0, g;
    
        while (*name_bytes) {
            h = (h << 4) + *name_bytes++;
            g = h & 0xf0000000;
            h ^= g;
            h ^= g >> 24;
        }
        return h;
    }
    
    

    相关文章

      网友评论

          本文标题:获取android bin、so文件符号偏移或者内存地址

          本文链接:https://www.haomeiwen.com/subject/xryhqqtx.html