青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-80  評論-22  文章-0  trackbacks-0
GNU binutils是一組二進制工具集。包括:addr2line ar gprof nm objcopy objdump ranlib size strings strip. 本文歸納他們的常用法。

ar

ar 用于建立、修改、提取檔案文件(archive)。archive是一個包含多個被包含文件的單一文件(也稱之為庫文件),其結構保證了可以從中檢索并得 到原始的被包含文件(稱之為archive中的member)。member的原始文件內容、模式(權限)、時間戳、所有著和組等屬性都被保存在 archive中。member被提取后,他們的屬性被恢復到初始狀態。

ar主要用于創建C庫文件

創建靜態庫
(1) 生成目標文件:

$ gcc -Wall -c file1.c file2.c file3.c


不用指定生成.o文件名(默認生成file1.o, file2.o, file3.o)。

(2) 從.o目標文件創建靜態連接庫
$ ar rv libNAME.a file1.o file2.o file3.o

ar生成了libNAME.a庫,并列出庫中的文件。
r : 將flie1.o, file2,o, file3.o插入archive,如故原先archive中已經存在某文件,則先將該文件刪除。
v : 顯示ar操作的附加信息


創建動態庫(利用gcc,未用ar)

(1) 生成目標文件

$ gcc -Wall -c -fpic file1.c file2.c file3.c


-fpic: 指定生成的.o目標文件可被重定址. pic是position idependent code的縮寫: 位置無關代碼.

(2)生成動態庫文件

$ gcc -shared -o libNAME.so file1.o file2.o file3.o


一般地, 連接器使用main()函數作為程序入口. 但在動態共享庫中沒有這樣的入口. 所以就要指定-shared選項來避免編譯器顯示出錯信息.

實際上, 上述的兩條命令可以合并為下面這條:

$ gcc -Wall -shared -fpic -o libNAME.so file1.c file2.c file3.c



此后,將main函數所在的程序與libNAME.so連接

至此,與動態庫連接的函數編譯成了一個可執行文件。貌似成功了,但還差最后一步。如果直接運行該程序,會給出這樣的錯誤信息:

error while loading shared libraries: libhello.so:
cannot open shared object file: No such file or directory


這是因為與動態庫連接的程序在運行時,首先將該動態庫加載到內存中,而gcc默認加載動態庫文件所在目錄為/usr/local/lib, /usr/lib。剛才的程序雖然能編譯成功,但如果我們自己建立的動態庫沒有位于默認目錄中,則執行時會應為無法找到它而失敗。

解決辦法:改變加載路徑對應的環境變量,然后再執行。


export LD_LIBRARY_PATH=動態庫所在目錄:$LD_LIBRARY_PATH


查看archive內容

$ ar tv archiveNAME


t : 顯示archive中member的內容,若不指定member,則列出所有。
v : 與t結合使用時,顯示member的詳細信息。

要想進了解ar的詳細選項,參考ar的on-line manual


nm

nm用來列出目標文件中的符號,可以幫助程序員定位和分析執行程序和目標文件中的符號信息和它的屬性。
如果沒有目標文件作為參數傳遞給nm, nm假定目標文件為a.out.
這里用一個簡單的示例程序來介紹nm的用法:

main.c:

int main(int argc, char *argv[])
{
hello();
bye();
return 0;
}


hello.c:

void hello(void)
{
printf("hello!\n");
}


bye.c:


void bye(void)
{
printf("good bye!\n");
}


運行下列命令:
$ gcc -Wall -c main.c hello.c bye.c
gcc生成main.o, hello.o, bye.o三個目標文件(這里沒有聲明函數原型,加了-Wall,gcc會給出警告)
$ nm main.o hello.o bye.o

結果顯示如下:

main.o:
U bye
U hello
00000000 T main

hello.o:
00000000 T hello
U puts

bye.o:
00000000 T bye
U puts


結合這些輸出結果,以及程序代碼,可以知道:
對于main.o, bye和hello未被定義, main被定義了
對于hello.o, hello被定義了, puts未被定義
對于bye.o, bye被定義了,puts未被定義

幾個值得注意的問題:
(1)"目標文件"指.o文件, 庫文件, 最終的可執行文件
.o : 編譯后的目標文件,即含有最終編譯出的機器碼,但它里面所引用的其他文件中函數的內存位置尚未定義.
(2)如果用nm查看可執行文件, 輸出會比較多, 仔細研究輸出, 可以對nm用法有更清醒的認識.
(3) 在上述hello.c, bye.c中, 調用的是printf(), 而nm輸出中顯示調用的是puts(), 說明最終程序實際調用的puts(), 如果令hello.c或bye.c中的printf()使用格式化輸出,則nm顯示調用printf(). ( 如: printf("%d", 1); )

關于nm的參數選項,參考on-line manual


objcopy

objcopy可以將一種格式的目標文件轉化為另外一種格式的目標文件. 它使用GNU BFD庫進行讀/寫目標文件.使用BFD, objcopy就能將原格式的目標文件轉化為不同格式的目標文件.
以我們在nm中使用的hello.o目標文件和hello可執行為例:

$ file hello.o hello


file命令用來判別文件類型, 輸出如下:

hello.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), not stripped

現在運行objcopy來改變hello的文件類型: 原先它是ELF格式的可執行程序, 現將它轉換為srec格式. srec格式文件是Motolora S-Record格式的文件, 主要用來在主機和目標機之間傳輸數據.


$ objcopy -O srec hello hello_srec
$ file hello.o hello


file命令結果: hello_srec: Motorola S-Record; binary data in text format

注意objcopy的格式, "-O"指定輸出文件類型; 輸入文件名和輸出文件名位于命令末尾. 關于objcopy命令的詳細選項, 參考on-line manual


objdump

objdump用來顯示目標文件的信息. 可以通過選項控制顯示那些特定信息. objdump一個最大的用處恐怕就是將C代碼反匯編了. 在嵌入式軟件開發過程中, 也可以用它查看執行文件或庫文件的信息.
下面我們用上文提到的hello可執行文件和hello_srec可執行文件為例, 介紹objdump的簡單用法:


$ objdump -f hello hello_srec


輸出如下:
hello: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080482c0

hello_srec: file format srec
architecture: UNKNOWN!, flags 0x00000000:
start address 0x00000000080482c0

-f : 顯示目標文件的頭文件概要信息.

生成反匯編代碼:


$ objdump -d hello.o


顯示如下:
hello.o: file format elf32-i386

Disassembly of section .text:

00000000 <hello>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub x8,%esp
6: 83 ec 0c sub xc,%esp
9: 68 00 00 00 00 push x0
e: e8 fc ff ff ff call f <hello+0xf>
13: 83 c4 10 add x10,%esp
16: c9 leave
17: c3 ret

-d : 顯示目標文件中機器指令使用的匯編語言. 只反匯編那些應該含有指令機器碼的節(顯示.text段); 如果用-D, 則反匯編所有節的內容.
關于objcopy命令的詳細選項, 參考on-line manual


readelf

readelf用來顯示ELF格式目標文件的信息.可通過參數選項來控制顯示哪些特定信息.(注意: readelf不支持顯示archive文檔, 也不支持64位的ELF文件).
下面利用先前的hello可執行文件演示readelf的簡單用法:


$ readelf -h hello


ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x80482c0
Start of program headers: 52 (bytes into file)
Start of section headers: 3848 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 34
Section header string table index: 31

注意: readelf只能用于ELF格式目標文件, 且選項中至少要指定一個(除V, H外)的選項!


gprof


gprof被用來測量程序的性能. 它記錄每個函數被調用的次數以及相應的執行時間. 這樣就能鎖定程序執行時花費時間最多的部分, 對程序的優化就可集中于對它們的優化.

用一個簡單的數值計算程序來掩飾gprof的用法:

collatz.c:
#include <stdio.h>
/* Computes the length of Collatz sequences */
unsigned int step (unsigned int x)
{
if (x % 2 == 0)
{
return (x / 2);
}
else
{
return (3 * x + 1);
}
}

unsigned int nseq (unsigned int x0)
{
unsigned int i = 1, x;
if (x0 == 1 || x0 == 0)
return i;
x = step (x0);
while (x != 1 && x != 0)
{
x = step (x);
i++;
}
return i;
}

int main (void)
{
unsigned int i, m = 0, im = 0;
for (i = 1; i < 500000; i++)
{
unsigned int k = nseq (i);
if (k > m)
{
m = k;
im = i;
printf ("sequence length = %u for %u\n", m, im);
}
}
return 0;
}


先將collatz.c編譯成目標文件collatz.o, gcc通過 -pg選項來打開gprof支持:

$ gcc -Wall -c -pg collatz.c

$ gcc -Wall -pg -o collatz collatz.o


注意:兩條命令都要加 "-pg"選項。前一條命令生成collatz.o目標文件。后一條命令生成可執行文件,該可執行文件中包含了記錄函數執行時間的指令。
生成collatz可執行文件后,現執行它,結果與一般程序的執行無疑。但此時在PWD目錄生成一個名為"gmon.out"的文件,gprof通過它來分析程序的執行。
如果不現執行程序,而直接用gprof來分析它,會提示“gmon.out: No such file or directory”。

gprof用法:

$ gprof ./collatz


Addr2line

Addr2line 工具(它是標準的 GNU Binutils 中的一部分)是一個可以將指令的地址和可執行映像轉換成文件名、函數名和源代碼行數的工具。這種功能對于將跟蹤地址轉換成更有意義的內容來說簡直是太棒了。

要了解這個過程是怎樣工作的,我們可以試驗一個簡單的交互式的例子。(我直接從 shell 中進行操作,因為這是最簡單地展示這個過程的方法,如清單 4 所示。)這個示例 C 文件(test.c)是通過 cat 一個簡單的應用程序實現的(也就是說,將標準輸出的文本重定向到一個文件中)。然后使用 gcc 來編譯這個文件,它會傳遞一些特殊的選項。首先,要(使用 -Wl 選項)通知鏈接器生成一個映像文件,并(使用 -g 選項)通知編譯器生成調試符號。最終生成可執行文件 test。得到新的可執行應用程序之后,您就可以使用 grep 工具在映像文件中查找 main 來尋找它的地址了。使用這個地址和 Addr2line 工具,就可以判斷出函數名(main)、源文件(/home/mtj/test/test.c)以及它在源文件中的行號(4)。

在調用 Addr2line 工具時,要使用 -e 選項來指定可執行映像是 test。通過使用 -f 選項,可以告訴工具輸出函數名。


清單 4. addr2line 的一個交互式例子

$ cat >> test.c
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
<ctld-d>
$ gcc -Wl,-Map=test.map -g -o test test.c
$ grep main test.map
0x08048258 __libc_start_main@@GLIBC_2.0
0x08048258 main
$ addr2line 0x08048258 -e test -f
main
/home/mtj/test/test.c:4
$
posted on 2012-04-24 10:28 Bluesea 閱讀(1113) 評論(0)  編輯 收藏 引用 所屬分類: linux

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美日韩成人高清在线一区| 国产精品成人国产乱一区| 欧美激情一二区| 麻豆成人在线观看| 麻豆精品在线视频| 亚洲成人中文| 欧美成人国产一区二区| 欧美成ee人免费视频| 亚洲高清一区二| 亚洲日韩欧美视频| 极品尤物久久久av免费看| 影音先锋亚洲视频| 99视频在线观看一区三区| 亚洲一区二区欧美| 久久久女女女女999久久| 欧美激情在线有限公司| 99国产精品| 欧美亚洲综合另类| 狂野欧美一区| 国产精品久久福利| 亚洲国产精品99久久久久久久久| 亚洲精品日韩激情在线电影| 亚洲午夜精品| 美女国产一区| 亚洲午夜精品网| 久久综合999| 国产精品久久午夜夜伦鲁鲁| **网站欧美大片在线观看| 亚洲一区二区av电影| 免费在线观看精品| 亚洲免费影视| 欧美日韩一区成人| 在线成人激情| 欧美一区二区视频观看视频| 亚洲国产美国国产综合一区二区| 午夜国产欧美理论在线播放 | 久久精品亚洲一区二区| 欧美精品大片| 在线观看欧美一区| 欧美在线一二三四区| 亚洲三级国产| 另类亚洲自拍| 亚洲第一福利视频| 久久久久欧美精品| 亚洲一区在线免费| 国产精品videosex极品| 99亚洲视频| 亚洲国产精品成人va在线观看| 久久不射2019中文字幕| 国产精品入口66mio| 亚洲视频导航| 亚洲伦理一区| 欧美精品一区二区视频| 亚洲电影在线| 蜜臀91精品一区二区三区| 欧美在线免费观看| 国产日韩欧美在线播放| 欧美一级二区| 亚洲欧美久久久久一区二区三区| 欧美午夜理伦三级在线观看| 一二三四社区欧美黄| 91久久精品久久国产性色也91| 毛片基地黄久久久久久天堂| 在线免费观看欧美| 免费av成人在线| 免费美女久久99| 亚洲裸体在线观看| 99re国产精品| 欧美成年人网站| 久久av一区二区三区| 国产婷婷色一区二区三区| 性欧美video另类hd性玩具| 亚洲免费视频一区二区| 国产偷国产偷亚洲高清97cao| 午夜精品亚洲| 欧美一区二区三区日韩视频| 国内视频精品| 亚洲第一精品电影| 欧美日韩国产一区精品一区| 亚洲天堂免费在线观看视频| 在线亚洲成人| 国内欧美视频一区二区| 欧美+亚洲+精品+三区| 欧美激情精品久久久久久免费印度| 亚洲裸体视频| 亚洲无人区一区| 国产日韩精品在线| 欧美14一18处毛片| 欧美午夜无遮挡| 久久久久**毛片大全| 久久综合九色综合欧美狠狠| 日韩午夜在线观看视频| 在线天堂一区av电影| 好看不卡的中文字幕| 亚洲成人直播| 国产精品一区二区三区四区五区| 葵司免费一区二区三区四区五区| 欧美电影免费观看| 欧美一级播放| 欧美国产在线视频| 久久国产夜色精品鲁鲁99| 欧美成人在线免费观看| 欧美一区二区三区四区在线观看地址| 久久久久久一区| 亚洲男人的天堂在线aⅴ视频| 久久久精品欧美丰满| 亚洲一级黄色片| 久久久久网站| 欧美一区日本一区韩国一区| 欧美成人性网| 久久性色av| 国产精品日韩欧美| 亚洲人成在线免费观看| 国产亚洲在线观看| 亚洲网站在线看| 99re6热只有精品免费观看 | 麻豆91精品91久久久的内涵| 午夜宅男欧美| 欧美视频在线一区二区三区| 欧美激情一区二区三区高清视频| 国产欧美日韩亚洲一区二区三区| 亚洲人成在线播放| 最新国产成人在线观看| 久久久久久亚洲精品中文字幕| 欧美一区二区在线免费播放| 欧美日韩极品在线观看一区| 欧美高清自拍一区| 一区视频在线播放| 久久精品理论片| 久久黄金**| 国产欧美在线观看一区| 亚洲欧美一区二区视频| 欧美日韩成人| 亚洲片在线观看| 亚洲欧洲在线一区| 欧美国产第二页| 亚洲啪啪91| 宅男噜噜噜66国产日韩在线观看| 欧美大胆成人| 亚洲精品日韩激情在线电影| 亚洲剧情一区二区| 欧美激情第3页| 亚洲欧洲在线一区| 在线视频欧美日韩精品| 欧美日韩国产在线| 一区二区三区日韩欧美精品| 亚洲欧美在线磁力| 国产日韩视频| 久久久天天操| 亚洲国产精品福利| 宅男噜噜噜66一区二区66| 欧美日韩亚洲国产一区| 99re8这里有精品热视频免费 | 欧美一区二视频| 久久香蕉国产线看观看av| 在线观看欧美视频| 欧美精品一区在线发布| 一区二区三区回区在观看免费视频| 亚洲欧美日本在线| 国产婷婷成人久久av免费高清 | 亚洲一区二区高清| 久久久精品午夜少妇| 亚洲黄色在线看| 欧美日韩网址| 午夜欧美电影在线观看| 免费影视亚洲| 亚洲小说欧美另类社区| 国产亚洲精品bv在线观看| 久久美女性网| 日韩亚洲在线观看| 久久久噜噜噜久久久| 亚洲精品小视频| 国产精品主播| 欧美黄色免费| 亚洲欧美国产一区二区三区| 欧美不卡激情三级在线观看| 亚洲色无码播放| 一色屋精品视频免费看| 欧美日韩亚洲免费| 久久精品一区蜜桃臀影院 | 国产精品一区二区三区乱码| 久久亚洲精选| 亚洲图色在线| 亚洲国产一区在线| 久久久久国产精品人| 9i看片成人免费高清| 国内在线观看一区二区三区| 欧美日韩小视频| 久久躁狠狠躁夜夜爽| 亚洲综合清纯丝袜自拍| 亚洲精品国产精品国自产在线| 久久天堂国产精品| 欧美一区二区三区四区高清| 99在线|亚洲一区二区| 在线观看日韩av| 久久免费少妇高潮久久精品99| 亚洲美女在线一区| 欧美国产日韩精品| 男男成人高潮片免费网站| 久久精品国产999大香线蕉|