【转】GCC 工具链使用

转自:https://blog.csdn.net/icarman/article/details/108647809

GCC 工具链使用

GCC 有很多编译,链接工具,同时还有一些查看工具,方便用户查看生成的object文件,ELF文件信息等。这里简单介绍常用的GCC工具的使用方法。

1. nm:list symbols from object files

可以从.a, .o, .out(elf)文件中读出符号表(函数名,变量名),还可以发现函数在那个文件/库中定义和被调用,如:

$nm -A lib/MSD7853/release/*.a | grep CSUDIPlusOSTimerStop

获得信息如下:
libkernel.a:event.o: U CSUDIPlusOSTimerStop
libkernel.a:dsm_sg.o: U CSUDIPlusOSTimerStop
libos_udi2_to_udi1.a:udi1_os.o: U CSUDIPlusOSTimerStop
libUDIPlus.a:udiplus_ostimer.o:00000308 T CSUDIPlusOSTimerStop
U: 表示undifined,即该库里面调用该函数, 在其他库中定义。
T:表示函数在库中是全局函数的定义("t"表示局部函数定义)。
W:表示函数在当前库中定义,被其它库中的函数覆盖

所以,从这个例子里面可以看到CSUDIPlusOSTimerStop是在库libUDIPlus.a的udiplus_ostimer.c文件中实现。

nm还有作用就是直接通过可执行文件生成相应的map文件。当然,这个前提是改可执行文件没有被strip命令裁剪过。命令如下:
nm integration/product/a.out > flash.map

可以输出执行文件函数地址和函数名称的对照表
nm -n --defined-only -C a.out > a.sym

2. readelf: Display information about ELF files

$readelf -s: 显示ELF的符号表信息(变量和函数)
列出的项目中有两项比较重要的参考信息
Type: 
FILE- ELF中使用到的文件
FUNC- 定义的函数
OBJECT- 变量,数组或指针等
NOTYPE- 未定义的应用,通常是调用到的外部函数
SECTION-
Bind:
GLOBAL-全局的函数或变量
LOCAL-局部函数或变量

$readelf -s test.o | grep FILE: 有可能test.o由多个.o直接merge而成,该指令可以找出这个test.o是有那些.c文件合成的
$readelf -s test.o | grep FUNC: 列出test.c中的函数
$readelf -s test.o | grep NOTYPE: 列出test.c中调用的其他函数

如何判断执行文件或者目标文件(.o文件)带有debug信息(-g 编译的)?
$readelf -S 查看section header信息,即段header信息
$readelf -S libxxx.so |grep debug
$readelf -S xx.o |grep debug
如果输出有debug字样的,就是带有debug信息的(-g 编译的),如:
[12] .debug_info MIPS_DWARF 00000000 009b90 008200 00 0 0 1
[13] .rel.debug_info REL 00000000 0220f4 004be8 08 I 28 12 4
[14] .debug_abbrev MIPS_DWARF 00000000 011d90 00042a 00 0 0 1
[15] .debug_loc MIPS_DWARF 00000000 0121ba 00574e 00 0 0 1
[16] .rel.debug_loc REL 00000000 026cdc 000040 08 I 28 15 4
[17] .debug_aranges MIPS_DWARF 00000000 017908 000020 00 0 0 1
[18] .rel.debug_arange REL 00000000 026d1c 000010 08 I 28 17 4
[19] .debug_ranges MIPS_DWARF 00000000 017928 000120 00 0 0 1
[20] .debug_line MIPS_DWARF 00000000 017a48 001513 00 0 0 1
[21] .rel.debug_line REL 00000000 026d2c 000008 08 I 28 20 4
[22] .debug_str MIPS_DWARF 00000000 018f5b 0022b9 01 MS 0 0 1
[25] .debug_frame MIPS_DWARF 00000000 01b26c 000698 00 0 0 4
[26] .rel.debug_frame REL 00000000 026d34 0002d0 08 I 28 25 4

readelf -e
显示 elf header信息, 和 objdump -h 类似
$readelf -e a.out
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2’s complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x80000200
Start of program headers: 52 (bytes into file)
Start of section headers: 16363192 (bytes into file)
Flags: 0x70001001, noreorder, o32, mips32r2
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 29
Section header string table index: 26

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .jump_boot PROGBITS 80000200 000080 000010 00 AX 0 0 16
[ 2] .boot PROGBITS 800a0a00 000a00 003df8 00 AX 0 0 4096
[ 3] .standby PROGBITS 800a47f8 0047f8 00453c 00 WAX 0 0 4096
[ 4] .text PROGBITS 800a8d34 008d34 3e22dc 00 AX 0 0 16
[ 5] .rodata PROGBITS 8048c010 3ec010 12c460 00 A 0 0 16
[ 6] .data PROGBITS 805b8470 518470 02dd7c 00 WA 0 0 8
[ 7] .structure.init PROGBITS 805e61ec 5461ec 000384 00 A 0 0 4
[ 8] .sdata PROGBITS 805e6570 546570 0022a8 00 WAp 0 0 8
[ 9] .sbss NOBITS 805e8818 548818 0014f8 00 WAp 0 0 8
[10] .bss NOBITS 805e9d10 548818 2a5110 00 WA 0 0 32
[11] .reginfo MIPS_REGINFO 00000000 548818 000018 18 0 0 4
[12] .mdebug MIPS_DEBUG 00000000 548830 0818a4 01 0 0 4
[13] .pdr PROGBITS 00000000 5ca0d4 066260 00 0 0 4
[14] .mdebug.abi32 PROGBITS 00000000 630334 000000 00 0 0 1
[15] .debug_abbrev MIPS_DWARF 00000000 630334 06d77b 00 0 0 1
[16] .debug_info MIPS_DWARF 00000000 69daaf 63d645 00 0 0 1
[17] .debug_line MIPS_DWARF 00000000 cdb0f4 0f9b51 00 0 0 1
[18] .debug_frame MIPS_DWARF 00000000 dd4c48 06e1d4 00 0 0 4
[19] .debug_pubnames MIPS_DWARF 00000000 e42e1c 055890 00 0 0 1
[20] .debug_aranges MIPS_DWARF 00000000 e986ac 023660 00 0 0 1

3. ldd: print shared library dependencies

打印可执行档依赖的共享库文件, 但是ldd本身不是一个程序,而仅是一个shell脚本

4. objdump: 产生反汇编文件

$objdump -D a.out > a.dis

$objdump -h, 获取elf各个段信息
$ objdump -h a.out
a.out: file format elf32-tradlittlemips

Sections:
Idx Name Size VMA LMA File off Algn
0 .jump_boot 00000010 80000200 80000200 00000080 24
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .boot 00003df8 800a0a00 800a0a00 00000a00 2
12
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .standby 0000453c 800a47f8 800a47f8 000047f8 212
CONTENTS, ALLOC, LOAD, CODE
3 .text 003e22dc 800a8d34 800a8d34 00008d34 2
4
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .rodata 0012c460 8048c010 8048c010 003ec010 24
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .data 0002dd7c 805b8470 805b8470 00518470 2
3
CONTENTS, ALLOC, LOAD, DATA
6 .structure.init 00000384 805e61ec 805e61ec 005461ec 22
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .sdata 000022a8 805e6570 805e6570 00546570 2
3
CONTENTS, ALLOC, LOAD, DATA
8 .sbss 000014f8 805e8818 805e8818 00548818 23
ALLOC
9 .bss 002a5110 805e9d10 805e9d10 00548818 2
5
ALLOC
10 .reginfo 00000018 00000000 00000000 00548818 22
CONTENTS, READONLY, LINK_ONCE_SAME_SIZE
11 .mdebug 000818a4 00000000 00000000 00548830 2
2
CONTENTS, READONLY, DEBUGGING
12 .pdr 00066260 00000000 00000000 005ca0d4 22
CONTENTS, READONLY
13 .mdebug.abi32 00000000 00000000 00000000 00630334 2
0
CONTENTS, READONLY
14 .debug_abbrev 0006d77b 00000000 00000000 00630334 2**0

5. objcopy: 主要用于抽取执行文件.out文件中的各类段。

6. strip: 丢弃目标文件中的全部或者特定符号

Remove all debugging symbols & sections of object files,删除object中的全部debug信息
这样生成的object size较小,并且可以防止反汇编,安全性更高
$strip -g -S -d ${OBJS}

7. ar: 把.o 打包生成.a库文件或者把.a 拆成.o文件

$ar -r a.o b.o c.o test.a

8. gprof:可以显示程序运行的“flat profile”,包括每个函数的调用次数,每个函数消耗的处理器时间。

也可以显示“调用图”,包括函数的调用关系,每个	函数调用花费了多少时间。还可以显示“注释的源代码”,
是程序源代码的一个复本,标记有程序中每行代码的执行次数。命令行参数中加入“-pg”选项
 
  • 1
  • 2

9. gcov: 一个保险测试工具。当构建一个程序时,gcov会监视一个程序的执行,并且会标识出执行了哪一行源码,哪一行没有执行

10. size: 列出目标文件每一段的大小以及总体的大小

11. gcc -M test.c

不编译test.c, 仅仅列出test.c所依赖的.h头文件
$gcc -MM test.c
仅仅列出test.c所依赖的.h头文件,不包括系统头文件
查看gcc所定义的所有预定义宏
$cpp -dM /dev/null

14. gcc -E -P test.c > test_macro.txt

gcc对test.c 进行预处理即可看到宏展开后的代码,输出到test_macro.txt,方便理解
但注意会把所有宏都展开,包括系统头文件里面的宏,要自己查找想要的宏

 
原文地址:https://www.cnblogs.com/langqi250/p/13901691.html