ELF格式解析库之基本数据类型

ELF格式简介

ELF是现代linux/unix流行的程序可执行链接格式,它有官方定义文档,具体的资料在Tool Interface Standard Executable and Linking Format Specification version 1.2 有其对应的详细描述。我在这里不会讲述关于这个格式详细描述,如果我叙述的有什么不对的地方,欢迎指正出来。当然一切都以官方的参考文档为标准,建议您在阅读本文的时候,手边最好有一份官方定义文档参考。

ELF由三个头表描述:ELF header,section header,programer (segment) header。

简单的说,ELF格式描述的是编译生成的二进制可链接文件,可共享库文件,以及可执行文件的数据组织形式,或者说内存组织形式。我们知道,程序可以分为从编译生成的静态内存分布和动态链接执行两个方面来理解,ELF格式也是基于此来构成两个基本视图的:section view和 segment view;前者描述了静态的视图,对应的详细描述定义在section header里,后者则描述了动态链接执行的视图,对应的详细描述定义在segment header。可以说ELF确实是一个抽象良好的格式描述形式,因为这样做简化了格式描述的复杂性,也节省了在内核中管理和描述格式的内存开销。这也可以理解到为什么现代unix/linux流行逐渐放弃a.out格式和COEFF格式,而是采用ELF来作为二进制程序文件的描述的原因。

另外不同的计算机体系结构在字长,CPU架构,大小端等方面是有明显的差异。ELF格式的二进制文件为了在不同的体系结构中正确的被内核理解,所以它会在ELF header 中的16字节长的e_indent数组详细描述该二进制文件对应的体系结构,包括对应的字长,CPU架构,大小端等。我们知道系统的字长直接在系统位数反应出来;所以,为了兼容不同位数的系统,我们对于每一个视图的详细描述都定义了两种字长的结构。当然,在ELF header 还详细描述了其它的信息,比如程序的入口点e_entry, 节表(section header)的文件头偏移等等。

从通俗的角度来说,ELF header 是整个文件的总管家,对程序数据组织形式的理解都是从它开始的,通过它再转到其它对应信息的二管家,例如:segment header,section header,然后层层深入,最后到达想要的信息地址。

在这里我只是给出我自己关于ELF header/section header/segment header 的代码,不详细解释定义的结构中各个字段的意思,官方文档里边已经描述的很详细了,请自己去那里仔细的阅读,它可以很好的解释您的疑问。

ELF header

   1:  typedef struct
   2:  {
   3:    unsigned char    e_ident[EI_NIDENT];    /* Magic number and other info */
   4:    Elf32_Half    e_type;            /* Object file type */
   5:    Elf32_Half    e_machine;        /* Architecture */
   6:    Elf32_Word    e_version;        /* Object file version */
   7:    Elf32_Addr    e_entry;        /* Entry point virtual address */
   8:    Elf32_Off    e_phoff;        /* Program header table file offset */
   9:    Elf32_Off    e_shoff;        /* Section header table file offset */
  10:    Elf32_Word    e_flags;        /* Processor-specific flags */
  11:    Elf32_Half    e_ehsize;        /* ELF header size in bytes */
  12:    Elf32_Half    e_phentsize;        /* Program header table entry size */
  13:    Elf32_Half    e_phnum;        /* Program header table entry count */
  14:    Elf32_Half    e_shentsize;
  15:    Elf32_Half    e_shnum;
  16:    Elf32_Half    e_shstrndx;
  17:  } SEF_ELFHEADER_32;
  18:   
  19:  typedef struct
  20:  {
  21:    unsigned char    e_ident[EI_NIDENT];    /* Magic number and other info */
  22:    Elf64_Half    e_type;            /* Object file type */
  23:    Elf64_Half    e_machine;        /* Architecture */
  24:    Elf64_Word    e_version;        /* Object file version */
  25:    Elf64_Addr    e_entry;        /* Entry point virtual address */
  26:    Elf64_Off    e_phoff;        /* Program header table file offset */
  27:    Elf64_Off    e_shoff;        /* Section header table file offset */
  28:    Elf64_Word    e_flags;        /* Processor-specific flags */
  29:    Elf64_Half    e_ehsize;        /* ELF header size in bytes */
  30:    Elf64_Half    e_phentsize;        /* Program header table entry size */
  31:    Elf64_Half    e_phnum;        /* Program header table entry count */
  32:    Elf64_Half    e_shentsize;        /* Section header table entry size */
  33:    Elf64_Half    e_shnum;        /* Section header table entry count */
  34:    Elf64_Half    e_shstrndx;        /* Section header string table index */
  35:  }SEF_ELFHEADER_64;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

SECTION header

   1:  /* Section header.  */
   2:   
   3:  typedef struct
   4:  {
   5:    Elf32_Word    sh_name;        /* Section name (string tbl index) */
   6:    Elf32_Word    sh_type;        /* Section type */
   7:    Elf32_Word    sh_flags;        /* Section flags */
   8:    Elf32_Addr    sh_addr;        /* Section virtual addr at execution */
   9:    Elf32_Off    sh_offset;        /* Section file offset */
  10:    Elf32_Word    sh_size;        /* Section size in bytes */
  11:    Elf32_Word    sh_link;        /* Link to another section */
  12:    Elf32_Word    sh_info;        /* Additional section information */
  13:    Elf32_Word    sh_addralign;        /* Section alignment */
  14:    Elf32_Word    sh_entsize;        /* Entry size if section holds table */
  15:  } SEF_SECHEADER_32;
  16:   
  17:  typedef struct
  18:  {
  19:    Elf64_Word    sh_name;        /* Section name (string tbl index) */
  20:    Elf64_Word    sh_type;        /* Section type */
  21:    Elf64_Xword    sh_flags;        /* Section flags */
  22:    Elf64_Addr    sh_addr;        /* Section virtual addr at execution */
  23:    Elf64_Off    sh_offset;        /* Section file offset */
  24:    Elf64_Xword    sh_size;        /* Section size in bytes */
  25:    Elf64_Word    sh_link;        /* Link to another section */
  26:    Elf64_Word    sh_info;        /* Additional section information */
  27:    Elf64_Xword    sh_addralign;        /* Section alignment */
  28:    Elf64_Xword    sh_entsize;        /* Entry size if section holds table */
  29:  } SEF_SECHEADER_64;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

SEGMENT header

   1:  /* Program segment header.  */
   2:   
   3:  typedef struct
   4:  {
   5:    Elf32_Word    p_type;            /* Segment type */
   6:    Elf32_Off     p_offset;        /* Segment file offset */
   7:    Elf32_Addr    p_vaddr;        /* Segment virtual address */
   8:    Elf32_Addr    p_paddr;        /* Segment physical address */
   9:    Elf32_Word    p_filesz;        /* Segment size in file */
  10:    Elf32_Word    p_memsz;        /* Segment size in memory */
  11:    Elf32_Word    p_flags;        /* Segment flags */
  12:    Elf32_Word    p_align;        /* Segment alignment */
  13:  } SEF_PROHEADER_32;
  14:   
  15:  typedef struct
  16:  {
  17:    Elf64_Word    p_type;            /* Segment type */
  18:    Elf64_Word    p_flags;        /* Segment flags */
  19:    Elf64_Off    p_offset;        /* Segment file offset */
  20:    Elf64_Addr    p_vaddr;        /* Segment virtual address */
  21:    Elf64_Addr    p_paddr;        /* Segment physical address */
  22:    Elf64_Xword    p_filesz;        /* Segment size in file */
  23:    Elf64_Xword    p_memsz;        /* Segment size in memory */
  24:    Elf64_Xword    p_align;        /* Segment alignment */
  25:  } SEF_PROHEADER_64;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

这里给出我的头文件:elf_type.h

   1:  #ifndef _ELF_TYPE_H
   2:  #define _ELF_TYPE_H
   3:  #include<stdint.h>
   4:   
   5:  #define ELFCLASSNONE   (0)
   6:  #define ELFCLASS32     (1)
   7:  #define ELFCLASS64     (2)
   8:   
   9:  #define ELFDATANONE    (0)
  10:  #define ELFDATA2LSB    (1)
  11:  #define ELFDATA2MSB    (2)
  12:   
  13:  #define ET_NONE        (0)
  14:  #define ET_REL         (1)
  15:  #define ET_EXEC        (2)
  16:  #define ET_DYN         (3)
  17:   
  18:  #define E_PHNUM       (65535)
  19:  #define NULL          ((void *)0)
  20:   
  21:  /* Type for a 16-bit quantity.  */
  22:  typedef uint16_t Elf32_Half;
  23:  typedef uint16_t Elf64_Half;
  24:   
  25:  /* Types for signed and unsigned 32-bit quantities.  */
  26:  typedef uint32_t Elf32_Word;
  27:  typedef    int32_t  Elf32_Sword;
  28:  typedef uint32_t Elf64_Word;
  29:  typedef    int32_t  Elf64_Sword;
  30:   
  31:  /* Types for signed and unsigned 64-bit quantities.  */
  32:  typedef uint64_t Elf32_Xword;
  33:  typedef    int64_t  Elf32_Sxword;
  34:  typedef uint64_t Elf64_Xword;
  35:  typedef    int64_t  Elf64_Sxword;
  36:   
  37:  /* Type of addresses.  */
  38:  typedef uint32_t Elf32_Addr;
  39:  typedef uint64_t Elf64_Addr;
  40:   
  41:  /* Type of file offsets.  */
  42:  typedef uint32_t Elf32_Off;
  43:  typedef uint64_t Elf64_Off;
  44:   
  45:  /* Type for section indices, which are 16-bit quantities.  */
  46:  typedef uint16_t Elf32_Section;
  47:  typedef uint16_t Elf64_Section;
  48:   
  49:  /* Type for version symbol information.  */
  50:  typedef Elf32_Half Elf32_Versym;
  51:  typedef Elf64_Half Elf64_Versym;
  52:   
  53:  //char *pBuffer;
  54:  /* The ELF file header.  This appears at the start of every ELF file.  */
  55:   
  56:  #define EI_NIDENT (16)
  57:   
  58:  typedef struct
  59:  {
  60:    unsigned char    e_ident[EI_NIDENT];    /* Magic number and other info */
  61:    Elf32_Half    e_type;            /* Object file type */
  62:    Elf32_Half    e_machine;        /* Architecture */
  63:    Elf32_Word    e_version;        /* Object file version */
  64:    Elf32_Addr    e_entry;        /* Entry point virtual address */
  65:    Elf32_Off    e_phoff;        /* Program header table file offset */
  66:    Elf32_Off    e_shoff;        /* Section header table file offset */
  67:    Elf32_Word    e_flags;        /* Processor-specific flags */
  68:    Elf32_Half    e_ehsize;        /* ELF header size in bytes */
  69:    Elf32_Half    e_phentsize;        /* Program header table entry size */
  70:    Elf32_Half    e_phnum;        /* Program header table entry count */
  71:    Elf32_Half    e_shentsize;
  72:    Elf32_Half    e_shnum;
  73:    Elf32_Half    e_shstrndx;
  74:  } SEF_ELFHEADER_32;
  75:   
  76:  typedef struct
  77:  {
  78:    unsigned char    e_ident[EI_NIDENT];    /* Magic number and other info */
  79:    Elf64_Half    e_type;            /* Object file type */
  80:    Elf64_Half    e_machine;        /* Architecture */
  81:    Elf64_Word    e_version;        /* Object file version */
  82:    Elf64_Addr    e_entry;        /* Entry point virtual address */
  83:    Elf64_Off    e_phoff;        /* Program header table file offset */
  84:    Elf64_Off    e_shoff;        /* Section header table file offset */
  85:    Elf64_Word    e_flags;        /* Processor-specific flags */
  86:    Elf64_Half    e_ehsize;        /* ELF header size in bytes */
  87:    Elf64_Half    e_phentsize;        /* Program header table entry size */
  88:    Elf64_Half    e_phnum;        /* Program header table entry count */
  89:    Elf64_Half    e_shentsize;        /* Section header table entry size */
  90:    Elf64_Half    e_shnum;        /* Section header table entry count */
  91:    Elf64_Half    e_shstrndx;        /* Section header string table index */
  92:  }SEF_ELFHEADER_64;
  93:   
  94:   
  95:   
  96:  /* Program segment header.  */
  97:   
  98:  typedef struct
  99:  {
 100:    Elf32_Word    p_type;            /* Segment type */
 101:    Elf32_Off     p_offset;        /* Segment file offset */
 102:    Elf32_Addr    p_vaddr;        /* Segment virtual address */
 103:    Elf32_Addr    p_paddr;        /* Segment physical address */
 104:    Elf32_Word    p_filesz;        /* Segment size in file */
 105:    Elf32_Word    p_memsz;        /* Segment size in memory */
 106:    Elf32_Word    p_flags;        /* Segment flags */
 107:    Elf32_Word    p_align;        /* Segment alignment */
 108:  } SEF_PROHEADER_32;
 109:   
 110:  typedef struct
 111:  {
 112:    Elf64_Word    p_type;            /* Segment type */
 113:    Elf64_Word    p_flags;        /* Segment flags */
 114:    Elf64_Off    p_offset;        /* Segment file offset */
 115:    Elf64_Addr    p_vaddr;        /* Segment virtual address */
 116:    Elf64_Addr    p_paddr;        /* Segment physical address */
 117:    Elf64_Xword    p_filesz;        /* Segment size in file */
 118:    Elf64_Xword    p_memsz;        /* Segment size in memory */
 119:    Elf64_Xword    p_align;        /* Segment alignment */
 120:  } SEF_PROHEADER_64;
 121:   
 122:  /* Section header.  */
 123:   
 124:  typedef struct
 125:  {
 126:    Elf32_Word    sh_name;        /* Section name (string tbl index) */
 127:    Elf32_Word    sh_type;        /* Section type */
 128:    Elf32_Word    sh_flags;        /* Section flags */
 129:    Elf32_Addr    sh_addr;        /* Section virtual addr at execution */
 130:    Elf32_Off    sh_offset;        /* Section file offset */
 131:    Elf32_Word    sh_size;        /* Section size in bytes */
 132:    Elf32_Word    sh_link;        /* Link to another section */
 133:    Elf32_Word    sh_info;        /* Additional section information */
 134:    Elf32_Word    sh_addralign;        /* Section alignment */
 135:    Elf32_Word    sh_entsize;        /* Entry size if section holds table */
 136:  } SEF_SECHEADER_32;
 137:   
 138:  typedef struct
 139:  {
 140:    Elf64_Word    sh_name;        /* Section name (string tbl index) */
 141:    Elf64_Word    sh_type;        /* Section type */
 142:    Elf64_Xword    sh_flags;        /* Section flags */
 143:    Elf64_Addr    sh_addr;        /* Section virtual addr at execution */
 144:    Elf64_Off    sh_offset;        /* Section file offset */
 145:    Elf64_Xword    sh_size;        /* Section size in bytes */
 146:    Elf64_Word    sh_link;        /* Link to another section */
 147:    Elf64_Word    sh_info;        /* Additional section information */
 148:    Elf64_Xword    sh_addralign;        /* Section alignment */
 149:    Elf64_Xword    sh_entsize;        /* Entry size if section holds table */
 150:  } SEF_SECHEADER_64;
 151:   
 152:  #endif

ELF格式解析库之基本数据类型

时间: 2024-10-22 16:48:06

ELF格式解析库之基本数据类型的相关文章

ELF格式解析库之抽象数据类型

抽象?抽谁的象? ELF是一种链接执行格式,它规定了对于一个ELF文件的基本数据类型是什么样的.可是,要解析一个ELF文件,而这个ELF文件或者是32Bits 或者是 64Bits,反正字长是未定的,怎么办?难道我们要定义两套解析的接口,以对应不同的字长的ELF文件吗?如果要这样做,不是不可以,只是那样做为接口的设计增加了太大的负担.这里我们采用"抽象"的方式,将已有的两套基础数据结构封装成一个兼容的数据结构.这样,我们设计解析接口时,可以做到尽量的简化,大大的减轻了工作量. 因此,这

ELF格式解析库之提取信息

看,宝藏就在那儿 在上一篇文章中,我们提到用按图索骥比喻库的初始化过程,那么现在有了地图,接下来的事情就是去寻找我们感兴趣的宝藏了.这个宝藏可能是一个ELF文件的程序文本段,也有可能是程序的某个不知名的代码段,这些都取决于你想要什么信息.我建议你去阅读ELF 的官方标准,那里边讲的比较清楚. 我这里只是实现了几个提取诸如:程序的大小端,能执行的CPU位数,程序的入口点,以及获得程序的所有节的编号和根据节的编号获取该节的详细信息. 提取信息:程序的大小端 1: long ELF_GetELFEnd

ELF格式解析库之初始化

寻宝要先设计路线图 对一个ELF文件来说,它里边装个一个程序的所有信息.我们想要拿的程序信息就在这个ELF文件的某个地址处.可是我们根本就不知道这个具体的地址是哪个,怎么办?举个较形象的例子来描述我们将要的做的事情.峨眉山的山道上放着一大箱金子,我们想搞到这箱黄金.所以在动手之前,我们应该先搞清楚这箱黄金具体位置在哪条山路上,然后设计出几条可行的路线图,接着才是沿着先前设计好的路线去找宝藏.只不过,在这里我们要找的黄金变成了程序某个部分的信息,而那座峨眉山则变成了一个ELF文件. 所以,寻宝要先

ELF格式的组成结构

LF指的是Executable and Linkable Format.最初是由UNIX系统实验室作为应用程序二进制接口开发和发行的,后来逐渐发展成为了可执行文件的格式标准,在很多操作系统和非操作系统环境中都有非常广泛的应用.完整的ELF格式标准涉及了三个方面的内容.在这里我们只需要关心一个方面,那就是一个ELF格式可执行程序的组成结构. 一个ELF可执行文件格式如图8-1所示. 像图8-1那样,一个ELF可执行文件包含了一个描述全局信息的ELF文件头.若干个Program头.若干个Segmen

Linux下的ELF可执行文件的格式解析 (转)

LInux命令只是和Kernel一起被编译进操作系统的存在于FS的ELF格式二进制文件,或者权限足够的脚本,或者一个软链 ELF(Executable and Linking Format)是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东西.以及都以什么样的格式去放这些东西.它自最早在 System V 系统上出现后,被 xNIX 世界所广泛接受,作为缺省的二进制文件格式来使用.可以说,ELF是构成众多xNIX系统的基础之一,所以作为嵌入式Linux系统

ELF格式文件符号表全解析及readelf命令使用方法

http://blog.csdn.net/edonlii/article/details/8779075 1. 读取ELF文件头: $ readelf -h signELF Header:  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  Class:                                                  ELF64  Data:                            

ELF文件格式解析

1. ELF文件简介 首先,你需要知道的是所谓对象文件(Object files)有三个种类: 可重定位的对象文件(Relocatable file) 这是由汇编器汇编生成的 .o 文件.后面的链接器(link editor)拿一个或一些 Relocatable object files 作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file).我们可以使用 ar 工具将众多的 .o Relocata

ELF格式的重定位原理分析

前面有篇文章分析了ELF格式,也只是让我们对目标文件有了一个大概的了解,并没有说明一个十分重要的问题:重定位,今天重新看了下重定位的资料,终于弄懂了重定位的过程,下面来做一个分析. 我们将使用下面两个源代码中的文件a.c和b.c展开分析: //a.c extern int shared; int main() { int a=100; swap(&a,&shared); } //b.c int shared=1; void swap(int *a,int *b) { *a^=*b^=*a^

开源项目OkHttpPlus——支持GET、POST、UI线程回调、JSON格式解析、链式调用、文件上传下载

OkHttpPlus介绍 项目地址:https://github.com/ZhaoKaiQiang/OkHttpPlus 主要功能:OkHttp封装,支持GET.POST.UI线程回调.JSON格式解析.链式调用.小文件上传下载及进度监听等功能 为什么要写这么一个库呢? 首先,是因为OkHttp在4.4之后已经作为底层的Http实现了,所以OkHttp这个库很强大,值得我们学习. 其次,在我看来,OkHttp使用起来不如Volley方便,OkHttp的回调都是在工作线程,所以如果在回调里面操作V