ELF (Executable Linkable Format,wiki chs)是Linux參考COFF(Common Object File Format)規范而定義的可執行文件格式。
可執行文件、共享目標文件(*.so)、目標中間文件(又稱可重定位文件,*.o)、核心轉儲文件(Core Dump File)都是ELF文件。
按位數可分為:elf32和elf64;支持cpu架構有:aarch64(即:arm64)、arm等。
ELF可能按照不同的字節序(Byte Order)來存儲。例如:elf32-bigarm是大端(Big-endian)存儲;elf64-littleaarch64是小端(Little-endian)存儲。
與COFF一樣,ELF也是基於段(Segment,有時也被叫節Section)的結構。其文件結構如下:
ELF頭(ELF Header):ELF魔數、文件機器字節長度、數據存儲方式(大小端)、版本、運行平台、ABI版本、ELF重定位類型、硬件平台及版本、入口地址、程序頭入口和長度、段表的位置和長度、段的數量。
段表(Section header table):描述了ELF各個段的基本信息,如:每個段的段名、段的長度、在文件中偏移、讀寫權限及段的其他屬性。編譯器、鏈接器和裝載器都是依靠段表來定位和訪問各個段的屬性的。
段的類型:
常量 | 值 | 含義 |
SHT_NULL | 0 | 無效段 |
SHT_PROGBITS | 1 | 程序段、代碼段、數據段都是這種類型 |
SHT_SYMTAB | 2 | 該段的內容為符號表 |
SHT_STRTAB | 3 | 該段的內容為字符串表 |
SHT_RELA | 4 | 重定位表,包含重定位信息 |
SHT_HASH | 5 | 符號表的哈希表 |
SHT_DYNAMIC | 6 | 動態鏈接信息 |
SHT_NOTE | 7 | 提示性信息 |
SHT_NOBITS | 8 | 表示該段在文件中沒有內容。如:bss段 |
SHT_REL | 9 | 該段包含了重定位信息 |
SHT_SHLIB | 10 | 保留 |
SHT_DNYSYM | 11 | 動態鏈接的符號表 |
段的標志位表示該段在進程虛擬空間中的屬性。包括:是否可寫(SHF_WRITE),是否需要分配空間(SHF_ALLOC)及是否可執行(SHF_EXECINSTR)。
常見的段如下:
段名 | 類型 | 標志位 | 說明 |
.text | SHT_PROGBITS | SHF_ALLOC + SHF_EXECINSTR |
代碼段
存放程序的可執行代碼 |
.data .data1 |
SHT_PROGBITS | SHF_ALLOC + SHF_EXECINSTR |
數據段
存放如下內容: ① 顯示初始化為非0的局部靜態變量 ② 顯示初始化為非0的全局變量 |
.rela.text .rel.text |
SHT_RELA | 代碼段重定位表
存在於目標中間文件(又稱可重定位文件,*.o)中,用於鏈接時重定位(為靜態重定位) |
|
.rela.data .rel.data |
SHT_RELA | 數據段重定位表
存在於目標中間文件(又稱可重定位文件,*.o)中,用於鏈接時重定位(為靜態重定位) |
|
.rodata .rodata1 |
SHT_PROGBITS | SHF_ALLOC |
只讀數據段
存放如下內容: ① 字符串常量 ② 全局const變量 |
.bss | SHT_NOBITS | SHF_ALLOC + SHF_WRITE |
bss段 這個段在程序運行時,在內存中會被清零 在ELF文件中不占用空間
存放如下內容: ① 未初始化的全局變量 ② 未初始化的局部靜態變量 ③ 顯示初始化為0的局部靜態變量 ④ 顯示初始化為0的全局變量 |
.tdata | SHF_ALLOC + SHF_WRITE | 用來保存線程局部存儲的初始化數據。 默認情況下,每次進程啟動新的線程時,系統會產生一份.tdata副本。 |
|
.tbss | SHF_ALLOC + SHF_WRITE | 用來保存線程局部存儲的未初始化數據。 默認情況下,每次進程啟動新的線程時,系統會產生一份.tbss副本,並將它的內容初始化為0。 |
|
.data.rel.ro | SHF_ALLOC(SHF_WRITE) | 保存的是程序的只讀數據,與.rodata類似,唯一不同的是它在重定位時會被改寫,然后將會被置為只讀。 | |
.dynamic | SHT_DYNAMIC | SHF_ALLOC + SHF_WRITE 注:在某些系統,可能是只讀的,沒有SHF_WRITE標志位 |
動態鏈接信息
① 依賴於哪些共享對象 ② 動態鏈接符號表(.dynsym)的位置 ③ 動態鏈接重定位表(.rela.dyn)的位置 ④ 共享對象初始化代碼的地址 |
.plt | SHF_ALLOC + SHF_EXECINSTR | 用於支持延遲綁定,這些指令是用來計算外部函數的最終地址 |
|
.got | SHF_ALLOC + SHF_WRITE | 全局偏移表 (Global Offset Table,GOT) 存放外部變量的地址
GOT表中的地址需要動態鏈接器在裝載模塊,進行地址重定位時進行填充。 在訪問外部符號,可以先通過相對地址找到GOT表中相關的項,再從中取出最終地址 |
|
.got.plt | SHF_ALLOC + SHF_WRITE | 使用PLT(Procedure Linkage Table,過程鏈接表)來實現對外部函數延遲綁定(第一次用到時才進行綁定) 以此來提升程序的啟動速度
第一項保存的是“.dynamic”段的地址 第N項保存的是運用plt段的指令計算得到的外部函數的最終地址(動態鏈接器重定位得到外部函數的地址后,會寫入在這里) |
|
.rela.dyn .rel.dyn |
SHT_RELA | SHF_ALLOC | .dynsym段的重定位表
對數據引用的修正,它所修正的位置存放在“.got”以及數據段 |
.rela.plt .rel.plt |
SHT_RELA | SHF_ALLOC | .plt段的重定位表 對函數引用的修正,它所修正的位置存放在“.got.plt” |
.dynstr | SHF_ALLOC | 動態符號字符串表(Dynamic String Table)
存放動態鏈接符號的符號名 |
|
.dynsym | SHF_ALLOC | 動態符號表(Dynamic Symbol Table)
① 導入符號(Import Symbol) ② 導出符號(Export Symbol)
編譯選項開啟:-fvisibility=hidden -fvisibility-inlines-hidden,默認不導出so中的符號 |
|
.hash | SHT_HASH | SHF_ALLOC |
動態符號哈希表
提升動態符號的查找效率 |
.comment | SHT_PROGBITS |
|
注釋信息段
存放的是編譯器版本信息,比如字符串:"GCC:(GNU)4.2.0" |
.init | SHF_ALLOC + SHF_EXECINSTR | 程序執行前的初始化代碼,這些代碼早於main函數被執行,多數被用作實現C++全局構造 |
|
.fini | SHF_ALLOC + SHF_EXECINSTR | 程序退出時執行的代碼,這些代碼晚於main函數執行,多數被用作實現C++全局析構 | |
.init_array | SHT_PROGBITS | SHF_ALLOC + SHF_EXECINSTR |
包含一些程序或共享對象剛開始初始化時所須要執行的函數指針 |
.fini_array | SHT_PROGBITS | SHF_ALLOC + SHF_EXECINSTR | 包含一些程序或共享對象退出時須要執行的函數指針 |
.preinit_array | 保存的是早於初始化階段執行的函數指針數組,這些函數會在.init_array的函數指針數組之前被執行 | ||
.ctors | 保存的是全局構造函數指針 |
||
.dtors | 保存的是全局析構函數指針 |
||
.interp | SHT_PROGBITS | 包含動態鏈接器的路徑(如:/lib/ld-linux.so.2) interp是interpreter(解釋器)的縮寫
系統在對可執行文件進行加載時,會從該段尋找並裝載該可執行文件所需的動態鏈接器。 |
|
.shstrtab | SHT_STRTAB | 段表字符串表(Section String Table) 用於存放各個段的名字 |
|
.note.GNU-stack | SHT_NOTE | 堆棧提示段 | |
.note.android.ide | SHT_NOTE | 記錄使用的android ndk的版本 | |
.note.gnu.build-id | SHT_NOTE | 鏈接時的唯一標識 | |
.note.ABI-tag | SHT_NOTE | 指定程序的ABI | |
.eh_frame | SHT_PROGBITS | c++異常處理相關的內容 詳見:Exception Frames
異常時棧幀unwind信息(Exception Handling Frame unwinding information) Call Frame Information(CFI)信息,保存了函數的調用關系,可以用於異常發生后的棧回溯
編譯時,帶上-funwind-tables,可以去除該段 -fno-asynchronous-unwind-tables |
|
.eh_frame_hdr | SHT_PROGBITS | c++異常處理相關的內容
包含了對.eh_frame的補充信息 ① 一個指針指向.eh_frame包含的數據起始地址 |
|
.gcc_except_table | SHT_PROGBITS | try catch異常處理相關的信息:如異常時的對象清理邏輯 | |
.jcr | Java類注冊信息 | ||
.gnu.version | 符號版本相關
所有動態符號的版本信息,它和.dynsym是一一對應的 為0表示內部定義的local的符號,1表示內部定義的global符號 其他的值則來自於.gnu_version_d的Index和.gnu_version_r的Version,前者表示導出的符號版本信息,后者表示導入的符號版本信息 |
||
.gnu.version_d | 符號版本相關
版本定義信息 |
||
.gnu.version_r | 符號版本相關 |
||
.debug_str .debug_loc .debug_abbrev .debug_info .debug_ranges .debug_macinfo .debug_line .debug_aranges |
SHT_PROGBITS | 調試信息
ELF采用DWARF(Debug With Arbitrary Record Format)的標准調試信息格式來存放調試信息 |
|
.symtab | SHT_SYMTAB | 如果有其他裝載的段用到該段,則有SHF_ALLOC標志位 | 符號表(Symbol Table) 保存鏈接時所需要的符號信息 |
.strtab | SHT_STRTAB | 如果有其他裝載的段用到該段,則有SHF_ALLOC標志位 | 字符串表(String Table) 通常是符號表里的符號名所需要的字符串
注:目標中間文件(又稱可重定位文件,*.o)也存在該段 |
readelf
llvm-readelf.exe所在目錄在:<android-ndk>\toolchains\llvm\prebuilt\windows-x86_64\bin
llvm-readelf.exe -S libUE4.so // 輸出libUE4.so段表中各個段的信息
There are 27 section headers, starting at offset 0xf2c1650: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align ;Size為段的長度;Offset為段在文件中偏移位置 [ 0] NULL 0000000000000000 00000000 ;第一個元素是無效的段描述符,類型為NULL 0000000000000000 0000000000000000 0 0 0 [ 1] .note.android.ide NOTE 0000000000000270 00000270 ;記錄使用的android ndk的版本的段 0000000000000098 0000000000000000 A 0 0 4 [ 2] .note.gnu.build-i NOTE 0000000000000308 00000308 ;鏈接時的唯一標識 0000000000000024 0000000000000000 A 0 0 4 [ 3] .dynsym DYNSYM 0000000000000330 00000330 0000000000dee838 0000000000000018 A 8 1 8 [ 4] .gnu.version VERSYM 0000000000deeb68 00deeb68 000000000012935a 0000000000000002 A 3 0 2 [ 5] .gnu.version_r VERNEED 0000000000f17ec4 00f17ec4 0000000000000080 0000000000000000 A 8 4 4 [ 6] .gnu.hash GNU_HASH 0000000000f17f48 00f17f48 00000000003e61c8 0000000000000000 A 3 0 8 [ 7] .hash HASH 00000000012fe110 012fe110 00000000004a4d70 0000000000000004 A 3 0 4 [ 8] .dynstr STRTAB 00000000017a2e80 017a2e80 000000000326c716 0000000000000000 A 0 0 1 [ 9] .rela.dyn RELA 0000000004a0f598 04a0f598 0000000001a9a510 0000000000000018 A 3 0 8 [10] .rela.plt RELA 00000000064a9aa8 064a9aa8 00000000000041b8 0000000000000018 AI 3 22 8 [11] .rodata PROGBITS 00000000064adc80 064adc80 ; 只讀數據段 0000000000b19d08 0000000000000000 AMS 0 0 64 [12] .gcc_except_table PROGBITS 0000000006fc7988 06fc7988 000000000005e32c 0000000000000000 A 0 0 4 [13] .eh_frame_hdr PROGBITS 0000000007025cb4 07025cb4 00000000003aed74 0000000000000000 A 0 0 4 [14] .eh_frame PROGBITS 00000000073d4a28 073d4a28 0000000000e29424 0000000000000000 A 0 0 8 [15] .text PROGBITS 00000000081fe000 081fe000 ; 代碼段 0000000006464320 0000000000000000 AX 0 0 16 [16] .plt PROGBITS 000000000e662320 0e662320 0000000000002bf0 0000000000000000 AX 0 0 16 [17] .data.rel.ro PROGBITS 000000000e665000 0e665000 0000000000b40f88 0000000000000000 WA 0 0 16 [18] .fini_array FINI_ARRAY 000000000f1a5f88 0f1a5f88 0000000000000010 0000000000000008 WA 0 0 8 [19] .init_array INIT_ARRAY 000000000f1a5f98 0f1a5f98 0000000000002918 0000000000000008 WA 0 0 8 [20] .dynamic DYNAMIC 000000000f1a88b0 0f1a88b0 00000000000002b0 0000000000000010 WA 8 0 8 [21] .got PROGBITS 000000000f1a8b60 0f1a8b60 00000000000e3280 0000000000000000 WA 0 0 8 [22] .got.plt PROGBITS 000000000f28bde0 0f28bde0 0000000000001600 0000000000000000 WA 0 0 8 [23] .data PROGBITS 000000000f28e000 0f28e000 ; 數據段 0000000000033220 0000000000000000 WA 0 0 16 [24] .bss NOBITS 000000000f2c1240 0f2c1220 ; BSS段 該段在文件中不存在內容 000000000060aaa8 0000000000000000 WA 0 0 64 [25] .comment PROGBITS 0000000000000000 0f2c1220 ; 注釋信息段 0000000000000328 0000000000000001 MS 0 0 1 [26] .shstrtab STRTAB 0000000000000000 0f2c1548 0000000000000104 0000000000000000 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), p (processor specific)
注:以上段的Offset是基於ELF文件起始處
以uam為例,libUE4.so的大小對比:
配置 | so size | debug so size |
Debug | 532MB | 2.07GB |
DebugGame | 389MB | 2.48GB |
Development | 343MB | 2.52GB |
Test | 175MB | 2.11GB |
Shipping | 148MB | 1.81GB |
注:對debug so執行strip -S命令去除掉調試信息,就得到so文件
不同配置的libUE4.so(非debug)各個段的大小對比(單位為byte):
段名 | Debug | DebugGame | Development | Test | Shipping |
.note.android.ident | 152 | 152 | 152 | 152 | 152 |
.note.gnu.build-id | 36 | 36 | 36 | 36 | 36 |
.dynsym | 36937800 | 21539400 | 19843704 | 391176 | 195792 |
.gnu.version | 3078150 | 1794950 | 1653642 | 32598 | 16316 |
.gnu.version_r | 128 | 128 | 128 | 128 | 128 |
.gnu.hash | 11885344 | 6580208 | 6226960 | 110088 | 53272 |
.hash | 12312608 | 7179808 | 6614576 | 130400 | 65272 |
.dynstr | 166468508 | 88218683 | 81551149 | 854321 | 244190 |
.rela.dyn | 35363208 | 34303248 | 34031904 | 29215536 | 27984648 |
.rela.plt | 19488 | 19416 | 19320 | 18768 | 17760 |
.rodata | 15322736 | 15091552 | 15056704 | 11529632 | 10449008 |
.gcc_except_table | 554452 | 597372 | 662504 | 650196 | 544796 |
.eh_frame_hdr | 13486636 | 6668844 | 5787516 | 3948092 | 3640124 |
.eh_frame | 51114172 | 25550380 | 22173820 | 15188700 | 13873572 |
.text | 194929800 | 184359724 | 150390280 | 107480476 | 84720920 |
.plt | 13024 | 12976 | 12912 | 12544 | 11872 |
.data.rel.ro | 14868208 | 14560768 | 14509008 | 13900256 | 13422608 |
.fini_array | 16 | 16 | 16 | 16 | 16 |
.init_array | 11432 | 11288 | 11288 | 11232 | 10320 |
.dynamic | 736 | 736 | 736 | 736 | 736 |
.got | 1234496 | 1196112 | 1189088 | 46504 | 34848 |
.got.plt | 6520 | 6496 | 6464 | 6280 | 5944 |
.data | 398160 | 276400 | 234256 | 161744 | 157440 |
.bss | 6143992 | 6076552 | 6051080 | 5332728 | 4972416 |
.comment | 747 | 747 | 747 | 747 | 747 |
.shstrtab | 260 | 260 | 260 | 260 | 260 |
llvm-readelf.exe -t libUE4.so // 輸出libUE4.so段表中各個段的信息
llvm-readelf.exe -h libUE4.so // 輸出libUE4.so的ELF頭的信息
llvm-readelf.exe -l libUE4.so // 輸出libUE4.so的program headers
llvm-readelf.exe -e libUE4.so // 等價於-h -l -S輸出的信息
llvm-readelf.exe -d libUE4.so // 輸出libUE4.so的dynamic段的信息
llvm-readelf.exe -r libUE4.so // 輸出libUE4.so的重定位信息(.rela.dyn段和.rela.plt段)
llvm-readelf.exe --dyn-syms -d -C -W libUE4.so // 輸出libUE4.so的dynsym段中所有符號(不截斷),且自動對c++符號名進行反修飾(Demangle),並輸出libUE4.so依賴的so文件 注:Ndx為UND時,表示是一個導入符號
。。。 。。。 37263: 000000000a0cca50 144 FUNC GLOBAL DEFAULT 15 uprv_stricmp_64 37264: 000000000b1deeb8 56 OBJECT GLOBAL DEFAULT 17 CMS_ReceiptRequest_it 37265: 000000000a3efec4 16 FUNC GLOBAL DEFAULT 15 hb_font_is_immutable 37266: 0000000009f258f8 164 FUNC GLOBAL DEFAULT 15 g6_toolkit_manager::LoginRsp::default_instance() 37267: 0000000009ffdde4 164 FUNC GLOBAL DEFAULT 15 G6ToolKit::google::protobuf::OneofOptions::default_instance() 37268: 0000000002778899 18 OBJECT GLOBAL DEFAULT 11 typeinfo name for icu_64::UObject 37269: 000000000a3e8278 92 FUNC GLOBAL DEFAULT 15 hb_segment_properties_equal 37270: 000000000a462248 68 FUNC GLOBAL DEFAULT 15 png_reciprocal 37271: 0000000009a955b4 236 FUNC GLOBAL DEFAULT 15 ak_rpmalloc_initialize 37272: 0000000009edf7bc 388 FUNC WEAK DEFAULT 15 void physx::RepXPropertyFilter<physx::Sn::RepXVisitorWriter<physx::PxVehicleClutchData> >::operator()<588u, physx::PxVehicleClutchData, unsigned int, unsigned int>(physx::PxPropertyInfo<588u, physx::PxVehicleClutchData, unsigned int, unsigned int> const&, unsigned int) 37273: 000000000a0070b4 56 FUNC GLOBAL DEFAULT 15 G6ToolKit::google::protobuf::SourceCodeInfo_Location::CopyFrom(G6ToolKit::google::protobuf::SourceCodeInfo_Location const&) 37274: 000000000a32976c 36 FUNC GLOBAL DEFAULT 15 d2i_RSA_PUBKEY_bio Dynamic section at offset 0xb211b58 contains 52 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libGLESv3.so] 0x0000000000000001 (NEEDED) Shared library: [libEGL.so] 0x0000000000000001 (NEEDED) Shared library: [libandroid.so] 0x0000000000000001 (NEEDED) Shared library: [libOpenSLES.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so] 0x0000000000000001 (NEEDED) Shared library: [libdl.so] 0x0000000000000001 (NEEDED) Shared library: [liblog.so] 0x0000000000000001 (NEEDED) Shared library: [libm.so] 0x0000000000000001 (NEEDED) Shared library: [libz.so] 0x0000000000000001 (NEEDED) Shared library: [libTDataMaster.so] 0x0000000000000001 (NEEDED) Shared library: [libMSDKCore.so] 0x0000000000000001 (NEEDED) Shared library: [libGPM.so] 0x0000000000000001 (NEEDED) Shared library: [libgrobot.so] 0x0000000000000001 (NEEDED) Shared library: [libavcodec.so] 0x0000000000000001 (NEEDED) Shared library: [libavfilter.so] 0x0000000000000001 (NEEDED) Shared library: [libavformat.so] 0x0000000000000001 (NEEDED) Shared library: [libavutil.so] 0x0000000000000001 (NEEDED) Shared library: [libswresample.so] 0x0000000000000001 (NEEDED) Shared library: [libswscale.so] 0x0000000000000001 (NEEDED) Shared library: [libgcloudcore.so] 0x0000000000000001 (NEEDED) Shared library: [libgcloud.so] 0x0000000000000001 (NEEDED) Shared library: [libhttpdns.so] 0x0000000000000001 (NEEDED) Shared library: [libHttpDnsPlugin.so] 0x0000000000000001 (NEEDED) Shared library: [libtersafe.so] 0x0000000000000001 (NEEDED) Shared library: [libGVoice.so] 0x0000000000000001 (NEEDED) Shared library: [libCrashSight.so] 0x0000000000000001 (NEEDED) Shared library: [libc++_shared.so] 0x000000000000000e (SONAME) Library soname: [libUE4.so] 0x000000000000001e (FLAGS) SYMBOLIC BIND_NOW 0x000000006ffffffb (FLAGS_1) NOW 0x0000000000000007 (RELA) 0x3a7500 0x0000000000000008 (RELASZ) 29283912 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000006ffffff9 (RELACOUNT) 1210342 0x0000000000000017 (JMPREL) 0x1f94b48 0x0000000000000002 (PLTRELSZ) 19704 (bytes) 0x0000000000000003 (PLTGOT) 0xb221058 0x0000000000000014 (PLTREL) RELA 0x0000000000000006 (SYMTAB) 0x330 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000005 (STRTAB) 0x1721c4 0x000000000000000a (STRSZ) 2315065 (bytes) 0x000000006ffffef5 (GNU_HASH) 0xecdf0 0x0000000000000004 (HASH) 0x1294e4 0x0000000000000019 (INIT_ARRAY) 0xb20ef90 0x000000000000001b (INIT_ARRAYSZ) 11208 (bytes) 0x000000000000001a (FINI_ARRAY) 0xb20ef80 0x000000000000001c (FINI_ARRAYSZ) 16 (bytes) 0x000000006ffffff0 (VERSYM) 0xda9b8 0x000000006ffffffe (VERNEED) 0xeccf0 0x000000006fffffff (VERNEEDNUM) 8 0x0000000000000000 (NULL) 0x0
llvm-readelf.exe -s -W libUE4.so // 輸出libUE4.so的.symtab段(調試符號)中所有符號(不截斷)
llvm-readelf.exe --debug-dump=frames-interp libUE4.so // 輸出libUE4.so的eh_frame段的信息
llvm-readelf.exe -V libUE4.so // 輸出libUE4.so的符號版本信息
llvm-readelf.exe -x.data libc++_shared.so // 以16進制的方式輸出libc++_shared.so的.data段內容到文本文件 注:libc++_shared.so來自於strip后的<android-ndk>\sources\cxx-stl\llvm-libc++\libs\arm64-v8a\libc++_shared.so
llvm-readelf.exe -x.note.gnu.build-id libUE4.so // 以16進制的方式輸出libUE4.so的.note.gnu.build-id段內容 注:里面存儲着libUE4.so的BuildId,符號表匹配依賴這個 (BuildId: 72e1338dd3e2096ddc9555842ca24ecfafd2586e)
Hex dump of section '.note.gnu.build-id': 0x00000308 04000000 14000000 03000000 474e5500 ............GNU. 0x00000318 72e1338d d3e2096d dc955584 2ca24ecf r.3....m..U.,.N. 0x00000328 afd2586e ..Xn
llvm-readelf.exe -p.shstrtab libtestSo.so // 以字符串(char)的方式輸出libtestSo.so的.shstrtab段內容 注:utf16寬字符串會在解析時截斷
llvm-readelf.exe -c libssl.a // 輸出靜態庫libssl.a中包括各個中間目標文件(*.o)中的符號信息
llvm-readelf.exe -n libUE4.so // 輸出libUE4.so中所有note段的信息
llvm-readelf.exe -v // 輸出readelf的版本信息
llvm-readelf.exe --help // 輸出readelf的幫助信息
objdump
llvm-objdump.exe所在目錄在:<android-ndk>\toolchains\llvm\prebuilt\windows-x86_64\bin
llvm-objdump.exe -v // 輸出objdump的版本信息
llvm-objdump.exe --help // 輸出objdump的幫助信息
llvm-objdump.exe -i // 輸出支持的ELF的格式和架構(architecture)
llvm-objdump.exe -f libUE4.so // 輸出libUE4.so的簡要信息
llvm-objdump.exe -h libUE4.so // 輸出libUE4.so段表的信息 注:不輸出一些輔助性的段(如:符號表、字符串表、段名字符串表、重定位表等)
llvm-objdump.exe -x libUE4.so // 輸出llibUE4.so整個頭的信息 注:包括段表的信息
llvm-objdump.exe -p libUE4.so // 輸出llibUE4.so的program headers和dynsym段基本信息
llvm-objdump.exe -d -s libUE4.so // 對libUE4.so中的代碼段進行反編譯,並以16進制的形式輸出
llvm-objdump.exe -a libpython2.7.a // 列出.a靜態庫中所有的目標中間文件(*.o)
llvm-objdump.exe -t libUE4.so // 顯示libUE4.so中的調試符號表
llvm-objdump.exe -T libtestSo.so // 輸出libtestSo.so的動態鏈接符號表(dynsym段)
llvm-objdump.exe -T -C libtestSo.so // 輸出libtestSo.so的動態鏈接符號表(dynsym段),並自動對c++符號名進行反修飾(Demangle)
llvm-objdump.exe -R libtestSo.so // 輸出libtestSo.so的動態鏈接重定位信息(.rela.dyn段和.rela.plt段)
llvm-objdump.exe -R -C libtestSo.so // 輸出libtestSo.so的動態鏈接重定位信息,並自動對c++符號名進行反修飾(Demangle)
llvm-objdump.exe -d libtestSo.so // 對libtestSo.so中的包含機器指令的段進行反匯編
llvm-objdump.exe -S libtestSo.so // 顯示libtestSo.so源代碼和機器指令的段的反匯編代碼(包含-d參數功能)
llvm-objdump.exe -D libtestSo.so // 對libtestSo.so所有的段進行反匯編
llvm-objdump.exe -r testSo.o // 顯示中間文件testSo.o中重定位信息
llvm-objdump.exe -s libtestSo.so // 以16進制的方式輸出libtestSo.so的內容
// 輸出libUE4.debug.so地址范圍為[0x0000000008277724, 0x0000000008277850]的機器指令進行反匯編,並自動其中c++符號名進行反修飾(Demangle)
llvm-objdump.exe -d -C libUE4.debug.so --start-address=0x0000000008277724 --stop-address=0x0000000008277850
注1:[0x0000000008277724, 0x0000000008277850]的機器指令對應UAkGameplayStatics::SetState(UAkStateValue const*, FName, FName)函數
注2:可通過命令:llvm-nm.exe -n -C libUE4.debug.so | findstr "UAkGameplayStatics::SetState"來獲取該函數的起始地址
// 輸出libUE4.debug.so地址范圍為[0x0000000008277724, 0x0000000008277850]的機器指令進行反匯編(配合源代碼),並自動其中c++符號名進行反修飾(Demangle)
llvm-objdump.exe -S -C libUE4.debug.so --start-address=0x0000000008277724 --stop-address=0x0000000008277850 --include="D:\svn\MyGame\Plugins\Wwise\Source\AkAudio\Private"
注:可通過命令:llvm-addr2line.exe -e libUE4.debug.so 0000000008277724來獲取地址為0000000008277724(該地址為RVA地址,即已減去libUE4.so模塊的基地址)對應的源代碼文件和行數,得到如下結果
E:/tiyan/MyGame/Plugins/Wwise/Source/AkAudio/Private/AkGameplayStatics.cpp:377
參考
Executable and Linkable Format (ELF)