linux中的strip命令简介

来源:互联网 发布:php发送异步请求 编辑:程序博客网 时间:2024/05/16 01:44

一、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-debugtest
   方法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这个问题很简单,如果你了解了标准输入,标准输出


     





0 0