elf(executable linkable format)格式是linux中的可執行檔案格式。在linux中,可執行檔案、目標檔案、動態鏈結庫(linux的.so)、靜態鏈結庫(linux下的.a檔案)都是elf格式的檔案。
elf檔案標準裡面把elf格式檔案分為了4類。可重定位檔案(relocatable file)、可執行檔案(executable file)、共享目標檔案(shared object file)、核心轉儲檔案(core dump file)。可以在bash中用file命令來檢視相應的檔案格式。
$ file a.o
a.o: elf 64-bit lsb relocatable, x86-64, version 1 (sysv), not stripped
$ file a.out
a.out: elf 64-bit lsb executable, x86-64, version 1 (sysv), dynamically linked, interpreter /lib64/l, for gnu/linux 2.6.32, buildid[sha1]
=697f760e13fbf75e42a80bbfb459678d805d51cc, not stripped
$ file liba.so
liba.so: elf 64-bit lsb shared object, x86-64, version 1 (gnu/linux), dynamically linked, buildid[sha1]
=915c865179f6bb09fe6c36c3649e816fb986a1e1, not stripped
正確理解"section"和"segment"的概念有助於我們理解目標檔案和可執行檔案。從本質上講,"section"和"segment"都是elf檔案中的一小塊區域。"section"是相對於目標檔案的乙個概念,乙個目標檔案由elf頭和若干section組成,如目標檔案中的**段、資料段、bss段等。"segment"是相對於可執行檔案的乙個概念。我們知道,可執行檔案是由多個目標檔案鏈結起來的,鏈結器會將目標檔案中具有相同性質的段合併到一起,如將各個目標檔案中的.text段合併成乙個.text段,將各個.data段合併成乙個.data段。此時,這些合併後的.text段、.data段以section的形式存放在可執行檔案中。那麼為什麼要在可執行檔案中引入segment的概念呢?因為直接將可執行檔案按section為劃分單位對映到虛擬記憶體空間會浪費大量的記憶體空間,因為虛擬記憶體是按頁對齊的。而作業系統在將可執行檔案載入到虛擬記憶體空間時,往往只關心每個section的許可權(可讀、可寫、可執行),於是大佬們決定把具有相同許可權的section合併成乙個segment對映到虛擬記憶體空間。因此,segment的概念實際上是從裝載的角度重新劃分了elf的各個section,鏈結器會盡量將具有相同許可權的section分配在同乙個空間,這些section被稱作為乙個segment,作業系統正是按照segment來將可執行檔案對映到虛擬記憶體空間的,而不是按section。
目標檔案是elf格式的檔案,整個目標檔案被分成多個具有一定長度的區域,每個區域被稱為段,這裡的段指的是乙個section。例如,.text段就是目標檔案中用來存放程式源**的地方,這些源**被翻譯成機器指令存放在**段。.data段是用來存放初始化的全域性變數和區域性靜態變數的地方。
$ objdump -h ******section.o # 引數 -h 表示把elf檔案的各個段的基本資訊列印出來
# size命令也可以用來檢視elf檔案的**段、資料段和bss段的長度,-a指定執行模式為"system v compatibility mode"
$ size -a ******section.o
# **段
$ objdump -s -d ******section.o # -s 表示將所有段的內容以16進製制方式列印,-d將所有包含指令的段反彙編
在linux中,elf檔案的最前面是elf檔案頭,檔案頭的資訊在32位機器中是由elf32_ehdr結構體來描述的,在64位機器上用elf64_ehdr結構體來描述。
$ readelf -h ******section.o # 檢視elf檔案頭
$ hexdump -x ******section.o -n 64 # hexdump檢視二進位制檔案,-x表示以雙位元組16進製制顯示,-n顯示指定位元組
上圖是64位機器下elf檔案頭,共64個位元組,下面對其中的部分選項進行說明。
段表描述了elf檔案中各個段的資訊,例如段名、段的長度、在檔案中的偏移、讀寫許可權等。段表中的每一項用乙個結構體來描述,在64位機器中是elf64_shdr(32機器中是elf32_shdr),段表本質上就是乙個陣列,陣列中的每一項是乙個elf64_shdr(32機器中是elf32_shdr)結構體。
$ readelf -s ******section.o # 檢視段表
重定位表用來儲存與重定位相關的資訊,它在elf檔案中往往是乙個或多個段,每個需要被重定位的elf段都有乙個對應的重定位表,如**段.txt的重定位表為.rel.text。重定位表本質上是乙個elf64_rel(32機器中是elf32_rel)結構的陣列。elf64_rel的大小為16位元組(elf32_rel為8位元組),有兩個成員變數:r_offset、r_info。
$ objdump -r ******section.o # 檢視目標檔案中需要重定位的符號
字串表在elf檔案中也以段的形式儲存,用來儲存elf檔案中的段名、變數名等。常見的字串表有兩個,.strtab: 用來儲存普通的字串;.shstrtab: 用來儲存段表中用到的字串。在字串表中,所有的字串連續儲存在表中,用空字元(』\0』)隔開,字串表的第乙個字元為空字元。在elf檔案中只需要給出字串在字串表中的首位址的索引,就能夠在字串表中獲取到這個字串。
符號表是elf檔案中的乙個段,段名一般叫.symtab
程式頭表是elf可執行檔案中的乙個段,用來儲存"segment"的資訊。elf目標檔案中沒有程式頭表。程式頭表本質上是乙個陣列,陣列元素是乙個elf64_phdr(32為機器為elf32_phdr)結構體。
ELF格式檔案和BIN檔案的區別
elf檔案格式是乙個開放標準,各種unix系統的可執行檔案都採用elf格式,它有三種不同的型別 elf格式提供了兩種不同的視角,鏈結器把elf檔案看成是section的集合,而載入器把elf檔案看成是segment的集合。在linux os上,為了執行可執行檔案,他們是遵循elf格式的,通常gcc ...
ELF格式檔案特點的簡單說明
elf 可執行連線檔案格式。elf檔案優點 1.支援不同平台上的交叉編譯和交叉鏈結,可移植性性強 與linux下其他可執行檔案 a.out,cof 相比 2.在執行時支援動態鏈結共享庫 elf檔案型別 1.可重定位檔案 使用者和其他目標檔案一起建立可執行檔案或者共享目標檔案,例如lib a檔案 2....
elf格式轉換為hex格式檔案的兩種方法
這周工作終於不太忙了,可以寫點筆記總結一下了。之前的文章如何在keil mdk開發環境生成bin格式檔案,介紹了如何在keil開發環境使用fromelf軟體,將生成的axf檔案轉換為bin檔案,這次我們再來介紹一下如何將elf檔案轉換為hex檔案。elf executable and linkabl...