1. 程式人生 > >linux中的strip命令簡介

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 去除,指令如下,

  1. [email protected]:~/code/c/self/debug_symbol# strip --strip-debug test
   方法1 使用eu-strip
    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
這個問題很簡單,如果你瞭解了標準輸入,標準輸出