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

代码

直接晒代码

  • 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 [email protected]
* @ time 2018/11/20 5:04 PM
* @ class describe
*/

#ifndef UNPACKER_LIBRARYREADER_H
#define UNPACKER_LIBRARYREADER_H

#include 
#include "external.h"
#include 
#include 

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 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 [email protected]
* @ time 2018/11/20 5:04 PM
* @ class describe
*/

#include "LibraryReader.h"
#include 
#include 

#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 : "";
            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::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(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文件符号偏移或者内存地址)