linux中的strip命令簡介
一、stip命令學習原因
背景: 在除錯一個ko模組時,應用addr2line命令 得不到行號等宕機的具體位置資訊,只能得到一個函式名稱,"addr2line得到行號為??:?或??:0的原因"。
猜測:當時很困惑,以為編譯此模組時,沒有加-g除錯資訊,於是在makefile中加上結果除錯還是不行,猜測2是因為用核心編譯的模組,懷疑核心配置選項(除錯選項)沒有開啟,於是開啟後用別的ko,反彙編除錯其它ko檔案可以;但是反彙編除錯這個模組還是不可以。
解決方法:
1.網上查 "addr2line得到行號為??:?或??:0的原因"。網上一律說:原因就是編譯得到的檔案沒有附加上符號表(symbolic)資訊。但用nm看目標檔案的符號表資訊,還是有的,目前還是找不到具體的原因。
2.對比這個有問題的ko 的makefile(把兩個裝置檔案放在一個ko裡)和其它正常可調的makefile檔案,發現多了一條命令,&(AT) $(strip) --strip-unneeded ./xx.ko.
二、 於是開始瞭解stip的作用;
strip英文:剝光、拆除、清除,刪除,除去等。
作為一名Linux開發人員, strip這個單詞, , 你就記住是脫衣服就行了, 別的不要多想。 在linux中, strip也有脫衣服的含義, 具體就是從特定檔案中剝掉一些符號資訊和除錯資訊。
linux下檔案壓縮命令compress大家都比較熟悉了,它的壓縮率比較高, 和tar命令結合使用來做資料備份是最合適不過了。但compress壓縮也有缺點,就是被壓縮後的檔案需要用命令uncompress解壓後才能正常使用。而用strip命令就沒有這個問題,它能清除執行檔案中不必要的標示符及除錯資訊,可減小檔案大小而不影響正常使用。但與compress 不同的是,檔案一旦strip後就不能恢復原樣了,所以strip是一個減肥工具而不是壓縮工具。而且,被strip後的檔案不包含除錯資訊,就不能用
dbx來除錯程式了。
http://blog.csdn.net/stpeace/article/details/47090255
我們來看main.c檔案:
#include <stdio.h>
int add(int x, int y)
{
return x + y;
}
int aaa;
int bbb = 1;
char szTest[] = "good";
int main()
{
int ccc = 2;
return 0;
}
然後我們看看結果:
[[email protected] learn_strip]$ ls
main.c
[[email protected] learn_strip]$ gcc main.c
[[email protected] learn_strip]$ ls -l a.out
-rwxrwxr-x 1 taoge taoge 4673 Jul 27 05:30 a.out
[[email protected] learn_strip]$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
[[email protected] learn_strip]$ nm a.out
08049538 d _DYNAMIC
08049604 d _GLOBAL_OFFSET_TABLE_
0804847c R _IO_stdin_used
w _Jv_RegisterClasses
08049528 d __CTOR_END__
08049524 d __CTOR_LIST__
08049530 D __DTOR_END__
0804952c d __DTOR_LIST__
08048520 r __FRAME_END__
08049534 d __JCR_END__
08049534 d __JCR_LIST__
08049628 A __bss_start
08049618 D __data_start
08048430 t __do_global_ctors_aux
08048310 t __do_global_dtors_aux
08048480 R __dso_handle
w __gmon_start__
0804842a T __i686.get_pc_thunk.bx
08049524 d __init_array_end
08049524 d __init_array_start
080483c0 T __libc_csu_fini
080483d0 T __libc_csu_init
U [email protected]@GLIBC_2.0
08049628 A _edata
08049634 A _end
0804845c T _fini
08048478 R _fp_hw
08048274 T _init
080482e0 T _start
08049630 B aaa
08048394 T add
0804961c D bbb
08049628 b completed.5963
08049618 W data_start
0804962c b dtor_idx.5965
08048370 t frame_dummy
080483a2 T main
08049620 D szTest
[[email protected] learn_strip]$
通過ls -l 命令可知, a.out的大小是4673個位元組;
通過file命令可知, a.out是可執行檔案, 且是not stripped, 也就是說沒有脫衣服。
通過nm命令, 可以讀出a.out中的符號資訊。
[[email protected] learn_strip]$ ls
a.out main.c
[[email protected] learn_strip]$ strip a.out
[[email protected] learn_strip]$ ls -l a.out
-rwxrwxr-x 1 taoge taoge 2980 Jul 27 05:34 a.out
[[email protected] learn_strip]$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
[[email protected] learn_strip]$ nm a.out
nm: a.out: no symbols
[[email protected] learn_strip]$
通過ls -l 命令可知, a.out的大小是2980個位元組, 大大減小;
通過file命令可知, a.out是可執行檔案, 且是stripped, 也就是說衣服被脫了;
通過nm命令, 發現a.out中的符號沒有了。
由此可見, strip用於脫掉檔案的衣服, 檔案會變小, 其中的符號資訊會失去。 那這個strip有什麼用呢? 很有用的! 原來的a.out比較大, 可以執行。 在strip之後, 檔案變小了, 仍然可以執行, 這就就節省了很多空間。
其實, strip不僅僅可以針對可執行檔案, 還能針對目標檔案和動態庫等。
在實際的開發中, 經常需要對動態庫.so進行strip操作, 減少佔地空間。 而在除錯的時候(比如用addr2line), 就需要符號了。 因此, 通常的做法是: strip前的庫用來除錯, strip後的庫用來實際釋出, 他們兩者有對應關係。 一旦釋出的strip後的庫出了問題, 就可以找對應的未strip的庫來定位。
最後囉嗦一句, 某某動態庫strip前是18M左右, strip後是3M左右, 可見, 脫脫衣服還是有明顯好處的。
補充: 後來發現, 在除錯過程中, 經常涉及到傳庫, 庫太大時, 很耗費傳輸時間, 所以還是用strip來搞一下吧。
用法:strip <選項> 輸入檔案從檔案中刪除符號和節
選項為:
-I --input-target=<bfdname> Assume input file is in format <bfdname>
-O --output-target=<bfdname> Create an output file in format <bfdname>
-F --target=<bfdname> Set both input and output format to <bfdname>
-p --preserve-dates Copy modified/access timestamps to the output
-R --remove-section=<name> Remove section <name> from the output
-s --strip-all Remove all symbol and relocation information
-g -S -d --strip-debug Remove all debugging symbols & sections
--strip-unneeded Remove all symbols not needed by relocations
--only-keep-debug Strip everything but the debug information
-N --strip-symbol=<name> Do not copy symbol <name>
-K --keep-symbol=<name> Do not strip symbol <name>
--keep-file-symbols Do not strip file symbol(s)
-w --wildcard Permit wildcard in symbol comparison
-x --discard-all Remove all non-global symbols
-X --discard-locals Remove any compiler-generated symbols
-v --verbose List all object files modified
-V --version Display this program's version number
-h --help Display this output
--info List object formats & architectures supported
-o <file> Place stripped output into <file>
對於每個物件模組,strip 命令除去給出的選項所指定的資訊。對於每個歸檔檔案,strip 命令從歸檔中除去全域性符號表。
可以使用 ar -s 命令將除去的符號表恢復到歸檔檔案或庫檔案中。
沒有選項的 strip 命令除去行號資訊、重定位資訊、符號表、除錯段、typchk 段和註釋段。
標誌
-e 在物件檔案的可選頭中設定 F_LOADONLY 標誌。如果物件檔案放置在歸檔中,則該標誌告知繫結程式(ld 命令),在與此歸檔連結時應忽略該物件檔案中的符號。
-E 復位(關閉)物件檔案的可選頭中的 F_LOADONLY 位。(請參閱 -e 標誌。)
-H 除去物件檔案頭、任何可選的頭以及所有段的頭部分。
注:不除去符號表資訊。
-l (小寫 L)從物件檔案中除去行號資訊。
-r 除了外部符號和靜態符號條目,將全部符號表資訊除去。不除去重定位資訊。同時除去除錯段和 typchk 段。這個選項產生一個物件檔案,該物件檔案仍可以用作輸入到連結編輯器(ld 命令)中。
-t 除去大多數符號表資訊,但並不除去函式符號或行號資訊。
-V 列印 strip 命令的版本號。
-x 除去符號表資訊,但並不除去靜態或外部符號資訊。 -x 標誌同時除去重定位資訊,因此將不可能連結到該檔案。
-X mode 指定應檢查 strip 的物件檔案的型別。 mode 必須是下列之一:
32只處理 32 位物件檔案 ,64只處理 64 位物件檔案
32_64既處理 32 位物件檔案,又處理 64 位物件檔案
預設值是處理 32 位物件檔案(忽略 64 位物件檔案)。也可以用 OBJECT_MODE 環境變數來設定 mode。例如,OBJECT_MODE=64 使 strip 處理任何 64 位物件檔案,並忽略 32 位物件檔案。-X 標誌重設 OBJECT_MODE 變數。
-- (雙連字元)將跟隨在該標誌後的所有引數解釋為檔名。這就允許除去名稱是以連字元開始的檔案。
有的公司產品裡面的可執行程式和動態共享庫(DSO)裡面的符號表都被移除了,所以每次遇到core dump的時候,都需要將符號表匯入到/usr/lib/debug目錄下。一直沒弄明白為啥是這個目錄,能不能是其他目錄,今天沒啥事兒,研究了下這個主題。
我們要給我們生成的可執行檔案和DSO瘦身,因為這樣可以節省更多的磁碟空間,所以我們移除了debug資訊,移除了符號表資訊,同時我們還希望萬一出事了,比如coredump了,我們能獲取更多的資訊,這時候我們又希望有符號表。
http://blog.chinaunix.net/uid-24774106-id-3526766.html
然後,我們用strip命令將debug info 去除,指令如下,
- [email protected]:~/code/c/self/debug_symbol# strip --strip-debug test
eu-strip可以把檔案的符號表儲存起來,需要用的時候,匯入需要的符號表就能除錯coredump檔案了。
這次我直接生成了release版本的test了,然後用eu-strip將
另外補充file命令:
辨識檔案型別
該命令用來識別檔案型別,也可用來辨別一些檔案的編碼格式。它是通過檢視檔案的頭部資訊來獲取檔案型別,而不是像Windows通過副檔名來確定檔案型別的。
執行許可權 :All User
命令語法:
file [ -bchikLnNprsvz ] [ -f namefile ] [ -F separator ] [ -m magicfiles ] file ...
file [-beLvz][-f <名稱檔案>][-m <魔法數字檔案>...][檔案或目錄...]
LINUX中,將file檔案中的內容輸入到file.copy檔案中的命令是什麼?
可以如下操作: cat file > file.copy 這個問題很簡單,如果你瞭解了標準輸入,標準輸出