Android Travel Notes (2) --- ELF Executable File Format

Source: Internet
Author: User

ELF is a Unix-like system. Of course, it also includes the executable file formats (also including. so and. o files) on the Android system ). It can be understood as the exe or dll file format on the Android system. Understanding the ELF File specifications is a prerequisite for understanding process loading and execution on the Android system. Next, let's take a step-by-step look at what ELF is like (mainly in Arm 32 ELF format )! Of course, there have been a lot of ELF introductions on the Internet. The best manual is to read the ELF official manual directly. Here I will just give a programmatic introduction to the ELF File and go straight to the topic, for example. GOT. PLT, R_Arm_Jump_Slot, R_Arm_Relative, and so on.

Let's take libc. so as an example. first look at the ELF file generated through arm-linux-androideabi-readelf. It's very long. Let's take a look at the segment:


Let's pick a few interesting fields to illustrate.

First, ELF Header: As the name implies, this is the "Header" that all ELF files have. It contains the "programmatic" information of the ELF File. For example, "Machine" indicates the current CPU architecture. In this example, It is arm, and "Start of Sections" indicates "Section) the number of offset bytes of the header.

Section Headers lists all Section information contained in the file. For example,. data indicates the data zone and. text indicates the code zone. The following figure provides an overview of the ELF File Format: <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHA + pgltzybzcm9 "http://www.2cto.com/uploadfile/Collfiles/20140609/20140609091245187.jpg" alt = "\">

The static view is on the left, while the link loading view is on the right, both of which are in the same file status.

/* ELF Header */typedef struct elfhdr {unsigned chare_ident[EI_NIDENT]; /* ELF Identification */Elf32_Halfe_type;/* object file type */Elf32_Halfe_machine;/* machine */Elf32_Worde_version;/* object file version */Elf32_Addre_entry;/* virtual entry point */Elf32_Offe_phoff;/* program header table offset */Elf32_Offe_shoff;/* section header table offset */Elf32_Worde_flags;/* processor-specific flags */Elf32_Halfe_ehsize;/* ELF header size */Elf32_Halfe_phentsize;/* program header entry size */Elf32_Halfe_phnum;/* number of program header entries */Elf32_Halfe_shentsize;/* section header entry size */Elf32_Halfe_shnum;/* number of section header entries */Elf32_Halfe_shstrndx;/* section header table's "section    header string table" entry offset */} Elf32_Ehdr;

In this example, e_shoff is the Start of section headers we see above, while e_shstrndx refers to the starting index position of the Sections name String in the String Table (also a Section.

Next, let's look at the definition of Section Header:

/* Section Header */typedef struct {Elf32_Wordsh_name;/* name - index into section header   string table section */Elf32_Wordsh_type;/* type */Elf32_Wordsh_flags;/* flags */Elf32_Addrsh_addr;/* address */Elf32_Offsh_offset;/* file offset */Elf32_Wordsh_size;/* section size */Elf32_Wordsh_link;/* section header table index link */Elf32_Wordsh_info;/* extra information */Elf32_Wordsh_addralign;/* address alignment */Elf32_Wordsh_entsize;/* section entry size */} Elf32_Shdr;
We need to take a detailed look at this, which can be used later:

Field:

Sh_name: As the name implies, Section name, type: Elf32_Word. It actually points to the index value of the string table.

Sh_flags: type .. The dynsym type is DYNSYM, which indicates that the section contains the symbols for dynamic links.

Sh_addr: address. This section is in memory and is offset from the base address

Sh_offset: offset. The Byte offset from this section to the file header.

Sh_size: partition size

Sh_link: indicates the section index with link relationships with the current section. Different types of sections have different interpretations. In the preceding libc. so, the link of. dynsym is 2, while 2 is the index of. dynstr, which is actually the index of the dynamic symbol string table.

Sh_info: Additional information

Sh_addralign: address alignment of the Section

Sh_entsize: The size (bytes) of the partition)

There seems to be a lot of mess above. In fact, just remember one thing: all this information is the "reference table" That linker uses when loading elf ".

In old habits, we directly write a small program that elf reads to verify our understanding.

/* *  elf32 reader *  Created on: 2014-6 *  Author: Chris.Z */#include 
 
  #include 
  
   #include 
   
    #include 
    
     #include 
     
      #ifdef __x86_64    #define Elf_Ehdr Elf64_Ehdr    #define Elf_Shdr Elf64_Shdr    #define Elf_Sym Elf64_Sym    #define Elf_Rel Elf64_Rela    #define ELF_R_SYM ELF64_R_SYM    #define REL_DYN ".rela.dyn"    #define REL_PLT ".rela.plt"#else    #define Elf_Ehdr Elf32_Ehdr    #define Elf_Shdr Elf32_Shdr    #define Elf_Sym Elf32_Sym    #define Elf_Rel Elf32_Rel    #define ELF_R_SYM ELF32_R_SYM    #define REL_DYN ".rel.dyn"    #define REL_PLT ".rel.plt"#endif#define LOG(...) printf(__VA_ARGS__);/** * lookup the start address of a specific module(libc.so...) within current process * return 0 if FAILED */static uint32_t get_module_base(pid_t pid, const char *module_path) {FILE *fp = NULL;char *pch = NULL;char filename[32];char line[512];uint32_t addr = 0;LOG("[+] get libc base...\n");if (pid < 0)snprintf(filename, sizeof(filename), "/proc/self/maps");elsesnprintf(filename, sizeof(filename), "/proc/%d/maps", pid);if ((fp = fopen(filename, "r")) == NULL) {LOG("[-]open %s failed!", filename);return 0;}while (fgets(line, sizeof(line), fp)) {if (strstr(line, module_path)) {pch = strtok(line, "-");addr = strtoul(pch, NULL, 16);break;}}fclose(fp);LOG("[+] libc base:0x%x...\n",addr);return addr;}/** * read the elf header * return 0 if SUCCESS */static int read_header(int d, Elf_Ehdr **header)//read elf header structure{    *header = (Elf_Ehdr *)malloc(sizeof(Elf_Ehdr));    if (lseek(d, 0, SEEK_SET) < 0)//seek to the begin of file    {        free(*header);        return errno;    }    if (read(d, *header, sizeof(Elf_Ehdr)) <= 0)//read from begin,read sizof(Elf_Ehdr) bytes ==> header    {        free(*header);        return errno = EINVAL;    }    return 0;}/** * read the section header * return 0 if SUCCESS */static int read_section_table(int d, Elf_Ehdr const *header, Elf_Shdr **table)//read elf header,find section header base address{    size_t size;    if (NULL == header)        return EINVAL;    size = header->e_shnum * sizeof(Elf_Shdr);//section numbers and total size    *table = (Elf_Shdr *)malloc(size);    if (lseek(d, header->e_shoff, SEEK_SET) < 0)//point to section header,offset 0    {        free(*table);        return errno;    }    if (read(d, *table, size) <= 0)//read section header structure to **table    {        free(*table);        return errno = EINVAL;    }    return 0;}/** * read the string section table * return 0 if SUCCESS */static int read_string_table(int d, Elf_Shdr const *section, char const **strings){    if (NULL == section)//section == > .dynstr section        return EINVAL;    *strings = (char const *)malloc(section->sh_size);    if (lseek(d, section->sh_offset, SEEK_SET) < 0)    {        free((void *)*strings);        return errno;    }    if (read(d, (char *)*strings, section->sh_size) <= 0)//strings include all strings in .dynstr sections    {        free((void *)*strings);        return errno = EINVAL;    }    return 0;}int main(){    LOG("[+]Arm ELF32 reader...\n");    uint32_t lic_base = get_module_base(-1,"/system/lib/libc.so");    int descriptor = open("/system/lib/libc.so", O_RDONLY);//open libc.so,and return the handle    Elf_Ehdr *header = NULL;//elf header    Elf_Shdr *section_header = NULL;//section header array ptr    char const *strings = NULL;//string table ptr    read_header(descriptor,&header);    LOG("[+]libc.so elf header:\n");    LOG("[+]e_ident[EI_NIDENT]:   %s\n",header->e_ident);    LOG("[+]e_type:%d(ET_DYN:%d,DYN (Shared object file))\n",header->e_type,ET_DYN);    LOG("[+]e_machine:%d(EM_ARM:%d,Advanced RISC Machines)\n",header->e_machine,EM_ARM);    LOG("[+]e_shoff:%d bytes\n",header->e_shoff);    LOG("[+]libc.so section header:\n");    read_section_table(descriptor,header,§ion_header);    read_string_table(descriptor,§ion_header[header->e_shstrndx], &strings);//header->e_shstrndx ==>the index of string section header in section headers    int i = 0;    for(i = 0;i
      
       e_shnum;++i) { LOG("Section[%d] name:%s,type:%d,addr:0x%x,offset:0x%x,size:%dbytes,etc...\n",i,&strings[section_header[i].sh_name],section_header[i].sh_type,section_header[i].sh_addr,section_header[i].sh_offset,section_header[i].sh_size); } close(descriptor); return 0;}
      
     
    
   
  
 

Let's take a look at the running results:



Let's take a look at the results generated by readelf. Indeed, Enjoy IT!

Reprinted please indicate the source: Life Show

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.