00. 目錄
文章目錄
00. 目錄01. GCC的二進制工具02. ar指令03. readelf指令04. strings指令05. nm指令06. strip指令07. 附錄
01. GCC的二進制工具
在GCC的開發環境中,除了基本程式生成的編譯、連結工具,還有其它一系列二進制的工具可以使用。
ar 歸檔工具
readelf 讀取ELF格式檔案資訊
strings 檢視字元串
nm 顯示符号資訊
strip 删除符号
02. ar指令
ar工具用于建立、修改、提取歸檔檔案(archive)。一個歸檔檔案是包含多個目标檔案的單個檔案,它也被稱為靜态庫。歸檔檔案的結構保證了可以從中檢索并得到原始的被包含的檔案,也就是這個歸檔檔案的成員。被包含的原始檔案的内容、模式(權限)、時間戳、所有者群組等屬性都儲存在歸檔檔案中,在提取後,可以恢複原始檔案的相關屬性。
2.1 ar用法指令
Usage: ar [emulation options] [-]{dmpqrstx}[abcDfilMNoOPsSTuvV] [--plugin <name>] [member-name] [count]
archive-file file...
ar -M [<mri-腳本]
指令:
d - 從歸檔檔案中删除檔案
m[ab] - 在歸檔檔案中移動檔案
p - 列印在歸檔檔案中找到的檔案
q[f] - 将檔案快速追加到歸檔檔案中
r[ab][f][u] - 替換歸檔檔案中已有的檔案或加入新檔案
s - 作為 ranlib 工作
t[O][v] - display contents of the archive
x[o] - 從歸檔檔案中分解檔案
特定指令修飾符:
[a] - 将檔案置于 [成員名] 之後
[b] - 将檔案置于 [成員名] 之前 (于 [i] 相同)
[D] - 将 0 用于時間戳和 uid/gid(預設)
[D] - 使用實際時間戳和 uid/gid
[N] - 使用名稱的執行個體 [數量]
[f] - 截去插入的檔案名稱
[P] - 在比對時使用完整的路徑名
[o] - 保留原來的日期
[O] - display offsets of files in the archive
[u] - 隻替換比目前歸檔内容更新的檔案
通用修飾符:
[c] - 不在必須建立庫的時候給出警告
[s] - 建立歸檔索引 (cf. ranlib)
[S] - 不要建立符号表
[T] - 産生一個簡單歸檔
[v] - 輸出較多資訊
[V] - 顯示版本号
@<file> - 從 <file> 讀取選項
--target=BFDNAME - 指定目标對象格式為 BFDNAME
--output=DIRNAME - specify the output directory for extraction operations
可選項:
--plugin <p> - 加載指定的插件程式
2.2 用法示例
在GCC工具系列中,ar工具常用于生成靜态庫(static lib)檔案。
生成靜态庫
deng@itcast:~/share/3rd/1static_lib$ ar -rv libtest.a add.o sub.o mul.o div.o
ar: 正在建立 libtest.a
a - add.o
a - sub.o
a - mul.o
a - div.o
deng@itcast:~/share/3rd/1static_lib$
2.3 檢視已經生成的靜态庫的内容
deng@itcast:~/share/3rd/1static_lib$ ar -t libtest.a
add.o
sub.o
mul.o
div.o
deng@itcast:~/share/3rd/1static_lib$
2.4 對于一個已經生成的靜态庫,再次調用ar可以替換靜态庫中的内容
deng@itcast:~/share/3rd/1static_lib$ ar -rv libtest.a add.o sub.o
r - add.o
r - sub.o
deng@itcast:~/share/3rd/1static_lib$
2.5 使用ar工具加-d選項,可以删除庫中的成員
deng@itcast:~/share/3rd/1static_lib$ ar -d libtest.a add.o
deng@itcast:~/share/3rd/1static_lib$ ar -t libtest.a
sub.o
mul.o
div.o
deng@itcast:~/share/3rd/1static_lib$
2.6 追加檔案到歸檔檔案中
deng@itcast:~/share/3rd/1static_lib$ ar -rv libtest.a add.o
a - add.o
deng@itcast:~/share/3rd/1static_lib$
2.7 提取其中的各個目标檔案
deng@itcast:~/share/3rd/1static_lib$ ar -x libtest.a
deng@itcast:~/share/3rd/1static_lib$ ls -l *.o
-rw-r--r-- 1 deng deng 1368 6月 15 22:38 add.o
-rw-r--r-- 1 deng deng 1368 6月 15 22:38 div.o
-rw-r--r-- 1 deng deng 1368 6月 15 22:38 mul.o
-rw-r--r-- 1 deng deng 1368 6月 15 22:38 sub.o
03. readelf指令
readelf用來顯示ELF格式檔案的資訊,可通過參數選項來控制顯示那些特定資訊。readelf工具的使用方式如下所示:
deng@itcast:~$ readelf --help
用法:readelf <選項> elf-檔案
顯示關于 ELF 格式檔案内容的資訊
Options are:
-a --all 顯示所有,等價于-h -l -S -s -r -d -V -A -I
-h --file-header 顯示ELF檔案頭資訊
-l --program-headers 顯示ELF程式頭
--segments --program-headers的别名
-S --section-headers Display the sections' header 顯示節頭
--sections --section-headers的别名
-g --section-groups Display the section groups
-t --section-details Display the section details
-e --headers Equivalent to: -h -l -S
-s --syms 顯示符号表
--symbols An alias for --syms
--dyn-syms Display the dynamic symbol table
-n --notes 顯示核心注釋
-r --relocs 顯示重定向資訊
-u --unwind 顯示unwind資訊
-d --dynamic 顯示動态段
-V --version-info 顯示版本節
-A --arch-specific 顯示體系架構特定資訊
-c --archive-index Display the symbol/file index in an archive
-D --use-dynamic 顯示資訊使用動态節
-x --hex-dump=<number|name>
Dump the contents of section <number|name> as bytes
-p --string-dump=<number|name>
Dump the contents of section <number|name> as strings
-R --relocated-dump=<number|name>
Dump the contents of section <number|name> as relocated bytes
-z --decompress Decompress section before dumping it
-w[lLiaprmfFsoRtUuTgAckK] or
--debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
=frames-interp,=str,=loc,=Ranges,=pubtypes,
=gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
=addr,=cu_index,=links,=follow-links]
Display the contents of DWARF debug sections
--dwarf-depth=N Do not display DIEs at depth N or greater
--dwarf-start=N Display DIEs starting with N, at the same depth
or deeper
--ctf=<number|name> Display CTF info from section <number|name>
--ctf-parent=<number|name>
Use section <number|name> as the CTF parent
--ctf-symbols=<number|name>
Use section <number|name> as the CTF external symtab
--ctf-strings=<number|name>
Use section <number|name> as the CTF external strtab
-I --histogram 顯示柱狀圖
-W --wide 對超過80列的輸出裝置指定一些行的格式
@<file> Read options from <file>
-H --help 顯示幫助資訊
-v --version Display the version number of readelf
将 bug 報告到 <http://www.sourceware.org/bugzilla/>
3.1 顯示目标檔案ELF檔案頭資訊
deng@itcast:~/share/3rd/1static_lib$ readelf -h add.o
ELF 頭:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
類别: ELF64
資料: 2 補碼,小端序 (little endian)
Version: 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: 600 (bytes into file)
标志: 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: 12
Section header string table index: 11
deng@itcast:~/share/3rd/1static_lib$
3.2 顯示共享庫頭資訊
deng@itcast:~/share/3rd/3share_lib$ readelf -h libtest.so
ELF 頭:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
類别: ELF64
資料: 2 補碼,小端序 (little endian)
Version: 1 (current)
OS/ABI: UNIX - System V
ABI 版本: 0
類型: DYN (共享目标檔案)
系統架構: Advanced Micro Devices X86-64
版本: 0x1
入口點位址: 0x1040
程式頭起點: 64 (bytes into file)
Start of section headers: 14208 (bytes into file)
标志: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 11
Size of section headers: 64 (bytes)
Number of section headers: 25
Section header string table index: 24
deng@itcast:~/share/3rd/3share_lib$
3.3 顯示可執行檔案頭資訊如下
deng@itcast:~/share/3rd/4share_test$ readelf -h main
ELF 頭:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
類别: ELF64
資料: 2 補碼,小端序 (little endian)
Version: 1 (current)
OS/ABI: UNIX - System V
ABI 版本: 0
類型: DYN (共享目标檔案)
系統架構: Advanced Micro Devices X86-64
版本: 0x1
入口點位址: 0x10e0
程式頭起點: 64 (bytes into file)
Start of section headers: 14816 (bytes into file)
标志: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
deng@itcast:~/share/3rd/4share_test$
04. strings指令
strings是一個簡單的工具,用于檢視檔案中的字元串。
deng@itcast:~/share/3rd/4share_test$ strings --help
用法:strings [選項] [檔案]
列印 [檔案] (預設為标準輸入) 中可列印的字元串
選項為:
-a - --all 掃描整個檔案,而不是資料段
-d --data 掃描資料段
-f --print-file-name 在字元串前面列印檔案的名字
-n --bytes=[number] 定位和列印任何以NUL結束的序列,至少number個位元組,預設為4個位元組
-<number> least [number] characters (default 4).
-t --radix={o,d,x} 基于八、十、十六進制列印字元串
-w --include-all-whitespace Include all whitespace as valid string characters
-o An alias for --radix=o
-T --target=<BFDNAME> 指定二進制檔案的格式
-e --encoding={s,S,b,l,B,L} 選擇字元大小
s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit
-s --output-separator=<string> String used to separate strings in output.
@<file> Read options from <file>
-h --help 顯示strings的所有選項然後退出
-v -V --version 顯示strings的版本号然後退出
deng@itcast:~/share/3rd/4share_test$
4.1 檢視目标檔案中的字元串
deng@itcast:~/share/3rd/1static_lib$ strings add.o
GCC: (Ubuntu 9.3.0-10ubuntu2) 9.3.0
add.c
.symtab
.strtab
.shstrtab
.text
.data
.bss
.comment
.note.GNU-stack
.note.gnu.property
.rela.eh_frame
deng@itcast:~/share/3rd/1static_lib$
05. nm指令
nm工具用于顯示檔案中的符号,可以用于各種ELF格式的檔案。使用nm檢視前面的目标檔案(可重定向檔案),将顯示符号及其相關内容。
deng@itcast:~/share/3rd/1static_lib$ nm --help
用法:nm [選項] [檔案]
列舉 [檔案] 中的符号 (預設為 a.out)。
The options are:
-a, --debug-syms 隻顯示調試符号
-A, --print-file-name 在每個符号前列印輸入檔案的名稱
-B Same as --format=bsd
-C, --demangle[=STYLE] 将底層的符号解碼位使用者層的符号。
The STYLE, if specified, can be `auto' (the default),
`gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'
or `gnat'
--no-demangle 不解析底層符号
--recurse-limit Enable a demangling recursion limit. This is the default.
--no-recurse-limit Disable a demangling recursion limit.
-D, --dynamic 顯示動态符号而不是普通符号。對動态目标檔案有意義。
--defined-only 隻顯示定義的符号
-e (ignored)
-f, --format=FORMAT 使用輸出的格式 FORMAT can be `bsd',
`sysv' or `posix'. The default is `bsd'
-g, --extern-only 隻顯示外部符号
-l, --line-numbers 對每個符号,使用調試資訊去視圖找到檔案名符号。對于已定義的符号,查找符号位址的行号。
對于未定義的符号,查找指定符号重定位入口的行号。如果可以找到行号資訊,
在其它符号資訊之後顯示該資訊。
-n, --numeric-sort 按符号對應位址的順序排序,而不是按符号名的字元順序
-o Same as -A
-p, --no-sort 不以任何順序對符号進行排序
-P, --portability Same as --format=posix
-r, --reverse-sort 反轉排序的順序(按照數字或者字母順序)顯示
--plugin NAME Load the specified plugin
-S, --print-size Print size of defined symbols
-s, --print-armap 列出歸檔檔案中成員的符号時包含索引,即名字和包含該名字定義的子產品的映射
--size-sort 按照大小排列符号順序,改大小是按照一個符号的值與它下一個符号的值進行計算
--special-syms 包括輸出特殊符号
--synthetic 顯示綜合符号
-t, --radix=RADIX Use RADIX for printing symbol values
--target=BFDNAME Specify the target object format as BFDNAME
-u, --undefined-only 僅顯示沒有定義的符号(那些目标檔案中的外部符号)
--with-symbol-versions Display version strings after symbol names
-X 32_64 (ignored)
@FILE Read options from FILE
-h, --help Display this information
-V, --version Display this program's version number
nm符号類型
符号類型 | 含義 |
A | Absolute 符号的值是絕對值,并且不會被将來的連接配接所改變 |
B | BSS 符号位于未初始化資料段 |
C | Common 符号是公共。公共符号是未初始化的資料。在連接配接時,多個公共符号可能以相同的名字出現。如果符号在其它地方被定義,該符号會被當做未定義的引用來處理。 |
D | Data,符号位于已經初始化資料部分 |
N | 調試符号 |
R | ReadOnly Data 符号位于隻讀資料段 |
T | Text 符号位于代碼段 |
U | Undefined 未被定義的符号 |
W | Weak 弱定義符号,也稱為弱符号。當一個弱定義符号和一個已定義的普通符号連接配接時,使用該以定義的普通符号不會引起錯誤。當一個未定義的弱符号被連接配接且該符号位被定義時,該Weak符号變為零,并且不會産生錯誤。 |
在nm顯示的符号中,小寫字母表示這個符号是局部符号,大寫字母表示這個符号是全局符号。
5.1 檢視目标檔案中的符号
deng@itcast:~/share/3rd/1static_lib$ nm add.o
0000000000000000 T add
deng@itcast:~/share/3rd/1static_lib$
5.2 檢視共享庫中的符号
deng@itcast:~/share/3rd/3share_lib$ nm libtest.so
00000000000010f9 T add
0000000000004020 b completed.8059
w __cxa_finalize
0000000000001040 t deregister_tm_clones
00000000000010b0 t __do_global_dtors_aux
0000000000003e88 d __do_global_dtors_aux_fini_array_entry
0000000000004018 d __dso_handle
0000000000003e90 d _DYNAMIC
0000000000001158 t _fini
00000000000010f0 t frame_dummy
0000000000003e80 d __frame_dummy_init_array_entry
0000000000002118 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000002000 r __GNU_EH_FRAME_HDR
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000001127 T mul
000000000000113e T mydiv
0000000000001070 t register_tm_clones
0000000000001111 T sub
0000000000004020 d __TMC_END__
deng@itcast:~/share/3rd/3share_lib$
5.3 檢視可執行檔案中的符号
deng@itcast:~/share/3rd/2static_test$ nm main
00000000000011f2 T add
0000000000004010 B __bss_start
0000000000004010 b completed.8059
w __cxa_finalize@@GLIBC_2.2.5
0000000000004000 D __data_start
0000000000004000 W data_start
0000000000001090 t deregister_tm_clones
0000000000001100 t __do_global_dtors_aux
0000000000003dc0 d __do_global_dtors_aux_fini_array_entry
0000000000004008 D __dso_handle
0000000000003dc8 d _DYNAMIC
0000000000004010 D _edata
0000000000004018 B _end
00000000000012c8 T _fini
06. strip指令
strip工具用于删除檔案中的符号。使用strip既可以删除目标檔案中的某個符号,也可以删除整個節。使用strip至少要有一個輸入檔案,也可以輸入一個檔案清單。
strip指令用法如下
deng@itcast:~/share/3rd/3share_lib$ strip --help
用法:strip <選項> 輸入檔案
從檔案中删除符号和節
選項為:
-I --input-target=<bfdname> 預設所有輸入檔案為<bfdname>格式
-O --output-target=<bfdname> 建立<bfdname>格式的輸出檔案
-F --target=<bfdname> Set both input and output format to <bfdname>
-p --preserve-dates 保留時間戳資訊
-D --enable-deterministic-archives
Produce deterministic output when stripping archives (default)
-U --disable-deterministic-archives
Disable -D behavior
-R --remove-section=<name> 删除名稱為<name>的節
--remove-relocations <name> Remove relocations from section <name>
-s --strip-all 删除所有的節
-g -S -d --strip-debug 删除所有符号和重定向資訊
--strip-dwo Remove all DWO sections
--strip-unneeded 删除所有重定向不需要的節
--only-keep-debug Strip everything but the debug information
-M --merge-notes Remove redundant entries in note sections (default)
--no-merge-notes Do not attempt to remove redundant notes
-N --strip-symbol=<name> 删除名稱為name的符号
--keep-section=<name> Do not strip section <name>
-K --keep-symbol=<name> 保留名稱為name的符号
--keep-file-symbols Do not strip file symbol(s)
-w --wildcard Permit wildcard in symbol comparison
-x --discard-all 删除所有非全局符号
-X --discard-locals 删除所有編譯産生的符号
-v --verbose 顯示所有修改的檔案
-V --version Display this program's version number
-h --help Display this output
--info List object formats & architectures supported
-o <file> 輸出檔案為file
6.1 使用strip删除main檔案中的符号,輸出為main_stripped檔案。
# main_stripped是被删除了符号的可執行程式。
deng@itcast:~/projects/Project1$ strip main -o main_stripped
deng@itcast:~/projects/Project1$ ls -lh main main_stripped
-rwxrwxr-x 1 deng deng 17K 6月 18 20:11 main
-rwxrwxr-x 1 deng deng 15K 6月 18 20:11 main_stripped
deng@itcast:~/projects/Project1$
# main_stripped中已經不包含任何符号
deng@itcast:~/projects/Project1$ nm main_stripped
nm: main_stripped:無符号
deng@itcast:~/projects/Project1$
6.2 使用file指令對比main和main_stripped兩個檔案
deng@itcast:~/projects/Project1$ file main
main: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=655998d8473f3943b09638ea12e6bb148838c2e1,
for GNU/Linux 3.2.0, not stripped
deng@itcast:~/projects/Project1$ file main_stripped
main_stripped: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-
linux-x86-64.so.2, BuildID[sha1]=655998d8473f3943b09638ea12e6bb148838c2e1, for GNU/Linux 3.2.0, stripped
deng@itcast:~/projects/Project1$
友情提示:
strip工具在嵌入式這種存儲空間非常有限的系統中很有用,它可以極大程度的減少程式的體積,去掉複雜的符号表,因為符号表主要用于調試,是以可以再PC上調試完成後,燒寫到目标闆之前就直接利用strip指令。
07. 附錄
7.1【Linux】GCC程式開發工具(上)
7.2 【Linux】GCC程式開發工具(中)