分析平台: x86_64机器
 
简单的C程序 
$ cat hello.c
int main() {
  return 0;
}
  
将该文件用gcc 编译成可重定位文件, 利用hexdump -C得到其16进制的文本(用vim -b 打开, 再用:%!xxd -g 1也可以得到)  
$ gcc hello.c -c
$ hexdump -C hello.o
  
得到的文本:  
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  10 02 00 00 00 00 00 00  |................|
00000030  00 00 00 00 40 00 00 00  00 00 40 00 0b 00 0a 00  |....@.....@.....|
00000040  55 48 89 e5 b8 00 00 00  00 5d c3 00 47 43 43 3a  |UH.......]..GCC:|
00000050  20 28 47 4e 55 29 20 38  2e 35 2e 30 20 32 30 32  | (GNU) 8.5.0 202|
00000060  31 30 35 31 34 20 28 52  65 64 20 48 61 74 20 38  |10514 (Red Hat 8|
00000070  2e 35 2e 30 2d 31 30 29  00 00 00 00 00 00 00 00  |.5.0-10)........|
00000080  14 00 00 00 00 00 00 00  01 7a 52 00 01 78 10 01  |.........zR..x..|
00000090  1b 0c 07 08 90 01 00 00  1c 00 00 00 1c 00 00 00  |................|
000000a0  00 00 00 00 0b 00 00 00  00 41 0e 10 86 02 43 0d  |.........A....C.|
000000b0  06 46 0c 07 08 00 00 00  00 00 00 00 00 00 00 00  |.F..............|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  01 00 00 00 04 00 f1 ff  00 00 00 00 00 00 00 00  |................|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 03 00 01 00  |................|
000000f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000100  00 00 00 00 03 00 02 00  00 00 00 00 00 00 00 00  |................|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 03 00 03 00  |................|
00000120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000130  00 00 00 00 03 00 05 00  00 00 00 00 00 00 00 00  |................|
00000140  00 00 00 00 00 00 00 00  00 00 00 00 03 00 06 00  |................|
00000150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000160  00 00 00 00 03 00 04 00  00 00 00 00 00 00 00 00  |................|
00000170  00 00 00 00 00 00 00 00  09 00 00 00 12 00 01 00  |................|
00000180  00 00 00 00 00 00 00 00  0b 00 00 00 00 00 00 00  |................|
00000190  00 68 65 6c 6c 6f 2e 63  00 6d 61 69 6e 00 00 00  |.hello.c.main...|
000001a0  20 00 00 00 00 00 00 00  02 00 00 00 02 00 00 00  | ...............|
000001b0  00 00 00 00 00 00 00 00  00 2e 73 79 6d 74 61 62  |..........symtab|
000001c0  00 2e 73 74 72 74 61 62  00 2e 73 68 73 74 72 74  |..strtab..shstrt|
000001d0  61 62 00 2e 74 65 78 74  00 2e 64 61 74 61 00 2e  |ab..text..data..|
000001e0  62 73 73 00 2e 63 6f 6d  6d 65 6e 74 00 2e 6e 6f  |bss..comment..no|
000001f0  74 65 2e 47 4e 55 2d 73  74 61 63 6b 00 2e 72 65  |te.GNU-stack..re|
00000200  6c 61 2e 65 68 5f 66 72  61 6d 65 00 00 00 00 00  |la.eh_frame.....|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000250  1b 00 00 00 01 00 00 00  06 00 00 00 00 00 00 00  |................|
00000260  00 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000270  0b 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000280  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000290  21 00 00 00 01 00 00 00  03 00 00 00 00 00 00 00  |!...............|
000002a0  00 00 00 00 00 00 00 00  4b 00 00 00 00 00 00 00  |........K.......|
000002b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000002c0  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000002d0  27 00 00 00 08 00 00 00  03 00 00 00 00 00 00 00  |'...............|
000002e0  00 00 00 00 00 00 00 00  4b 00 00 00 00 00 00 00  |........K.......|
000002f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000300  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000310  2c 00 00 00 01 00 00 00  30 00 00 00 00 00 00 00  |,.......0.......|
00000320  00 00 00 00 00 00 00 00  4b 00 00 00 00 00 00 00  |........K.......|
00000330  2e 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000340  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................|
00000350  35 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |5...............|
00000360  00 00 00 00 00 00 00 00  79 00 00 00 00 00 00 00  |........y.......|
00000370  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000380  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000390  4a 00 00 00 01 00 00 00  02 00 00 00 00 00 00 00  |J...............|
000003a0  00 00 00 00 00 00 00 00  80 00 00 00 00 00 00 00  |................|
000003b0  38 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |8...............|
000003c0  08 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000003d0  45 00 00 00 04 00 00 00  40 00 00 00 00 00 00 00  |E.......@.......|
000003e0  00 00 00 00 00 00 00 00  a0 01 00 00 00 00 00 00  |................|
000003f0  18 00 00 00 00 00 00 00  08 00 00 00 06 00 00 00  |................|
00000400  08 00 00 00 00 00 00 00  18 00 00 00 00 00 00 00  |................|
00000410  01 00 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................|
00000420  00 00 00 00 00 00 00 00  b8 00 00 00 00 00 00 00  |................|
00000430  d8 00 00 00 00 00 00 00  09 00 00 00 08 00 00 00  |................|
00000440  08 00 00 00 00 00 00 00  18 00 00 00 00 00 00 00  |................|
00000450  09 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  |................|
00000460  00 00 00 00 00 00 00 00  90 01 00 00 00 00 00 00  |................|
00000470  0e 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000480  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000490  11 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  |................|
000004a0  00 00 00 00 00 00 00 00  b8 01 00 00 00 00 00 00  |................|
000004b0  54 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |T...............|
000004c0  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000004d0
  
可利用二进制工具readelf, objdump来分析该可重定位文件是怎么排列的.  
分析可重定位文件(hello.o) 
可以看到分文件由"*"号附近分为两部分(都是十六进制):  
- 00000000~00000200
 - 00000210~ 00000250~ 000004c0
   
第1部分是ELF头和各个section的内容.  第2部分是描述各个sction的section header的结构体内容.  
$ readelf -h hello.o
ELF 头:
  Magic:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  类别:                              ELF64
  数据:                              2 补码,小端序 (little endian)
  版本:                              1 (current)
  OS/ABI:                            UNIX - System V
  ABI 版本:                          0
  类型:                              REL (可重定位文件)
  系统架构:                          Advanced Micro Devices X86-64
  版本:                              0x1
  入口点地址:              0x0
  程序头起点:              0 (bytes into file)
  Start of section headers:          528 (bytes into file)
  标志:             0x0
  本头的大小:       64 (字节)
  程序头大小:       0 (字节)
  Number of program headers:         0
  节头大小:         64 (字节)
  节头数量:         11
  字符串表索引节头: 10
  
可以看到section header是从528(十六进制为210)开始的, 且节头为64字节:  
typedef struct {
	Elf64_Word	sh_name; 
	Elf64_Word	sh_type; 
	Elf64_Xword	sh_flags; 
	Elf64_Addr	sh_addr; 
	Elf64_Off	sh_offset; 
	Elf64_Xword	sh_size; 
	Elf64_Word	sh_link; 
	Elf64_Word	sh_info; 
	Elf64_Xword	sh_addralign; 
	Elf64_Xword	sh_entsize; 
} Elf64_Shdr; 
  
利用  
readelf -SW hello.o
  
可以得到各个section的信息:  
There are 11 section headers, starting at offset 0x210:
节头:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        0000000000000000 000040 00000b 00  AX  0   0  1
  [ 2] .data             PROGBITS        0000000000000000 00004b 000000 00  WA  0   0  1
  [ 3] .bss              NOBITS          0000000000000000 00004b 000000 00  WA  0   0  1
  [ 4] .comment          PROGBITS        0000000000000000 00004b 00002e 01  MS  0   0  1
  [ 5] .note.GNU-stack   PROGBITS        0000000000000000 000079 000000 00      0   0  1
  [ 6] .eh_frame         PROGBITS        0000000000000000 000080 000038 00   A  0   0  8
  [ 7] .rela.eh_frame    RELA            0000000000000000 0001a0 000018 18   I  8   6  8
  [ 8] .symtab           SYMTAB          0000000000000000 0000b8 0000d8 18      9   8  8
  [ 9] .strtab           STRTAB          0000000000000000 000190 00000e 00      0   0  1
  [10] .shstrtab         STRTAB          0000000000000000 0001b8 000054 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)
  
00000210~ 00000250全是0, 对于index[0]的section.  同理,下面的也是各个section header.  下一个的sh_name 1b为偏移, 刚好为1b8+1b=1d3 是.text的名字, 以此类推.  
可以看到其偏移为40, 大小为b, 使用objdump -dr hello.o可以看到其二进制代码为:  
$objdump -dr hello.o
hello.o:     文件格式 elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	b8 00 00 00 00       	mov    $0x0,%eax
   9:	5d                   	pop    %rbp
   a:	c3                   	retq   
  
而对应的偏移[0x40,0x40 + 0xb)的位置信息:  55 48 89 e5 b8 00 00 00 00 5d c3  刚好为该段代码的二进制.  
接下来节.data, .bss大小都为0  .comment是[0x4b, 0x4b+2e), 即[0x4b, 0x79),  从二进制看  00000040 00 47 43 43 3a  00000050 20 28 47 4e 55 29 20 38 2e 35 2e 30 20 32 30 32  00000060 31 30 35 31 34 20 28 52 65 64 20 48 61 74 20 38  00000070 2e 35 2e 30 2d 31 30 29 00  
为comment信息 GCC: (GNU) 8.5.0 210514 (Red Hat 8.5.0-10)  
接下来是.note.GNU-stack, 大小都为0.  
接着是.eh_frame [0x80, 0x80+38), 因为对其是8, 所以从0x80开始.  具体内容有兴趣可继续研究.  
接下来是.symtab, [0xb8, 0xb8+0xd8), 即[0xb8, 0x190),  typedef struct  {  Elf64_Word st_name; /* Symbol name (string tbl index) /  unsigned char st_info; / Symbol type and binding /  unsigned char st_other; / Symbol visibility /  Elf64_Section st_shndx; / Section index /  Elf64_Addr st_value; / Symbol value /  Elf64_Xword st_size; / Symbol size */  } Elf64_Sym;  共9个符号入口9x24=216=0xb8  
接下来是.rela.eh_frame是放了一个重定位, 对于该机器来说, 一个重定位大小为0x18,即24字节.  为  typedef struct elf_internal_rela {  bfd_vma r_offset; /* Location at which to apply the action /  bfd_vma r_info; / Index and Type of relocation /  bfd_vma r_addend; / Constant addend used to compute value */  } Elf_Internal_Rela;  内容;  所以该节大小都是24(0x18)的整数倍.  
…  
参考文献 
Linux ELF 详解2 – Section Header & Section https://blog.csdn.net/helowken2/article/details/113757332 
                
                
                
        
        
    
  
 
 |