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;  
    }  
然後我們看看結果:

[taoge@localhost learn_strip]$ ls  
main.c  
[taoge@localhost learn_strip]$ gcc main.c   
[taoge@localhost learn_strip]$ ls -l a.out   
-rwxrwxr-x 1 taoge taoge 4673 Jul 27 05:30 a.out  
[taoge@localhost 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  
[taoge@localhost 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 __libc_start_main@@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  
[taoge@localhost learn_strip]$ 

通過ls -l 命令可知, a.out的大小是4673個字節;

       通過file命令可知, a.out是可執行文件, 且是not stripped, 也就是說沒有脫衣服。

       通過nm命令, 可以讀出a.out中的符號信息。

[taoge@localhost learn_strip]$ ls  
a.out  main.c  
[taoge@localhost learn_strip]$ strip a.out   
[taoge@localhost learn_strip]$ ls -l a.out   
-rwxrwxr-x 1 taoge taoge 2980 Jul 27 05:34 a.out  
[taoge@localhost 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  
[taoge@localhost learn_strip]$ nm a.out   
nm: a.out: no symbols  
[taoge@localhost 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. root@manu:~/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
這個問題很簡單,如果你瞭解了標準輸入,標準輸出


     





發佈了34 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章