ELF目標檔案與readelf
readelf elf檔案格式分析
背景
目標檔案
首先需要介紹的概念是 目標檔案(Object file) 的概念。 目標檔案 是電腦科學中編譯器或彙編器處理原始碼後所生成的程式碼(目的碼,Object code)的計算機檔案,它常被稱作二進位制檔案(binaries)。這個檔案型別主要是區別於你看得懂的用人話寫的程式碼檔案(.c、.cpp etc.)、中間檔案(.i)、彙編檔案(.s)。常見的.exe、.dll、.so啥的都算目標檔案。
目標檔案有三種類型:
- 可重定位的物件檔案(Relocatable file)
由彙編器彙編生成的 .o 檔案(下面會詳細講到) - 可執行的物件檔案(Executable file)
可執行應用程式 - 可被共享的物件檔案(Shared object file)
動態庫檔案
編譯過程
編譯的過程如下圖所示

編譯過程
程式碼檔案經過語言前處理器、編譯器、彙編器和連結器處理,最終生成可執行目標檔案。
下面以一個簡單的c語言檔案為例:
sum.c原始檔內容如下:
int sum(int *a, int n) { int i, s = 0; for (i = 0; i < n; ++i) { s += a[i]; } return s; }
通過執行C前處理器(cpp)可以生成sum.i中間檔案:
# 1 "sum.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "sum.c" int sum(int *a, int n) { int i, s = 0; for (i = 0; i < n; ++i) { s += a[i]; } return s; }
通過執行C編譯器(cc1),將中間檔案生成為sum.s彙編檔案:
.file›"sum.i" .text .globlsum .type›sum, @function sum: .LFB0: .cfi_startproc movl$0, %eax movl$0, %edx jmp›.L2 .L3: movslq%edx, %rcx addl(%rdi,%rcx,4), %eax addl$1, %edx .L2: cmpl%esi, %edx jl.L3 rep ret .cfi_endproc .LFE0: .size›sum, .-sum .ident"GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-36)" .section.note.GNU-stack,"",@progbits
最終生成通過彙編器(as)生成一個可重定位目標檔案(reloacatable object file)。
什麼是ELF
系統裡的目標檔案是按照特定的目標檔案格式來組織的,各個系統的目標檔案格式都不相同。
從貝爾實驗室誕生的第一個Unix系統使用的是a.out格式(直到今天,可執行檔案仍然稱為a.out檔案)。Windows使用可移植可執行(PortableExecutable,PE)格式。Mac OS-X使用Mach-O格式。現代x86-64Linux和Unix系統使用可執行可連結格式(Executable and Linkable Format,ELF)。
ELF格式的檔案在Linux系統下有.axf、 .bin、 .elf、 .o、 .prx、 .puff、 .ko、 .mod和.so等等
readelf指令
前面介紹了這麼多ELF的背景知識,下面回來來說說readelf這個指令。這個指令正是用來檢視目標檔案的內容的。
ELF可重定位目標檔案的格式
典型格式
典型的ELF可重定位目標檔案的格式如下圖:

ELF可重定位目標檔案格式
其中:
-g -g
符號表部分解析
符號表每節定義如下:
typedef struct { intname;/* String table offset */ chartype:4,/* Function or data (4 bits) */ binding:4; /* Local or global (4 bits) */ charreserved;/* Unused */ short section;/* Section header index */ longvalue;/* Section offset or absolute address */ longsize;/* Object size in bytes */ } Elf64_Symbol;
具體解釋如下:

符號表思維導圖
舉個例子:chestnut:
以上面的sum.c生成的sum.o為例,我們選取 readelf
的 -all
引數輸出全部內容:
$readelf -all sum.o ELF Header: Magic:7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class:ELF64 Data:2's complement, little endian Version:1 (current) OS/ABI:UNIX - System V ABI Version:0 Type:REL (Relocatable file) Machine:Advanced Micro Devices X86-64 Version:0x1 Entry point address:0x0 Start of program headers:0 (bytes into file) Start of section headers:536 (bytes into file) Flags:0x0 Size of this header:64 (bytes) Size of program headers:0 (bytes) Number of program headers:0 Size of section headers:64 (bytes) Number of section headers:11 Section header string table index: 10 Section Headers: [Nr] NameTypeAddressOffset SizeEntSizeFlagsLinkInfoAlign [ 0]NULL000000000000000000000000 00000000000000000000000000000000000 [ 1] .textPROGBITS000000000000000000000040 000000000000001b0000000000000000AX001 [ 2] .dataPROGBITS00000000000000000000005b 00000000000000000000000000000000WA001 [ 3] .bssNOBITS00000000000000000000005b 00000000000000000000000000000000WA001 1 int sum(int *a, int n) 2 { [ 4] .commentPROGBITS00000000000000000000005b 000000000000002e0000000000000001MS001 [ 5] .note.GNU-stackPROGBITS000000000000000000000089 00000000000000000000000000000000001 [ 6] .eh_framePROGBITS000000000000000000000090 00000000000000300000000000000000A008 [ 7] .rela.eh_frameRELA0000000000000000000001a8 00000000000000180000000000000018I868 [ 8] .symtabSYMTAB0000000000000000000000c0 00000000000000d80000000000000018988 [ 9] .strtabSTRTAB000000000000000000000198 000000000000000b0000000000000000001 [10] .shstrtabSTRTAB0000000000000000000001c0 00000000000000540000000000000000001 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) There are no section groups in this file. There are no program headers in this file. Relocation section '.rela.eh_frame' at offset 0x1a8 contains 1 entries: OffsetInfoTypeSym. ValueSym. Name + Addend 000000000020000200000002 R_X86_64_PC320000000000000000 .text + 0 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.symtab' contains 9 entries: Num:ValueSize TypeBindVisNdx Name 0: 00000000000000000 NOTYPELOCALDEFAULTUND 1: 00000000000000000 FILELOCALDEFAULTABS sum.i 2: 00000000000000000 SECTION LOCALDEFAULT1 3: 00000000000000000 SECTION LOCALDEFAULT2 4: 00000000000000000 SECTION LOCALDEFAULT3 5: 00000000000000000 SECTION LOCALDEFAULT5 6: 00000000000000000 SECTION LOCALDEFAULT6 7: 00000000000000000 SECTION LOCALDEFAULT4 8: 000000000000000027 FUNCGLOBAL DEFAULT1 sum No version information found in this file.
其中第一部分是ELF頭(ELF header)中的描述資訊。(用 -h
引數可以單獨得到)。
最後一部分是符號表部分(用 -s
引數可以單獨得到該部分),前面八個條目是連結器內部使用的區域性符號,最後一行是全域性符號 sum
定義的條目。可以通過最後一行看出,它是一個位於.text節中偏移量為0處的27位元組函式。(Ndx部分表示在哪個節中,1表示.text節,3表示.data節,對應上面輸出的 Section Headers
部分)
檢視更多文章請訪問我的部落格——左旋異構
本文地址: 左旋異構 - ELF目標檔案與readelf