【转】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 212
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .standby 0000453c 800a47f8 800a47f8 000047f8 212
CONTENTS, ALLOC, LOAD, CODE
3 .text 003e22dc 800a8d34 800a8d34 00008d34 24
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .rodata 0012c460 8048c010 8048c010 003ec010 24
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .data 0002dd7c 805b8470 805b8470 00518470 23
CONTENTS, ALLOC, LOAD, DATA
6 .structure.init 00000384 805e61ec 805e61ec 005461ec 22
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .sdata 000022a8 805e6570 805e6570 00546570 23
CONTENTS, ALLOC, LOAD, DATA
8 .sbss 000014f8 805e8818 805e8818 00548818 23
ALLOC
9 .bss 002a5110 805e9d10 805e9d10 00548818 25
ALLOC
10 .reginfo 00000018 00000000 00000000 00548818 22
CONTENTS, READONLY, LINK_ONCE_SAME_SIZE
11 .mdebug 000818a4 00000000 00000000 00548830 22
CONTENTS, READONLY, DEBUGGING
12 .pdr 00066260 00000000 00000000 005ca0d4 22
CONTENTS, READONLY
13 .mdebug.abi32 00000000 00000000 00000000 00630334 20
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,方便理解
但注意会把所有宏都展开,包括系统头文件里面的宏,要自己查找想要的宏