二进位实用程式(objdump, readelf,ar, nm等)

as (assembler)
组译器,当程式经过编译器后,输出的是组合语言,还需要经过组译器把组合语言转换成机械语言,通常输出结果为目的档(object file)。

ld (Linker)
连结器,把一只程式所有的目的档及其所需要的系统函式库都连结起来,才会产生出一个完整可执行的程式档。

ar
建立,操作静态函式库的内容,即是把原始码编译成目的档时,把这些目的档打包成一个静态函式库。

nm
此工具程式可以列出目的档或函式库中内含的物件名称,包括所有的函式名称与 全域变数的名称 .... 等。

Addr2line
把内含除错资讯的程式中某个特定位址转换成为原始码的档名以及其行号。

c++filt
它可以由组合标记反向对应出其原来的函式名称,以便连结 器参考使用,而此反向过程即称之为 demangling。

nlmconv
此工具程式可以将目的档转换成 NLM (NetWare Loadable Module) 的格式。

gprof
用来显示程式的效率测试资讯 (profiling)。通常在我们要试图提升程式的 执行效能时,我们必须要先知道程式的各部分到底花了多少时间来执行。

objcopy
此工具程式可以拷备、转换不同格式的目的档。

objdump
此工具程式可以列出目的档内含的资讯。

ranlib
此工具程式可以产生包裹档的内容索引,并加入该包裹档中。此包裹档即为 ar 程式所产生的包裹档。通常产生静态函式库时需要用到它。

readelf
此工具程式可以显示 ELF 格式的目的档内含的资讯。

size
此工具程式可以列出目的档或包裹档中各节区的大小。

strings
此工具程式可以列出档案中任何可印出的字串。

strip
此工具程式可以将目的档或可执行档中不必要的标记与资讯抽离,让该目的 档或可执行档的大小缩小。通常是除错资讯及其他符号标记。

 
GNU 二进位实用程式Binutils (GNU binary utilities)包括:objdumpreadelfaddr2linestriparnmlddngprofgcov等。
一。 objdump - 显示二进位档案资讯
objdump可以根据目的档案来生成可读性比较好的汇编档。常用的命令如下:
gcc -g3 test.c -o test.o 
objdump -Slz test.o
 
objdump
命令介绍,可以通过 man objdumplinux环境下获取到。 
       [-a] [-b bfdname |
 
       --target=bfdname] [-C] [--debugging]
 
       [-d] [-D]
 
       [--disassemble-zeroes]
 
       [-EB|-EL|--endian={big|little}] [-f]
 
       [-h] [-i|--info]
 
       [-j section | --section=section]
 
       [-l] [-m machine ] [--prefix-addresses]
 
       [-r] [-R]
 
       [-s|--full-contents] [-S|--source]
 
       [--[no-]show-raw-insn] [--stabs] [-t]
 
       [-T] [-x]
 
       [--start-address=address] [--stop-address=address]
 
       [--adjust-vma=offset] [--version] [--help]
 
       objfile...
 
  -a, --archive-headers    Display archive header information
 
  -f, --file-headers       Display the contents of the overall file header
 
  -p, --private-headers    Display object format specific file header contents
 
  -h, --[section-]headers  Display the contents of the section headers
 
  -x, --all-headers        Display the contents of all headers
 
  -d, --disassemble        Display assembler contents of executable sections
 
  -D, --disassemble-all    Display assembler contents of all sections
 
  -S, --source             Intermix source code with disassembly
 
  -s, --full-contents      Display the full contents of all sections requested
 
  -g, --debugging          Display debug information in object file
 
  -e, --debugging-tags     Display debug information using ctags style
 
  -G, --stabs              Display (in raw form) any STABS info in the file
 
  -W, --dwarf              Display DWARF info in the file
 
  -t, --syms               Display the contents of the symbol table(s)
 
  -T, --dynamic-syms       Display the contents of the dynamic symbol table
 
  -r, --reloc              Display the relocation entries in the file
 
  -R, --dynamic-reloc      Display the dynamic relocation entries in the file
 
  @                  Read options from
 
  -v, --version            Display this program's version number
 
  -i, --info               List object formats and architectures supported
 
  -H, --help               Display this information
--archive-headers 
-a 
显示档案库的成员资讯,与 ar tv 类似
     objdump -a libpcap.a 
     
 ar -tv libpcap.a 显示结果比较比较 
     
显然这个选项没有什么意思。
--adjust-vma=offset 
     When   dumping   information, first add offset to all
 
     the section addresses.   This is useful if the   sec-
 
     tion   addresses   do   not correspond   to the symbol
 
     table, which can happen when   putting   sections   at
 
     particular   addresses when using a format which can
 
     not represent section addresses, such as a.out.
-b bfdname 
--target=bfdname
 
     
指定目的码格式。这不是必须的,objdump能自动识别许多格式, 
     
比如:objdump -b oasys -m vax -h fu.o 
     
显示fu.o的头部摘要资讯,明确指出该档是Vax系统下用Oasys 
     
编译器生成的目的档案。objdump -i将给出这里可以指定的 
     
目的码格式列表
--demangle 
-C 
将底层的符号名解码成使用者级名字,除了去掉所有开头 
    
的底线之外,还使得C++函数名以可理解的方式显示出来。
--debugging 
     
显示调试资讯。企图解析保存在档中的调试资讯并以C语言 
     
的语法显示出来。仅仅支援某些类型的调试资讯。
--disassemble 
-d 
反汇编那些应该还有指令机器码的section
--disassemble-all 
-D 
 -d 类似,但反汇编所有section
--prefix-addresses 
     
反汇编的时候,显示每一行的完整位址。这是一种比较老的反汇编格式。 
     
显示效果并不理想,但可能会用到其中的某些显示,自己可以对比。
--disassemble-zeroes 
     
一般反汇编输出将省略大块的零,该选项使得这些零块也被反汇编。
-EB 
-EL
 
--endian={big|little}
 
     
这个选项将影响反汇编出来的指令。 
     little-endian
就是我们当年在dos下玩汇编的时候常说的高位在高位址, 
     x86
都是这种。
--file-headers 
-f 
显示objfile中每个档的整体头部摘要资讯。
--section-headers 
--headers
 
-h 
显示目的档案各个section的头部摘要资讯。
--help 简短的说明资讯。
--info 
-i 
显示对于 -b 或者 -m 选项可用的架构和目标格式清单。
--section=name 
-j name 
仅仅显示指定section的资讯
--line-numbers 
-l 
用档案名和行号标注相应的目标代码,仅仅和-d-D或者-r一起使用 
    
使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求 
    
编译时使用了-g之类的调试编译选项。
--architecture=machine 
-m machine
 
     
指定反汇编目的档案时使用的架构,当待反汇编档本身没有描述 
     
架构资讯的时候(比如S-records),这个选项很有用。可以用-i选项 
     
列出这里能够指定的架构
--reloc 
-r 
显示档的重定位入口。如果和-d或者-D一起使用,重定位部分以反汇 
    
编后的格式显示出来。
--dynamic-reloc 
-R 
显示档的动态重定位入口,仅仅对于动态目的档案有意义,比如某些 
    
共用库。
--full-contents 
-s 
显示指定section的完整内容。
     objdump --section=.text -s inet.o | more
--source 
-S 
尽可能反汇编出原始程式码,尤其当编译的时候指定了-g这种调试参数时, 
    
效果比较明显。隐含了-d参数。
--show-raw-insn 
     
反汇编的时候,显示每条汇编指令对应的机器码,除非指定了 
     --prefix-addresses
,这将是缺省选项。
--no-show-raw-insn 
     
反汇编时,不显示汇编指令的机器码,这是指定 --prefix-addresses 
     
选项时的缺省设置。
--stabs 
     Display the contents of the .stab, .stab.index, and
 
     .stab.excl sections from an ELF file.   This is only
 
     useful   on   systems   (such as Solaris 2.0) in which
 
     .stab debugging symbol-table entries are carried in
 
     an ELF section. &
二。 readelf -- 显示elf档资讯
LINUX 平台下三种主要的可执行档格式:a.outassembler and link editor output 汇编器和连结编辑器的输出)、COFFCommon Object File Format 通用物件档案格式)、ELFExecutable and Linking Format可执行和连结格式)。
a.out 档包含 7  section,格式如下:
exec header(执行头部,也可理解为档头部)
text segment(文本段)
data segment(资料段)
text relocations(文本重定位段)
data relocations(资料重定位段)
symbol table(符号表)
string table(字串表)
执行头部的资料结构:
struct exec {
unsigned long a_midmag; /* 魔数和其它资讯 */
unsigned long a_text; /* 文本段的长度 */
unsigned long a_data; /* 资料段的长度 */
unsigned long a_bss; /* BSS段的长度 */
unsigned long a_syms; /* 符号表的长度 */
unsigned long a_entry; /* 程式进入点 */
unsigned long a_trsize; /* 文本重定位表的长度 */
unsigned long a_drsize; /* 资料重定位表的长度 */
};
a.out 的格式非常紧凑,只包含了程式运行所必须的资讯(文本、资料、BSS),而且每个 section 的顺序是固定的。这种结构缺乏扩展性,a.out 档中包含符号表和两个重定位表,这三个表的内容在连接目的档案以生成可执行档时起作用。在最终可执行的 a.out 文件中,这三个表的长度都为 0a.out 档在连接时就把所有外部定义包含在可执行程式中,如果从程式设计的角度来看,这是一种硬编码方式,或者可称为模组之间是强藕和的。a.out 是早期UNIX系统使用的可执行档格式,由 AT&T 设计,现在基本上已被 ELF 档案格式代替。a.out 的设计比较简单,但其设计思想明显的被后续的可执行档格式所继承和发扬。这里我们著重介绍elf格式。
1. elf格式介绍
Executable and linking format(ELF)档是Linux系统下的一种常用目的档案(object file)格式,有三种主要类型:
(1)适于连接的可重定位文件(relocatable file),可与其它目的档案一起创建可执行档和共用目的档案 .obj or .o
(2)适于执行的可执行档(executable file),用于提供程式的进程映射,载入的记忆体执行。
(3)共用目的档案(shared object file),连接器可将它与其它可重定位文件和共用目的档案连接成其它的目的档案,动态连接器又可将它与可执行档和其它共用目的档案结合起来创建一个进 程映射。
ELF档内容有两个平行的视角:一个是程式连接角度,另一个是程式运行角度。
ELF header在档开始处描述了整个档的组织,Section提供了目的档案的各项资讯(如指令、资料、符号表、重定位资讯等),Program header table指出怎样创建进程映射,含有每个program header的入口,Section header table包含每一个section的入口,给出名字、大小等资讯。
 
段由若干个节(Section)构成,节头表对每一个节的资讯有相关描述。对可执行程式而言,节头表是可选的。ELF头部是一个关于本档的路线图 road map),从总体上描述档的结构。下面是ELF头部的资料结构:
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* 魔数和相关资讯 */
Elf32_Half e_type; /* 目的档案类型 */
Elf32_Half e_machine; /* 硬体体系 */
Elf32_Word e_version; /* 目的档案版本 */
Elf32_Addr e_entry; /* 程式进入点 */
Elf32_Off e_phoff; /* 程式头部偏移量 */
Elf32_Off e_shoff; /* 节头部偏移量 */
Elf32_Word e_flags; /* 处理器特定标志 */
Elf32_Half e_ehsize; /* ELF头部长度 */
Elf32_Half e_phentsize; /* 程式头部中一个条目的长度 */
Elf32_Half e_phnum; /* 程式头部条目个数 */
Elf32_Half e_shentsize; /* 节头部中一个条目的长度 */
Elf32_Half e_shnum; /* 节头部条目个数 */ Elf32_Half e_shstrndx; /* 节头部字元表索引 */
} Elf32_Ehdr;
2.  readelf 命令
readelf命令可以显示符号、段资讯、二进位档案格式的资讯等,这在分析编译器如何工从原始程式码创建二进位档案时非常有用。
$ readelf -h a.out
ELF Header: 
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
 
  Class:                             ELF64
 
  Data:                              2's complement, little endian
 
  Version:                           1 (current)
 
  OS/ABI:                            UNIX - System V
 
  ABI Version:                       0
 
  Type:                              EXEC (Executable file)
 
  Machine:                           Advanced Micro Devices X86-64
 
  Version:                           0x1
 
  Entry point address:               0x4003c0
 
  Start of program headers:          64 (bytes into file)
 
  Start of section headers:          2704 (bytes into file)
 
  Flags:                             0x0
 
  Size of this header:               64 (bytes)
 
  Size of program headers:           56 (bytes)
 
  Number of program headers:         8
 
  Size of section headers:           64 (bytes)
 
  Number of section headers:         29
 
  Section header string table index: 26
三。 addr2line -- 将位址对应到档案名和行号
四。 as -- GNU汇编器
as工具主要用来将组合语言编写的来源程式转换成二进位形式的目标代码。Linux平台的标准汇编器是GAS,它是Gnu GCC编译器所依赖的后台汇编工具,通常包含在Binutils套装软体中。
l        ld GNU的连结器
五。 ld -- GNU连结程式
as一样,ld也是GNU Binutils工具集中重要的工具,Linux使用ld作为标准的连结程式,由汇编器产生的目标代码是不能直接在电脑上运行的,它必须经过连结器的处 理才能生成可执行代码,连结是创建一个可执行程式的最后一个步骤,ld可以将多个目的档案连结成为可执行程式,同时指定了程式在运行时是如何执行的。
六。 ar
ar命令可以用来创建、修改库,也可以从库中提出单个模组。库是一单独的档,里面包含了按照特定的结构组织起来的其它的一些文件(称做此库文件的 member)。原始档的内容、模式、时间戳记、属主、组等属性都保留在库档中。有关ar命令使用的例子,(引自http://blog.163.com/huang_bp/blog/getBlog.do?bid=fks_083075087083082069083086083095085084082066085095094064083):
1.    要创建一个库,请输入:
ar -v -q lib.a strlen.o strcpy.o
如果 lib.a 库不存在,则此命令创建它,并将文件 strlen.o  strcpy.o 的副本输入其中。如果 lib.a 库存在,则此命令在不检查相同成员的情况下,将新的成员添加到末尾。标志设置详细方式,在此方式中 ar命令在其进行时显示进程报告。
2.     要显示库的目录,请输入: ar -v -t lib.a
此命令列出了 lib.a 库的目录,显示类似于 ls -l 命令的输出的长列表。要只列出成员档案名称,则省略 -v标志。
3.     要替换或添加新成员到库中,请输入: ar -v -r lib.a strlen.o strcat.o
此命令替换成员 strlen.o  strcat.o。如果 lib.a 如示例 1 中显示的那样创建,则替换 strlen.o 成员。因为不存在名为 strcat.o 的成员,所以它被添加到库的末尾。
4.     要指定在何处插入新成员,请输入: ar -v -r -b strlen.o lib.a strcmp.o
此命令添加 strcmp.o 文件,并将该新成员置于 strlen.o 成员之前。
5.     要更新一个已经更改过的成员,请输入: ar -v -r -u lib.a strcpy.o
此命令替换现有 strcpy.o 成员,但仅当文件 strcpy.o 自从最后一次添加到库后已经修改时才替换它。
6.     要更改库成员的顺序,请输入: ar -v -m -a strcmp.o lib.a strcat.o strcpy.o
此命令将成员 strcat.o  strcpy.o 移动到紧跟在 strcmp.o  员之后的位置。保留 strcat.o  strcpy.o 成员的相对顺序。换句话说,如果在移动之前 strcpy.o 成员在 strcat.o 成员之前,那么(移动后)它依旧如此。
7.     要解压缩库成员,请输入: ar -v -x lib.a strcat.o strcpy.o
此命令将成员 strcat.o  strcpy.o 分别复制到名为 strcat.o  strcpy.o 的文件。
8.     要解压缩并重命名一个成员,请输入: ar -p lib.a strcpy.o >stringcopy.o
此命令将成员 strcpy.o 复制到一个名为 stringcopy.o 的文件。
9.     要删除一个成员,请输入: ar -v -d lib.a strlen.o
此命令从 lib.a 库中删除成员 strlen.o
10.   要从多个用 ld 命令创建的共用模组中创建一个压缩文件库,请输入: ar -r -v libshr.a shrsub.o shrsub2.o shrsub3.o ...
此命令从名为 shrsub.oshrsub2.oshrsub3.o 等等的共用模组中创建名为 libshr.a 的压缩文件库。要编译并连结使用 libshr.a 压缩文件库的 main 程式,请使用以下命令:
cc -o main main.c -L/u/sharedlib -lshr
main 程式现在是可执行的。main 程式引用的任何符号(包含在libshr.a 压缩文件库中)已经因延迟解析度而作了标记。-l 标志指定应在 libshr.a 库中搜索这些符号。
11.   要列出 lib.a 的内容(忽略任何 32 位目的档案),请输入: ar -X64 -t -v lib.a
12.   要从 lib.a 解压缩所有 32 位的目的档案,请输入: ar -X32 -x lib.a
13.   要列出 lib.a 中的所有档,无论是 32 位、64 位元或非物件,请输入: ar -X32_64 -t -v lib.a
七。nm
nm用来列出目的档案的符号清单。下面是nm命令的格式:
nm[-a|--debug-syms][-g|--extern-only][-B] 
[-C|--demangle][-D|--dynamic][-s|--print-armap]
 
[-o|--print-file-name][-n|--numeric-sort]
 
[-p|--no-sort][-r|--reverse-sort][--size-sort]
 
[-u|--undefined-only][-l|--line-numbers][--help]
 
[--version][-tradix|--radix=radix]
 
[-P|--portability][-fformat|--format=format]
 
[--target=bfdname][objfile...]
 
如果没有为nm命令指出目的档案,则nm假定目的档案是a.out。下面列出该命令的任选项,大部分支援“-”开头的短格式和“-“开头的长格 式。 -A-o--print-file-name:在找到的各个符号的名字前加上档案名,而不是在此档的所有符号前只出现档案名一次。
八。objcopy
它可以把目的档案的内容从一种档案格式复制到另一种格式的目的档案中。通过objcopy可以实现对elf不同模组的分析,同时实现类似strip 的功能。
九。ldd
ldd 命令可以用来产看应用程式对库的依赖关系,在应用程式移植过程中很有用。可以首先确认要移植平时是否支援应用程式所依赖的库。例如:
$ ldd aout 
        libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9566c000)
 
        /lib64/ld-linux-x86-64.so.2 (0x0000002a95556000)
十。size
size 列出目的模组或档的代码尺寸
$ size a.out 
   text    data     bss     dec     hex filename
 
   1241     512       8    1761     6e1 a.out
十一。ranlib
ranlib 生成索引以加快对归档档的访问,并将结果保存到这个归档档中,在索引中列出了归档档各个成员所定义的可重分配目的档案。ar -s可以实现类似的功能。
十二。strings
      strings 列印可列印的目标代码字元(至少4个字元),列印字元多少可以控制.对于其它各式的档,列印字串。列印某个档的可列印字串,这些字串最少4个字 符长,也可以使用选项“-n”设置字串的最小长度。预设情况下,它只列印目的档案初始化和可载入段中的可列印字元;对于其他类型的的档它列印整个档 的可列印字元,这个程式对于了解非文字档内容很有说明。
十三。strip
      删除目的档案中的全部或者特定符号,这样可以减小可执行档的大小。在嵌入式应用中,可执行档一般存放在flash中,空间有限,因此在产品 release的过程中采用strip对程式进行裁剪很有必要。
十三。gprof
gprofLinux下一个强有力的程式分析工具。能够以日志的形式记录程式运行时的统计资讯:程式运行中各个函数消耗的时间和函式呼叫关 系,以及每个函数被调用的次数等等。从而可以说明程式师找出众多函数中耗时最多的函数,也可以说明程式师分析程式的运行流程。相信这些功能对于分析开源代 码的程式师来说,有著相当大的诱惑力;同时我们也可以借助gprof进行性能优化和分析。
gprof对程式进行分析主要分以下三个步骤:
l         用编译器对程式进行编译,加上-pg参数。
l         运行编译后的程式。
l         gprof命令查看程式的运行时资讯。
先以一个简单的例子演示一下吧。随便找一个能够运行的程式的原始程式码,比如下面的档test.c
int IsEven(int x)
{
        return 0 == x & 1;
}
int main(int argc, char *argv[]
{
        int i = 0;
        while(++i < 1000) IsEven(i);
}
首先,用以下命令进行编译:
       [root@localhost]#gcc –o test –pg test.c
然后,运行可执行档test.
       [root@localhost]#./test
运行后,在目前的目录下将生成一个档gmon.out,这就是gprof生成的档,保存有程式运行期间函式呼叫等资讯。
最后,用gprof命令查看gmon.out保存的资讯:
       [root@localhost]#gprof test gmon.out –b
这样就有一大堆资讯输出到萤幕上,有函数执行单间,函式呼叫关系图等等,如下:
Flat profile:
Each sample counts as 0.01 seconds.
no time accumulated
  %   cumulative   self              self     total          
time   seconds   seconds    calls  Ts/call  Ts/call  name   
  0.00      0.00     0.00     1000     0.00     0.00  IsEven(int)
                     Call graph
granularity: each sample hit covers 2 byte(s) no time propagated
index % time    self  children    called     name
                0.00    0.00    1000/1000        main [7]
[8]      0.0    0.00    0.00    1000         IsEven(int) [8]
-----------------------------------------------
Index by function name
   [8] IsEven(int)
以上介绍了gprof最简单的使用方法,下面针对其使用过程中的三个步骤详细说明。
编译和连结
上面的例子中,程式比较简单,只有一个档。如果原始程式码有多个档,或者代码结构比较复杂,编译过程中先生成若干个目的档案,然后又由连结器将这些 目的档案连结到一起,这时该怎么使用gprof呢?
对于由多个原始档案组成的程式,编译时需要在生成每个.o档的时候加上-pg参数,同时在连结的时候也要加上-pg参数。对于连结器不是GCC的情 况,如ld,又有特殊的要求。
同时,-pg参数只能记录原始程式码中各个函数的调用关系,而不能记录库函数的调用情况。要想记录每个库函数的调用情况,连结的时候必须指定库函数的动 态(或者静态)程式库libc_p.a,即加上-lc_p,而不是-lc
还要说明的是,如果有一部分代码在编译时指定了-pg参数,而另一部分代码没有指定,则生成的gmon.out档中将缺少一部分函数,也没有那些 函数的调用关系。但是并不影响gprof对其它函数进行记录。
运行
编译好的程式运行时和运行一般的程式没有什么不同,只是比正常的程式多生成了一个档gmon.out。注意,这个档案名是固定的,没法通过参数的 设置进行改变。如果程式目录中已经有一个gmon.out,则它会被新的gmon.out覆盖掉。
关于生成的gmon.out档所在的目录,也有以下约定:程式退出时所运行的档所在目录就是生成的gmon.out档所在的目录。如果一个程 序执行过程中调用了另一个程式,并在另一个程式的运行中终止,则gmon.out会在另一个程式所在的目录中生成。
还有一点要注意的就是当程式非正常终止时不会生成gmon.out档,也因此就没法查看程式运行时的资讯。只有当程式从main函数中正常退出, 或者通过系统调用exit()函数而退出时,才会生成gmon.out文件。而通过底层调用如_exit()等退出时不会生成gmon.out
查看
查看程式运行资讯的命令是gprof,它以gmon.out档作为输入,也就是将gmon.out档翻译成可读的形式展现给用户。其命令格式如 下:
       gprof [可执行档] [gmon.out文件] [其它参数]
方括号中的内容可以省略。如果省略了可执行档gprof会在目前的目录下搜索a.out档作为可执行档,而如果省略了gmon.out 件,gprof也会在目前的目录下寻找gmon.out。其它参数可以控制gprof输出内容的格式等资讯。最常用的参数如下:
l         -b 不再输出统计图表中每个栏位的详细描述。
l         -p 只输出函数的调用图(Call graph的那部分资讯)。
l         -q 只输出函数的时间消耗清单。
l         -e Name 不再输出函数Name 及其子函数的调用图(除非它们有未被限制的其它父函数)。可以给定多个 -e 标志。一个 -e 标志只能指定一个函数。
l         -E Name 不再输出函数Name 及其子函数的调用图,此标志类似于 -e 标志,但它在总时间和百分比时间的计算中排除了由函数Name 及其子函数所用的时间。
l         -f Name 输出函数Name 及其子函数的调用图。可以指定多个 -f 标志。一个 -f 标志只能指定一个函数。
l         -F Name 输出函数Name 及其子函数的调用图,它类似于 -f 标志,但它在总时间和百分比时间计算中仅使用所列印的常式的时间。可以指定多个 -F 标志。一个 -F 标志只能指定一个函数。-F 标志覆盖 -E 标志。
l         -z 显示使用次数为零的常式(按照调用计数和累积时间计算)。
不过,gprof不能显示物件之间的继承关系,这也是它的弱点.
参考文献:
5. 熟悉binutils工具集 http://yunli.blog.51cto.com/831344/186727 (推荐)

 

相关文章