编译链接基本素养笔记(一)ELF文件结构

来源:互联网 发布:数据透视表行标签重复 编辑:程序博客网 时间:2024/06/05 00:55

源代码:

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;}

头文件结构:

karl@ubuntu:~/c/static$ objdump -h SimpleSection.o SimpleSection.o:     file format elf32-i386Sections:Idx Name          Size      VMA       LMA       File off  Algn  0 .text         00000053  00000000  00000000  00000034  2**0                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE  1 .data         00000008  00000000  00000000  00000088  2**2                  CONTENTS, ALLOC, LOAD, DATA  2 .bss          00000004  00000000  00000000  00000090  2**2                  ALLOC  3 .rodata       00000004  00000000  00000000  00000090  2**0                  CONTENTS, ALLOC, LOAD, READONLY, DATA  4 .comment      0000002a  00000000  00000000  00000094  2**0                  CONTENTS, READONLY  5 .note.GNU-stack 00000000  00000000  00000000  000000be  2**0                  CONTENTS, READONLY  6 .eh_frame     00000058  00000000  00000000  000000c0  2**2                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

生成的汇编语言和代码段内容:

karl@ubuntu:~/c/static$ objdump -s -d SimpleSection.oSimpleSection.o:     file format elf32-i386Contents of section .text: 0000 5589e583 ec188b45 08894424 04c70424  U......E..D$...$ 0010 00000000 e8fcffff ffc9c355 89e583e4  ...........U.... 0020 f083ec20 c7442418 01000000 8b150400  ... .D$......... 0030 0000a100 00000001 c28b4424 1801c28b  ..........D$.... 0040 44241c01 d0890424 e8fcffff ff8b4424  D$.....$......D$ 0050 18c9c3                               ...             Contents of section .data: 0000 54000000 55000000                    T...U...        Contents of section .rodata: 0000 25640a00                             %d..            Contents of section .comment: 0000 00474343 3a202855 62756e74 7520342e  .GCC: (Ubuntu 4. 0010 382e342d 32756275 6e747531 7e31342e  8.4-2ubuntu1~14. 0020 30342920 342e382e 3400               04) 4.8.4.      Contents of section .eh_frame: 0000 14000000 00000000 017a5200 017c0801  .........zR..|.. 0010 1b0c0404 88010000 1c000000 1c000000  ................ 0020 00000000 1b000000 00410e08 8502420d  .........A....B. 0030 0557c50c 04040000 1c000000 3c000000  .W..........<... 0040 1b000000 38000000 00410e08 8502420d  ....8....A....B. 0050 0574c50c 04040000                    .t......        Disassembly of section .text:00000000 <func1>:   0:   55                      push   %ebp   1:   89 e5                   mov    %esp,%ebp   3:   83 ec 18                sub    $0x18,%esp   6:   8b 45 08                mov    0x8(%ebp),%eax   9:   89 44 24 04             mov    %eax,0x4(%esp)   d:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)  14:   e8 fc ff ff ff          call   15 <func1+0x15>  19:   c9                      leave    1a:   c3                      ret    0000001b <main>:  1b:   55                      push   %ebp  1c:   89 e5                   mov    %esp,%ebp  1e:   83 e4 f0                and    $0xfffffff0,%esp  21:   83 ec 20                sub    $0x20,%esp  24:   c7 44 24 18 01 00 00    movl   $0x1,0x18(%esp)  2b:   00   2c:   8b 15 04 00 00 00       mov    0x4,%edx  32:   a1 00 00 00 00          mov    0x0,%eax  37:   01 c2                   add    %eax,%edx  39:   8b 44 24 18             mov    0x18(%esp),%eax  3d:   01 c2                   add    %eax,%edx  3f:   8b 44 24 1c             mov    0x1c(%esp),%eax  43:   01 d0                   add    %edx,%eax  45:   89 04 24                mov    %eax,(%esp)  48:   e8 fc ff ff ff          call   49 <main+0x2e>  4d:   8b 44 24 18             mov    0x18(%esp),%eax  51:   c9                      leave    52:   c3                      ret    

段说明:

  • 代码段第一列为偏移量,中间代码段中的内容(16进制),往下为代码段的汇编指令。可以看到代码段中的内容和会汇编指令的序列一样。代码段的长度也和头文件结构中的长度(0x53)相同。
  • 数据段(data)保存的是初始化了的全局变量和局部静态变量。程序中有两个变量,global_init_varstatic_var,共八个字节。和头文件结构中的data段大小一样。
  • rodata段存放的是只读数据,const修饰的变量和字符串常量(%d\n)。
  • bss段存放的是未初始化的全局变量和局部静态变量。

观察文件头:

karl@ubuntu:~/c/static$ readelf -h SimpleSection.oELF Header:  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00   Class:                             ELF32  Data:                              2's complement, little endian  Version:                           1 (current)  OS/ABI:                            UNIX - System V  ABI Version:                       0  Type:                              REL (Relocatable file)  Machine:                           Intel 80386  Version:                           0x1  Entry point address:               0x0  Start of program headers:          0 (bytes into file)  Start of section headers:          376 (bytes into file)  Flags:                             0x0  Size of this header:               52 (bytes)  Size of program headers:           0 (bytes)  Number of program headers:         0  Size of section headers:           40 (bytes)  Number of section headers:         13  Section header string table index: 10

32位文件头数据结构:/usr/include/elf.h

#define EI_NIDENT (16)typedef struct{  unsigned char e_ident[EI_NIDENT];   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;
  • Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 ,这个16字节魔术数对应了ELF文件的平台属性,字长,字节序,版本等。操作系统在加载的时候会确认魔术数是否正确,如果不正确,会拒绝加载。
  • e_type ELF文件类型。
/* Legal values for e_type (object file type).  */#define ET_NONE     0       /* No file type */#define ET_REL      1       /* Relocatable file */#define ET_EXEC     2       /* Executable file */#define ET_DYN      3       /* Shared object file */#define ET_CORE     4       /* Core file */

段表

karl@ubuntu:~/c/static$   readelf -S SimpleSection.oThere are 13 section headers, starting at offset 0x178://注意在文件头中,Start of section headers的值为十进制。Section Headers:  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al  [ 0]                   NULL            00000000 000000 000000 00      0   0  0  [ 1] .text             PROGBITS        00000000 000034 000053 00  AX  0   0  1  [ 2] .rel.text         REL             00000000 0004e8 000028 08     11   1  4  [ 3] .data             PROGBITS        00000000 000088 000008 00  WA  0   0  4  [ 4] .bss              NOBITS          00000000 000090 000004 00  WA  0   0  4  [ 5] .rodata           PROGBITS        00000000 000090 000004 00   A  0   0  1  [ 6] .comment          PROGBITS        00000000 000094 00002a 01  MS  0   0  1  [ 7] .note.GNU-stack   PROGBITS        00000000 0000be 000000 00      0   0  1  [ 8] .eh_frame         PROGBITS        00000000 0000c0 000058 00   A  0   0  4  [ 9] .rel.eh_frame     REL             00000000 000510 000010 08     11   8  4  [10] .shstrtab         STRTAB          00000000 000118 00005f 00      0   0  1  [11] .symtab           SYMTAB          00000000 000380 000100 10     12  11  4  [12] .strtab           STRTAB          00000000 000480 000066 00      0   0  1Key to Flags:  W (write), A (alloc), X (execute), M (merge), S (strings)  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)  O (extra OS processing required) o (OS specific), p (processor specific)
  • 段表其实是一个段结构体的数组。
  • 段表描述符结构:
typedef struct{  Elf32_Word    sh_name;        /* Section name (string tbl index) */  Elf32_Word    sh_type;        /* Section type */  Elf32_Word    sh_flags;       /* Section flags */  Elf32_Addr    sh_addr;        /* Section virtual addr at execution */  Elf32_Off sh_offset;      /* Section file offset */  Elf32_Word    sh_size;        /* Section size in bytes */  Elf32_Word    sh_link;        /* Link to another section */  Elf32_Word    sh_info;        /* Additional section information */  Elf32_Word    sh_addralign;       /* Section alignment */  Elf32_Word    sh_entsize;     /* Entry size if section holds table */} Elf32_Shdr;
  • 对于编译器和链接器来说,主要决定段的属性的是段的类型(sh_type)和段的标志位(sh_flags).

  • 段类型:

/* Legal values for sh_type (section type).  */#define SHT_NULL      0     /* Section header table entry unused */#define SHT_PROGBITS      1     /* Program data */#define SHT_SYMTAB    2     /* Symbol table */#define SHT_STRTAB    3     /* String table */#define SHT_RELA      4     /* Relocation entries with addends */#define SHT_HASH      5     /* Symbol hash table */#define SHT_DYNAMIC   6     /* Dynamic linking information */#define SHT_NOTE      7     /* Notes */#define SHT_NOBITS    8     /* Program space with no data (bss) */#define SHT_REL       9     /* Relocation entries, no addends */#define SHT_SHLIB     10        /* Reserved */#define SHT_DYNSYM    11        /* Dynamic linker symbol table */#define SHT_INIT_ARRAY    14        /* Array of constructors */#define SHT_FINI_ARRAY    15        /* Array of destructors */#define SHT_PREINIT_ARRAY 16        /* Array of pre-constructors */#define SHT_GROUP     17        /* Section group */#define SHT_SYMTAB_SHNDX  18        /* Extended section indeces */#define SHT_NUM       19        /* Number of defined types.  */
  • 段标志:段的标志位(sh_flag) 段的标志位表示该段在进程虚拟地址空间中的属性,比如是否可写,是否可执行等。
/* Legal values for sh_flags (section flags).  */#define SHF_WRITE        (1 << 0)   /* Writable */#define SHF_ALLOC        (1 << 1)   /* Occupies memory during execution */#define SHF_EXECINSTR        (1 << 2)   /* Executable */#define SHF_MERGE        (1 << 4)   /* Might be merged */#define SHF_STRINGS      (1 << 5)   /* Contains nul-terminated strings */
  • 分析文件头,能够得到短表和短表字符串表的位置,从而了解整个ELF文件。

符号表

  • 查看目标文件的符号表:ELF文件中的符号表往往是文件中的一个段,段名一般叫”.symtab”。
karl@ubuntu:~/c/static$ nm SimpleSection.o00000000 T func100000000 D global_init_var00000004 C global_uninit_var0000001b T main         U printf00000004 d static_var.137800000000 b static_var2.1379
  • 符号表的结构很简单,它是一个Elf32_Sym结构(32位ELF文件)的数组,每个Elf32_Sym结构对应一个符号。
/* Symbol table entry.  */typedef struct{  Elf32_Word    st_name;        /* Symbol name (string tbl index) */  Elf32_Addr    st_value;       /* Symbol value */  Elf32_Word    st_size;        /* Symbol size */  unsigned char st_info;        /* Symbol type and binding */  unsigned char st_other;       /* Symbol visibility */  Elf32_Section st_shndx;       /* Section index */} Elf32_Sym;
  • 符号类型和绑定信息(st_info) 该成员低4位表示符号的类型(Symbol Type),高28位表示符号绑定信息(Symbol Binding)
  • 绑定信息:
/* Legal values for ST_BIND subfield of st_info (symbol binding).  */#define STB_LOCAL   0       /* Local symbol 局部符号,对于目标文件的外部不可见*/#define STB_GLOBAL  1       /* Global symbol 全局符号,外部可见*/#define STB_WEAK    2       /* Weak symbol 弱引用*/#define STB_NUM     3       /* Number of defined types.  */#define STB_LOOS    10      /* Start of OS-specific */#define STB_GNU_UNIQUE  10      /* Unique symbol.  */#define STB_HIOS    12      /* End of OS-specific */#define STB_LOPROC  13      /* Start of processor-specific */#define STB_HIPROC  15      /* End of processor-specific */
  • 符号的类型
/* Legal values for ST_TYPE subfield of st_info (symbol type).  */#define STT_NOTYPE  0       /* Symbol type is unspecified 未知类型符号*/#define STT_OBJECT  1       /* Symbol is a data object 该符号是个数据对象,比如变量、数组等*/#define STT_FUNC    2       /* Symbol is a code object 该符号是个函数或其他可执行代码*/#define STT_SECTION 3       /* Symbol associated with a section 该符号表示一个段,这种符号必须是STB_LOCAL的*/#define STT_FILE    4       /* Symbol's name is file name 该符号表示文件名,一般都是该目标文件所对应的源文件名,它一定是STB_LOCAL类型的,并且它的st_shndx一定是SHN_ABS*/#define STT_COMMON  5       /* Symbol is a common data object */#define STT_TLS     6       /* Symbol is thread-local data object*/#define STT_NUM     7       /* Number of defined types.  */#define STT_LOOS    10      /* Start of OS-specific */#define STT_GNU_IFUNC   10      /* Symbol is indirect code object */#define STT_HIOS    12      /* End of OS-specific */#define STT_LOPROC  13      /* Start of processor-specific */#define STT_HIPROC  15      /* End of processor-specific */
  • 符号所在段 st_shndx )如果符号定义在本目标文件中,那么这个成员表示符号所在的段在段表中的下标,但是如果符号不是定义在本目标文件中,或者对于有些特殊符号,sh_shndx的值有些特殊。
#define SHN_UNDEF   0       /* Undefined section符号块未定义,在本目标文件被引用到,但是定义在其他目标文件中*/#define SHN_ABS     0xfff1      /* Associated symbol is absolute 表示该符号包含了一个绝对的值。比如表示文件名的符号就属于这种类型的*/#define SHN_COMMON  0xfff2  /* Associated symbol is common 表示该符号是一个“COMMON块”类型的符号,一般来说,未初始化的全局符号定义就是这种类型的*/

查看SimpleSection.o中的符号表详细信息

karl@ubuntu:~/c/static$ readelf -s SimpleSection.oSymbol table '.symtab' contains 16 entries:   Num:    Value  Size Type    Bind   Vis      Ndx Name     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND      1: 00000000     0 FILE    LOCAL  DEFAULT  ABS SimpleSection.c     2: 00000000     0 SECTION LOCAL  DEFAULT    1      3: 00000000     0 SECTION LOCAL  DEFAULT    3      4: 00000000     0 SECTION LOCAL  DEFAULT    4      5: 00000000     0 SECTION LOCAL  DEFAULT    5      6: 00000004     4 OBJECT  LOCAL  DEFAULT    3 static_var.1378     7: 00000000     4 OBJECT  LOCAL  DEFAULT    4 static_var2.1379     8: 00000000     0 SECTION LOCAL  DEFAULT    7      9: 00000000     0 SECTION LOCAL  DEFAULT    8     10: 00000000     0 SECTION LOCAL  DEFAULT    6     11: 00000000     4 OBJECT  GLOBAL DEFAULT    3 global_init_var    12: 00000004     4 OBJECT  GLOBAL DEFAULT  COM global_uninit_var    13: 00000000    27 FUNC    GLOBAL DEFAULT    1 func1    14: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf    15: 0000001b    56 FUNC    GLOBAL DEFAULT    1 main
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 上班第一天无聊怎么办 上班紧张不自信怎么办 销售到了30岁怎么办 转行会计没经验怎么办 澳洲coe被取消怎么办 父母不同意嫁远怎么办 家人不同意我们在一起怎么办 语言课申请不到怎么办 墨尔本大学均分不够怎么办 去澳洲旅游签证怎么办 换新护照澳大利亚签证怎么办 大学错过交学费日期怎么办 留学加拿大申请工签被拒怎么办 英国大学挂科怎么办 小孩子学不进去怎么办 大学生学不进去怎么办 高考没考上本科怎么办 想读书家里没钱怎么办 考上大学没钱上怎么办 儿子没考上大学怎么办 后悔没上大学怎么办 把学费花了怎么办 临床预科挂科怎么办 补录了预科怎么办 美国预科没过怎么办 出国留学报到证怎么办 本科绩点2.93怎么办 在美国被抢劫怎么办 去美国留学费用怎么办 被美国大学停学怎么办 雅思作文字数不够怎么办 英国选修课挂科怎么办 英国双申保证金怎么办 研究生挂科了怎么办 大一绩点没过2.0怎么办 美国留学生打工超时怎么办 ucl挂科了怎么办 硕士不会发论文怎么办 中兴今年招聘硕士生怎么办 rmit 语言班不过怎么办 非深圳户口怎么办护照