首页 > C/C++ > Linux 可重定位文件 ELF结构
2017
09-18

Linux 可重定位文件 ELF结构

    ELF,全称Executable and Linkable Format,可执行链接格式,是UNIX系统实验室(USL)作为应用程序二进制接口(Application Binary Interface,ABI)而开发和发布的。扩展名为elf。ELF 标准的目的是为软件开发人员提供一组二进制接口定义,这些接口可以延伸到多种操作环境,从而减少重新编码、重新编译程序的需要。接口的内容包括目标模块格式、可执行文件格式以及调试记录信息与格式等。    

Linux下ELF文件类型分为以下几种:

    1、可重定位文件,包含适合于与其他目标文件连接来创建可执行文件或者共享目标文件的代码和数据,例如SimpleSection.o;

    2、可执行文件,包含适合于执行的一个程序,此文件规定了exec()如何创建一个程序的进程映像,例如/bin/bash;

    3、共享目标文件包含可在两种上下文中链接的代码和数据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件;其次,动态链接器(Dynamic Linker)可能将它与某个可执行文件以及其它共享目标一起组合,创建进程映像,例如/lib/libc.so。

    

Linux 可重定位文件 ELF结构 - 第1张  | 刘建广学习笔记

    文件开始处是一个ELF 头部(ELF Header),用来描述整个文件的组织。节区部分包含链接视图的大量信息:指令、数据、符号表、重定位信息等等。
    ELF Header之后可能会有一个程序头部表(Program Header Table),如果存在的话,告诉系统如何创建进程映像。用来构造进程映像的目标文件必须具有程序头部表,可重定位文件不需要这个表。 
    节区头部表(Section Heade Table)包含了描述文件节区的信息,每个节区在表中都有一项,每一项给出诸如节区名称、节区大小这类信息。用于链接的目标文件必须包含节区头部表,其他目标文件可以有,也可以没有这个表。
    另外,Sections是文件节区,它包含不同的节区,且节区没有规定的顺序。

    再接下来的文章中,我们会使用objdump,readelf,hexdump,nm等来分析一个Linux中可重定位文件SimpleSection.o。

    首先附上SimpleSection.c源代码:

int printf( const char* format, ... );

int global_init_var = 84;
int global_uninit_var;

void func1( int i )
{
    printf( "%d\n", i );
}

int main(void)
{
    static int static_var = 85;
    static int static_var2;

    int a = 1;
    int b;

    func1( static_var + static_var2 + a + b );

    return a;
}

    使用命令:

    gcc -c SimpleSection.c

    得到SimpleSection.o,下面我们首先附上SimpleSection.o的二进制内容以及整体轮廓。

    使用命令:

    hexdump -C SimpleSection.o,得到SimpleSection.o的二进制内容。

    计算机科学中,二进制0 1可以代表代码,字母,数字(十进制数和十六进制数)。

00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  01 00 3e 00 01 00 00 00  00 00 00 00 00 00 00 00  |..>.............|
00000020  00 00 00 00 00 00 00 00  20 04 00 00 00 00 00 00  |........ .......|
00000030  00 00 00 00 40 00 00 00  00 00 40 00 0d 00 0a 00  |....@.....@.....|
00000040  55 48 89 e5 48 83 ec 10  89 7d fc 8b 45 fc 89 c6  |UH..H....}..E...|
00000050  bf 00 00 00 00 b8 00 00  00 00 e8 00 00 00 00 c9  |................|
00000060  c3 55 48 89 e5 48 83 ec  10 c7 45 fc 01 00 00 00  |.UH..H....E.....|
00000070  8b 15 00 00 00 00 8b 05  00 00 00 00 01 c2 8b 45  |...............E|
00000080  fc 01 c2 8b 45 f8 01 d0  89 c7 e8 00 00 00 00 8b  |....E...........|
00000090  45 fc c9 c3 54 00 00 00  55 00 00 00 25 64 0a 00  |E...T...U...%d..|
000000a0  00 47 43 43 3a 20 28 47  4e 55 29 20 34 2e 38 2e  |.GCC: (GNU) 4.8.|
000000b0  35 20 32 30 31 35 30 36  32 33 20 28 52 65 64 20  |5 20150623 (Red |
000000c0  48 61 74 20 34 2e 38 2e  35 2d 31 31 29 00 00 00  |Hat 4.8.5-11)...|
000000d0  14 00 00 00 00 00 00 00  01 7a 52 00 01 78 10 01  |.........zR..x..|
000000e0  1b 0c 07 08 90 01 00 00  1c 00 00 00 1c 00 00 00  |................|
000000f0  00 00 00 00 21 00 00 00  00 41 0e 10 86 02 43 0d  |....!....A....C.|
00000100  06 5c 0c 07 08 00 00 00  1c 00 00 00 3c 00 00 00  |.\..........<...|
00000110  00 00 00 00 33 00 00 00  00 41 0e 10 86 02 43 0d  |....3....A....C.|
00000120  06 6e 0c 07 08 00 00 00  00 2e 73 79 6d 74 61 62  |.n........symtab|
00000130  00 2e 73 74 72 74 61 62  00 2e 73 68 73 74 72 74  |..strtab..shstrt|
00000140  61 62 00 2e 72 65 6c 61  2e 74 65 78 74 00 2e 64  |ab..rela.text..d|
00000150  61 74 61 00 2e 62 73 73  00 2e 72 6f 64 61 74 61  |ata..bss..rodata|
00000160  00 2e 63 6f 6d 6d 65 6e  74 00 2e 6e 6f 74 65 2e  |..comment..note.|
00000170  47 4e 55 2d 73 74 61 63  6b 00 2e 72 65 6c 61 2e  |GNU-stack..rela.|
00000180  65 68 5f 66 72 61 6d 65  00 00 00 00 00 00 00 00  |eh_frame........|
00000190  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001a0  00 00 00 00 00 00 00 00  01 00 00 00 04 00 f1 ff  |................|
000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001c0  00 00 00 00 03 00 01 00  00 00 00 00 00 00 00 00  |................|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 03 00 03 00  |................|
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 03 00 04 00  00 00 00 00 00 00 00 00  |................|
00000200  00 00 00 00 00 00 00 00  00 00 00 00 03 00 05 00  |................|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000220  11 00 00 00 01 00 03 00  04 00 00 00 00 00 00 00  |................|
00000230  04 00 00 00 00 00 00 00  21 00 00 00 01 00 04 00  |........!.......|
00000240  00 00 00 00 00 00 00 00  04 00 00 00 00 00 00 00  |................|
00000250  00 00 00 00 03 00 07 00  00 00 00 00 00 00 00 00  |................|
00000260  00 00 00 00 00 00 00 00  00 00 00 00 03 00 08 00  |................|
00000270  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000280  00 00 00 00 03 00 06 00  00 00 00 00 00 00 00 00  |................|
00000290  00 00 00 00 00 00 00 00  32 00 00 00 11 00 03 00  |........2.......|
000002a0  00 00 00 00 00 00 00 00  04 00 00 00 00 00 00 00  |................|
000002b0  42 00 00 00 11 00 f2 ff  04 00 00 00 00 00 00 00  |B...............|
000002c0  04 00 00 00 00 00 00 00  54 00 00 00 12 00 01 00  |........T.......|
000002d0  00 00 00 00 00 00 00 00  21 00 00 00 00 00 00 00  |........!.......|
000002e0  5a 00 00 00 10 00 00 00  00 00 00 00 00 00 00 00  |Z...............|
000002f0  00 00 00 00 00 00 00 00  61 00 00 00 12 00 01 00  |........a.......|
00000300  21 00 00 00 00 00 00 00  33 00 00 00 00 00 00 00  |!.......3.......|
00000310  00 53 69 6d 70 6c 65 53  65 63 74 69 6f 6e 2e 63  |.SimpleSection.c|
00000320  00 73 74 61 74 69 63 5f  76 61 72 2e 31 37 33 31  |.static_var.1731|
00000330  00 73 74 61 74 69 63 5f  76 61 72 32 2e 31 37 33  |.static_var2.173|
00000340  32 00 67 6c 6f 62 61 6c  5f 69 6e 69 74 5f 76 61  |2.global_init_va|
00000350  72 00 67 6c 6f 62 61 6c  5f 75 6e 69 6e 69 74 5f  |r.global_uninit_|
00000360  76 61 72 00 66 75 6e 63  31 00 70 72 69 6e 74 66  |var.func1.printf|
00000370  00 6d 61 69 6e 00 00 00  11 00 00 00 00 00 00 00  |.main...........|
00000380  0a 00 00 00 05 00 00 00  00 00 00 00 00 00 00 00  |................|
00000390  1b 00 00 00 00 00 00 00  02 00 00 00 0e 00 00 00  |................|
000003a0  fc ff ff ff ff ff ff ff  32 00 00 00 00 00 00 00  |........2.......|
000003b0  02 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  |................|
000003c0  38 00 00 00 00 00 00 00  02 00 00 00 04 00 00 00  |8...............|
000003d0  fc ff ff ff ff ff ff ff  4b 00 00 00 00 00 00 00  |........K.......|
000003e0  02 00 00 00 0d 00 00 00  fc ff ff ff ff ff ff ff  |................|
000003f0  20 00 00 00 00 00 00 00  02 00 00 00 02 00 00 00  | ...............|
00000400  00 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000410  02 00 00 00 02 00 00 00  21 00 00 00 00 00 00 00  |........!.......|
00000420  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000460  20 00 00 00 01 00 00 00  06 00 00 00 00 00 00 00  | ...............|
00000470  00 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000480  54 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |T...............|
00000490  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000004a0  1b 00 00 00 04 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
000004b0  00 00 00 00 00 00 00 00  78 03 00 00 00 00 00 00  |........x.......|
000004c0  78 00 00 00 00 00 00 00  0b 00 00 00 01 00 00 00  |x...............|
000004d0  08 00 00 00 00 00 00 00  18 00 00 00 00 00 00 00  |................|
000004e0  26 00 00 00 01 00 00 00  03 00 00 00 00 00 00 00  |&...............|
000004f0  00 00 00 00 00 00 00 00  94 00 00 00 00 00 00 00  |................|
00000500  08 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000510  04 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000520  2c 00 00 00 08 00 00 00  03 00 00 00 00 00 00 00  |,...............|
00000530  00 00 00 00 00 00 00 00  9c 00 00 00 00 00 00 00  |................|
00000540  04 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000560  31 00 00 00 01 00 00 00  02 00 00 00 00 00 00 00  |1...............|
00000570  00 00 00 00 00 00 00 00  9c 00 00 00 00 00 00 00  |................|
00000580  04 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000590  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000005a0  39 00 00 00 01 00 00 00  30 00 00 00 00 00 00 00  |9.......0.......|
000005b0  00 00 00 00 00 00 00 00  a0 00 00 00 00 00 00 00  |................|
000005c0  2e 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000005d0  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................|
000005e0  42 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |B...............|
000005f0  00 00 00 00 00 00 00 00  ce 00 00 00 00 00 00 00  |................|
00000600  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000610  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000620  57 00 00 00 01 00 00 00  02 00 00 00 00 00 00 00  |W...............|
00000630  00 00 00 00 00 00 00 00  d0 00 00 00 00 00 00 00  |................|
00000640  58 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |X...............|
00000650  08 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000660  52 00 00 00 04 00 00 00  40 00 00 00 00 00 00 00  |R.......@.......|
00000670  00 00 00 00 00 00 00 00  f0 03 00 00 00 00 00 00  |................|
00000680  30 00 00 00 00 00 00 00  0b 00 00 00 08 00 00 00  |0...............|
00000690  08 00 00 00 00 00 00 00  18 00 00 00 00 00 00 00  |................|
000006a0  11 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  |................|
000006b0  00 00 00 00 00 00 00 00  28 01 00 00 00 00 00 00  |........(.......|
000006c0  61 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |a...............|
000006d0  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000006e0  01 00 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................|
000006f0  00 00 00 00 00 00 00 00  90 01 00 00 00 00 00 00  |................|
00000700  80 01 00 00 00 00 00 00  0c 00 00 00 0b 00 00 00  |................|
00000710  08 00 00 00 00 00 00 00  18 00 00 00 00 00 00 00  |................|
00000720  09 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  |................|
00000730  00 00 00 00 00 00 00 00  10 03 00 00 00 00 00 00  |................|
00000740  66 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |f...............|
00000750  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000760

   使用命令ls -l SimpleSection.o,可以得到文件大小为1888字节,上面二进制内容正好也是1888个字节(0x760转换为十机制为1888)。


    SimpleSection.o的整体轮廓图如下,可能读者会想为什么会得到这样一张图,随着我们深入分析每个段的内容,答案自然会揭晓。

    我们看到0x758是所有段结束的位置,换算成十进制就是1888个字节。和我们刚才获取的文件大小一样。

   

    下面我们来利用命令来分析ELF文件结构的每个部分:

    1、ELF Header

    使用命令readelf -h SimpleSection.o,得到下图。

Linux 可重定位文件 ELF结构 - 第2张  | 刘建广学习笔记

           图 3

  ELF文件头结构及相关参数被定义在“/usr/include/elf.h”中,如下:

typedef struct  
{  
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */  
  Elf32_Half    e_type;                 /* Object file type */  
  Elf32_Half    e_machine;              /* Architecture */  
  Elf32_Word    e_version;              /* Object file version */  
  Elf32_Addr    e_entry;                /* Entry point virtual address */  
  Elf32_Off     e_phoff;                /* Program header table file offset */  
  Elf32_Off     e_shoff;                /* Section header table file offset */  
  Elf32_Word    e_flags;                /* Processor-specific flags */  
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */  
  Elf32_Half    e_phentsize;            /* Program header table entry size */  
  Elf32_Half    e_phnum;                /* Program header table entry count */  
  Elf32_Half    e_shentsize;            /* Section header table entry size */  
  Elf32_Half    e_shnum;                /* Section header table entry count */  
  Elf32_Half    e_shstrndx;             /* Section header string table index */  
} Elf32_Ehdr;  

    Type:ELF文件类型,本例中为REL(Relocatable File),可重定位文件。

    Start of section headers,段表在文件中偏移,就是图2中Section Table的位置为1056(0x420)。

    Size of section headers,ELF文件头的大小为64个字节。

    Number of section headers,ELF拥有多少个断,本例为13个段。见图 7。

    Section header string table index,段表字符串表所在的段在段表中的下标。本例中等于10,见图 7。


    2、.text
    使用命令:
    objdump -d SimpleSection.o,得到了下图,由于是代码段,所以二进制代表汇编代码。

Linux 可重定位文件 ELF结构 - 第3张  | 刘建广学习笔记

         图 4     

    3、.data

    使用命令objdump -s SimpleSection.o,得到数据段,如下图:

Linux 可重定位文件 ELF结构 - 第4张  | 刘建广学习笔记

         图 5     

    本例中存入数据段的是

int global_init_var = 84;  
static int static_var = 85;  

  共8个字节,一个是0x00000054,十进制是84;一个是0x0000000056,十进制是85。     

    4、.bss

    使用命令objdump -h SimpleSection.o,得到下图:

Linux 可重定位文件 ELF结构 - 第5张  | 刘建广学习笔记

         图 6     

    本例中存入数据段的是

static int static_var2;  

   大家会注意到int global_uninit_var;既没有在.data段中,也没有在.bss段中。如果在前面加上static,那么则存在.bss段中。

    5、.rodata

    .rodata存放的只读数据。25640a00,查看ASCII表代表的就是%d\n。

    6、.shstrtab(段表字符串表)

    如图1,存放的是

    ..symtab..strtab..shstrtab..rela.text..data..bs..rodata..comment..note.GNU-stak..rela.eh_frame

    7、.strtab(字符串表)

    如图1,存放的是

    SimpleSection.c.static_var.1594.static_var2.1595.global_init_var.global_uninit_var.func1.printf.main

    8、Section Table

    使用命令,readelf -S SimpleSection.o,得到下图:

Linux 可重定位文件 ELF结构 - 第6张  | 刘建广学习笔记

         图 7     

    这就解释了图1,为什么要那么画。

    Offset表示段偏移,Size表示段大小。

    Type,PROGBITS表示段,NOBITS表示不占空间,.RELA表示重定位段,STRTAB表示字符串表,SYMTAB表示符号表。

    EntSize表示如果段中有重复的内容,则表示重复内容大小。比如下面要介绍的符号表就是重复内容组成的。

    在TYPE为RELA时,Link表示该段所使用的相应符号表在段表中,本例中为11。Info表示该重定位表所作用的段在段表中的下标。.rela.text为1,.rela.eh_frame为8。    

    9、.symtab(符号表)

    使用命令,readelf -s SimpleSection.o,得到下图:

Linux 可重定位文件 ELF结构 - 第7张  | 刘建广学习笔记

          图 8     

    Name,表示字符串在字符串表中的下标;

    Ndx,SimpleSection.c为ABS,global_uninit_var为COM,表示这个变量是强引用或者弱引用,目前即不在.data段中,也不在.bss段中,等待链接时会确定。

    printf为UND,表示没有定义,即引用了外部的函数。

    global_init_var,NDX为3,表示在.data中,其余类似。表示符号所在的段在段表中的下标;参考图 7。

    Bind GLOBAL表示可以被外部引用或者引用外部的函数和变量。

    TYPE为OBJECT表示对象,FUNC表示函数,SECTION表示段,FILE表示文件,printf为NOTYPE,表示没有定义,是引用外部函数。

    SIZE表示大小。

    Value表示在本段中的偏移,比如static_var.1594表示在.data段中的偏移为4。 main在.data段中的偏移为21。

    最后介绍个命令,nm SimpleSection.o,结果如下:

Linux 可重定位文件 ELF结构 - 第8张  | 刘建广学习笔记

              图 9     

    可以看出示所有可以被外部引用或者引用外部的函数和变量。

    T表示text;D和d表示data;b表示bss,C表示Common,U表示Undef。

    程序中的非静态局部变量即不在数据段也不在代码段,可能在堆栈段。

最后编辑:
作者:liujg
真实-不弄虚,不做假,做自己,不违心; 踏实-不浮躁,不盲从,不急功,不近利; 实学-不投机,不取巧,勤于学,精于业。