1.3 GCC 工具
1.3.1 binutils 工具集
工具 |
描述 |
addr2line |
給出一個可執行文件的內部地址,addr2line 使用文件中的調試信息將地址翻譯成源代碼文件名和行號。 |
ar |
這是一個程序,可通過從文檔中增加、刪除和析取文件來維護庫文件。通常使用該工具是為了創建和管理連接程序使用的目標庫文檔。 |
as |
GNU 匯編器。實際上它是一族匯編器,因為它可以被編譯或能夠在各種不同平台上工作。 |
c++filt |
程序接受被 C++編譯程序轉換過的名字(不是被重載的) ,而且將該名字翻譯成初始形式。 |
elfedit |
更新 ELF 文件的 ELF 頭。 |
gprof |
該程序會監督編譯程序的執行過程,並報告程序中各個函數的運行時間,可以根據所提供的配置文件來優化程序。 |
ld |
GNU 連接程序。該程序將目標文件的集合組合成可執行程序。 |
ld.bfd |
到 ld 的硬鏈接。 |
libbfd |
二進制文件描述器庫。該程序是 binutils 包的一部分 |
libiberty |
包含多個 GNU 程序會使用的途徑,包括 getopt、obstack、strerror、strtol 和 strtoul。 |
libopcodes |
一個庫,用於處理 opcodes——處理器指令的 "可讀文本" 版本;用於編制 objdump 這樣的工具。 |
nlmconv |
將可重定位的目標文件轉換成 NetWare 可加載模塊(NetWare Loadable Module,NLM) 。 |
nm |
列出目標文件中定義的符號。 |
objcopy |
將目標文件從一種二進制格式復制和翻譯到另外一種。 |
objdump |
顯示一個或多個目標文件中保存的多種不同信息。 |
ranlib |
創建和添加到 ar 文檔的索引。該索引被 ld 使用來定位庫中的模塊。 |
readelf |
從 ELF 格式的目標文件顯示信息 |
size |
列出目標文件中每個部分的名字和尺寸。 |
strings |
瀏覽所有類型的文件,析取出用於顯示的字符串。 |
strip |
從目標文件或文檔庫中去掉符號表,以及其他調試所需的信息。 |
windres |
Window 資源文件編譯程序。 |
1.3.2 addr2line:地址翻譯工具
addr2line用於得到程序指令地址所對應的函數,以及函數所在的源文件名和行號。
參照對應工具的man和info信息,可以查找到詳細信息。或者運行相應的工具並指定--help參數,可以獲得該工具的簡單幫助信息。
用法:addr2line [選項] [地址]
將地址轉換成文件名/行號對。
如果沒有在命令行中給出地址,就從標准輸入中讀取它們
選項是:@<file> 讀取選項從 <file>
選項 |
描述 |
-a |
--addresses 顯示地址 |
-b |
--target=<bfdname> 設置二進位文件格式 |
-e |
--exe=<executable><name> 設置輸入文件名稱(默認為 a.out) |
-i |
--inlines 解開內聯函數 |
-j |
--section=<name> 讀取相對於段的偏移而非地址 |
-p |
--pretty-print 讓輸出對人類更可讀 |
-s |
--basenames 去除目錄名 |
-f |
--functions 顯示函數名 |
-C |
--demangle[=style] 解碼函數名 |
-h |
--help 顯示本幫助 |
測試代碼:main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <stdio.h> #include <stdlib.h>
void func(void) { printf("func() address is %p\n", func); }
int main(int argc, char *argv[]) { func(); return 0; } |
編譯:gcc -g main.c -o main -Wall
執行:./main
根據地址找到對應的代碼位置
1.3.3 ar:創建和管理連接程序使用的目標庫文檔
ar 命令的語法如下:ar [options] [positionname] [count] archive objectfile [objectfile ...]
- options:選項標簽,選項的字母表示之間沒有空格,選項可通過(也可不通過)連字符來表達。
- 可選的命令行項目 positionname 和 count 只有當用到了某些需要它們的選項時才會出現。
- ar 命令的選項分為兩類:命令行選項告訴 ar 應該采取什么樣的操作(有效命令行選項中的一個) ,以及修改子(modifier) 選項指出如何執行該命令操作
指明操作的ar 選項:
選項 |
描述 |
d |
從文檔中刪除模塊 objectfiles。利用 v 修改子,列出的所有模塊都要被刪除 |
m |
將模塊移入文檔內部。默認情況下,列舉的所有 objectfiles 成員都會移到文檔尾部。利用修改子 a、b 和 i 可將指定模塊移到其他位置 |
p |
將指定的目標文件 objectfiles 的二進制內容打印到標准輸出上。如果沒有指定目標文件objectfiles,就打印所有目標文件。修改子 v 會打印所有列在其內容之前的名字 |
q |
將指定目標文件 objectfiles 快速附加到文檔末尾,而不檢查是否可以取代而不是一味添加。不會更新索引,因此 ranlib 必須在連接庫之前使用 |
r |
將指定目標文件 objectfiles 插入文檔。如果指定的所有目標文件都已經在文檔中了,就用新的替換老的。如果指定文檔不存在,就會創建此文檔。默認條件下,新的模塊會添加到文件的末尾,但是修改子 a、b 或 i 可用來指定新模塊的位置 |
t |
顯示一列文檔文件的內容。修改子 v 會為該列表加上時間戳、所有者、組、以及每個模塊的大小。如果沒有指定目標文件 objectfiles,就會列出整個文檔 |
x |
將指定目標文件展開成正常的磁盤文件。如果沒有指定目標文件,就會展開所有文件 |
修改子選項:
選項 |
描述 |
a |
將新文件添加到命令行指定文件位置之后,該文件是作為位置文件的 |
b |
將新文件添加到命令行指定文件位置之前,該文件是作為位置文件的。這和選項 i 一樣 |
c |
如果必要就創建文檔。只要需要總會創建新的文檔,但使用該選項會禁止警告消息 |
f |
截斷文檔內的文件名。通常 ar 允許任意長度的文件名,可是這樣會導致文檔的創建過程在某些系統中不能相互兼容 |
i |
立即將所有新文件添加到命令行指定的文件位置之前。這和選項 b 一樣 |
N |
當文檔中存在多個指定的目標文件時,count 參數可用來當作指定目標文件的選擇子(selector) |
o |
當文件是從文檔中展開時,原始日期可以得到保留 |
s |
即使沒有改動文檔,也會創建新的文檔索引。在 ar 中會單獨使用修改子,這和使用 ranlib 的結果一樣 |
u |
當文件加入文檔時,該選項說明只有比文檔中現有文件更新的文件才會被添加。該修改子只有和選項 r 在一起才有效 |
v |
按照詳細模式運行,在運行處理過程中顯示附加信息 |
V |
顯示版本信息,然后退出 |
1.3.4 as:GNU匯編器
它是 GNU 匯編器,主要用來編譯 GNU C 編譯器 gcc 輸出的匯編文件,它將匯編代碼轉換成二進制代碼,並存放到一個 object 文件中,該目標文件將由連接器 ld 連接
-
as的內部預處理主要包括三個方面的工作
- 調整和去除額外的間隔符,保留每行的關鍵字前的一個空格或者TAB,其他任意的間隔符都轉換為一個空格。
- 去除所有注釋,代之以一個空格,或者新行的合適的數字。
- 把字符常量轉換成相應的數字值。
- 它不能做宏處理和文件包含處理,如果需要用,可以交給 C 預處理器來處理
語法:as(選項)(參數)
常用選項如下:
選項 |
描述 |
-ac |
忽略失敗條件; |
-ad |
忽略調試指令; |
-ah |
包括高級源; |
-al |
包括裝配; |
-am |
包括宏擴展; |
-an |
忽略形式處理; |
-as |
包括符號; |
=file |
設置列出文件的名字; |
--alternate |
以交互宏模式開始; |
-f |
跳過空白和注釋預處理; |
-g |
產生調試信息; |
-J |
對於有符號溢出不顯示警告信息; |
-L |
在符號表中保留本地符號; |
-o |
指定要生成的目標文件; |
--statistics |
打印匯編所用的最大空間和總時間。 |
例子:as -o main.o main.s –32,編譯32位的匯編代碼
1.3.5 c++filt:修復 C++ 和 Java 符號
主要是為了防止 C++ 和 Java 中的多個函數名重復產生的重載問題。由於每個重載函數都使用與原函數相同的名稱,因此,支持函數重載的語言必須擁有一種機制,以區分同一個函數的許多重載版本。
c++filt 將每個輸入的名稱看成是改編后的名稱,並設法確定用於生成該名稱的編譯器。
如果這個名稱是一個合法的改編名稱,那么,c++filt 就輸出改編之前的名稱; 如果c++filt無法識別一個改編名稱,那它就按原樣輸出該名稱。
不關注除 C 語言之外的語言,命令選項查看 man 手冊
1.3.6 elfedit:檢查或編輯 ELF 文件
elfedit 是一個用於檢查或修改現有 ELF 目標文件內容的工具。可以訪問目標文件中包含的大多數 ELF 數據,這些數據包括 ELF 頭、節頭表、程序頭表、動態節、硬件和軟件功能、字符串表和符號表。
elfedit 可以處理來自命令行(–e 選項)或標准輸入的命令。如果標准輸入是一個終端,elfedit 可提供終端編輯功能以及涵蓋大量命令的命令補齊功能。ELF 對特殊整數值和位掩碼使用許多標准符號名稱。elfedit 可識別此類名稱的最有可能的完整形式。在輸入 elfedit 命令時,可以隨時按 TAB 鍵,令 elfedit 顯示用法消息以及當前光標處文本的任意已知完整形式。
elfedit 功能以模塊形式組織。每個模塊提供一組命令,這些命令針對相關功能。通過使用冒號 (:) 分隔符將模塊和命令名稱組合到一起(中間無空格)來指定命令。例如,dyn:runpath 指的是由 dyn 模塊提供的 runpath 命令。模塊名稱必須是唯一的。給定模塊中的命令名稱在該模塊中必須唯一,但可在多個模塊中使用相同的命令名稱。
某些模塊將模塊內的某個命令指定為該模塊的缺省命令。用戶只需指定模塊名稱,就可運行此命令。大多數 elfedit 模塊均提供一個名為 dump 的命令,它針對模塊涵蓋的 ELF 文件部分生成的信息與 elfdump 實用程序所顯示的信息相同。通常,模塊會將 dump 指定為其缺省命令。
用於執行 elfedit 命令的語法在設計上采用類似 UNIX 命令行實用程序的語法,這樣任何會使用 UNIX 命令行實用程序的人都可以方便地使用 elfedit 命令。該語法由空格分隔的標記組成:第一個標記是命令名稱。選項(即以連字符 (-) 開頭的參數)跟在命令后面。純參數(操作數)跟在選項后面。一個給定的命令可以有 0 個或多個選項和操作數,但是如果它們同時存在,選項始終位於純參數前面。可使用特殊選項 --(兩個連字符)來限定選項的結尾。如果遇到此選項,其余所有參數均被視為純參數,即使它們以 - 開頭。
elfedit 標記中的字符的解釋取決於所用的引用格式:
引用格式 |
描述 |
非引用 |
單引號 (') 或雙引號 (") 外面的反斜杠 (\) 充當轉義符。elfedit 發現反斜杠字符時會將其忽略,並按字面意思處理反斜杠后面的字符(即使它后面的字符為反斜杠)。此功能可用於在命令的字符串參數中插入一個空白字符,從而無需將一個字符串分為兩個單獨的標記。同樣,它可用於插入一個引號或反斜杠作為文本字符。 |
單引號 |
在單引號 (') 中,空白字符不用於分隔標記,且會被解釋為標記內部的文本字符。雙引號 (") 和反斜杠 (\) 字符會被解釋為文本字符,無特殊意義。 |
雙引號 |
在雙引號 (") 中,空白字符不用於分隔標記。單引號字符會被解釋為文本,不具有引用功能。反斜杠 (\) 是一個轉義字符,在字符串文本中,其作用與 C 編程語言中反斜杠的作用類似: |
\a 警報(響鈴) |
|
\b 退格鍵 |
|
\f 換頁符 |
|
\n 換行符 |
|
\r 回車 |
|
\t 水平制表符 |
|
\v 垂直制表符 |
|
\\ 反斜杠 |
|
\' 單引號 |
|
\" 雙引號 |
|
\ooo 八進制常量,其中 ooo 是 1 到 3 個八進制位 (0...7) |
|
在反斜杠后面跟有任何其他字符,均會出錯。 |
核心命令均屬於一個名為 sys 的內部模塊。所有其他模塊均打包為可動態裝入的可共享目標文件。當執行需要某個模塊的命令時或者當執行 sys:load 命令時,elfedit 會按需裝入模塊。由於 sys 模塊特殊的內置狀態,而且其命令使用頻繁,所以 elfedit 命令允許在不加 sys: 前綴的情況下指定 sys 模塊中的命令,例如,使用 load 而非 sys:load。要訪問任何其他模塊中的命令,必須采用 module:cmd 完整格式指定。
elfedit 隨以下標准模塊一起提供:
模塊 |
描述 |
cap |
功能節 |
dyn |
動態節 |
ehdr |
ELF 頭 |
reloc |
重定位節 |
phdr |
程序頭數組 |
shdr |
節頭數組 |
str |
字符串表節 |
sym |
符號表節 |
syminfo |
Syminfo 節 |
sys |
內置的核心 elfedit 命令 |
命令用法:elfedit [-adr] [-e cmd] [-L path] [-o default | simple | num] [infile] [outfile]
選項 |
描述 |
–a |
啟用 autoprint 模式。啟用 autoprint 后,elfedit 將輸出修改 ELF 文件后所生成的修改值。此輸出以當前輸出樣式顯示,可使用 –o 選項更改此樣式。缺省輸出樣式是 elfdump(1) 實用程序使用的樣式。以交互方式使用 elfedit 時,autoprint 模式為缺省模式(當 stdin 和 stdout 為終端時)。因此,僅當在非交互式上下文中使用 elfedit 時,–a 選項才有意義。要在交互式會話中禁用 autoprint,請使用 elfedit 命令:> set a off |
–d |
如果已設置,此選項可使 elfedit 發布信息性消息,說明其內部操作和要處理的 ELF 目標文件的詳細信息。這在需要深入了解所執行的操作時非常有用。 |
–e cmd |
指定一個編輯命令。可以指定多個 –e 選項。如果在命令行上指定了多個編輯命令,elfedit 將在批處理模式下運行。打開文件后,elfedit 按給定的順序執行每個命令,然后保存修改的文件,最后 elfedit 退出。從 shell 腳本和 makefile 執行簡單操作時,批處理模式非常有用。 |
–L path |
設置用於定位 elfedit 模塊的缺省路徑。本手冊頁的"模塊搜索路徑"部分介紹了各個模塊。 |
–o default | simple | num |
用於顯示 ELF 數據的樣式。此選項用於確立會話的當前樣式。可在 elfedit 會話中更改此樣式,方法是使用 set (sys:set) 命令或向會話中執行的各個命令提供 –o 選項。 |
default |
缺省樣式是以適合用戶查看的格式顯示輸出。此樣式與 elfdump 實用程序使用的樣式類似。 |
num |
整數值始終以整數格式顯示。字符串顯示為在內含的字符串表中定位所用的整數偏移量。 |
simple |
顯示 ELF 文件中的字符串時,僅顯示字符串。如果可能,整數值顯示為符號常量,否則以整數格式顯示。不顯示任何標題、頭或其他補充輸出。 |
–r |
只讀模式。輸入文件以只讀訪問模式打開,編輯會話的結果不會保存。指定了 –r 時,elfedit 不允許使用 outfile 參數。如果不打算修改文件,強烈建議使用只讀模式。除了提供額外保護以防止意外修改外,該選項還允許檢查用戶沒有寫入權限的文件。 |
操作數支持:
操作數 |
描述 |
infile |
包含要處理的 ELF 目標文件的輸入文件。 此文件可以為可執行文件 (ET_EXEC)、共享目標文件 (ET_DYN) 或可重定位目標文件 (ET_REL)。不直接支持歸檔文件。要編輯歸檔中的目標文件,必須提取目標文件,編輯副本,然后將其重新插入到該歸檔文件。 如果未提供 infile,elfedit 將在限定模式下運行,此模式僅允許執行 sys: 模塊中的命令。此模式主要用於訪問 help (sys:help) 命令提供的命令文檔。 如果提供了 infile,但未給定任何 outfile,elfedit 將就地編輯文件並將結果寫入同一文件,這會導致原始文件內容被覆蓋。通常,不建議以此模式使用 elfedit,建議指定輸出文件。生成的文件經過測試和驗證后,可將其移動到原始文件所在的位置。 –r 選項可用於以只讀訪問模式打開 infile。在檢查不希望修改的現有文件時,此選項非常有用。 |
outfile |
輸出文件。如果同時提供了 infile 和 outfile,infile 將以只讀訪問模式打開,修改的目標文件內容會寫入到 outfile 中。 |