编译与调试工具

gcc

gccg++分别是gnu的cc++编译器,gcc/g++在执行编译工作的时候,总共需要4步:

  1. 预处理: 生成预处理文件,后缀名 .i (预处理器cpp)
  2. 编译: 预处理后的文件编译生成汇编语言文件,后缀名 .s(编译器egcs)
  3. 汇编: 汇编语言文件汇编生成目标代码(机器代码)文件,后缀名.o (汇编器as)
  4. 链接: 链接目标代码, 生成可执行文件 (链接器ld)

参数详解

  • -x language filename 设定文件所使用的语言,使后缀名无效,对以后的多个文件有效,直到下一个参数的使用。
    language可以是:
    c, objective-c, c-header, c++, cpp-output, assembler, assembler-with-cpp
    例如: gcc -x c hello.pig
  • -x none filename 关掉上一个选项,即让gcc根据文件名后缀,自动识别文件类型
    例如: gcc -x c hello.pig -x none hello2.c
  • -c 只激活预处理编译汇编,生成后缀名.o的obj文件
    例如: gcc -c hello.c
  • -S 只激活预处理编译,生成后缀名.s的汇编代码文件。
    例如: gcc -S hello.c
  • -E 只激活预处理,不生成文件,你需要把它重定向到一个输出文件里面。
    例如: gcc -E hello.c > pianoapan.txt
  • -o 指定目标名称,缺省的时候,gcc 编译出来的文件是a.out
    例如: gcc -o hello hello.cgcc -o hello.asm -S hello.c
  • -pipe 使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题
    例如: gcc -pipe -o hello.exe hello.c
  • -ansi 关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性
    (包括禁止asminlinetypeof关键字,以及unixvax等预处理宏)。具体参考man page
  • -fno-asm 此选项实现ansi选项的功能的一部分,它禁止将asm,inlinetypeof用作关键字。
  • -fno-strict-prototype 只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数的个数和类型说明,而不是没有参数。 而gcc无论是否使用这个参数,都将对没有带参数的函数,认为是没有显式说明的类型。
  • -fthis-is-varialble 就是向传统c++看齐,可以使用this当一般变量使用。
  • -fcond-mismatch 允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型
  • -funsigned-char-fno-signed-char-fsigned-char-fno-unsigned-char
    这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参数)或者 signed char(后两个参数)
  • -include file 包含某个代码,简单来说,就是当某个文件需要另一个文件的时候,就可以用它设定,功能就相当于在代码中使用#include<filename>
    例如: gcc hello.c -include /root/pianopan.h
  • -imacros filefile文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中。这个选项跟-include选项很像,但是任何通过扫描file产生的输出都被丢弃,定义的选项仍被定义,这允许你获得所有头文件的宏定义但不处理他的声明。所有该选项指定的文件将在-include选项指定的文件之前处理。
  • -Dmacro 相当于C语言中的#define macro
  • -Dmacro=defn 相当于C语言中的#define macro=defn
  • -Umacro 相当于C语言中的#undef macro
  • -undef 取消对任何非标准宏的定义
  • -Idir 在你使用#include "file"的时候,gcc/g++会先在当前目录查找你所指定的头文件,如果没有找到,他会到缺省的头文件目录找,如果使用-I指定了目录,他会先在你所指定的目录查找,然后再按常规的顺序去找。对于#include <file>, gcc/g++会到-I指定的目录查找,查找不到,然后将到系统的缺省的头文件目录查找。
  • -I- 就是取消前一个参数的功能,所以一般在-Idir之后使用
  • -idirafter dir-I的目录里面查找失败,将到这个目录里面查找。
  • -iprefix prefix-iwithprefix dir 一般一起使用,当-I的目录查找失败,会到prefix+dir下查找
  • -nostdinc 使编译器不在系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头文件的位置
  • -nostdinc++ 规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,此选项在创建libg++库使用
  • -C 在预处理的时候,不删除注释信息,一般和-E一起使用,有时候分析程序,用这个很方便的
  • -M 生成文件关联的信息。包含目标文件所依赖的所有源代码,你可以用gcc -M hello.c 来测试一下,很简单。
  • -MM 和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。
  • -MD-M相同,但是输出将导入到.d的文件里面
  • -MMD-MM相同,但是输出将导入到.d的文件里面
  • -Wa,option 此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然后传递给汇编程序
  • -Wl.option 此选项传递option给链接程序;如果option中间有逗号,就将option分成多个选项,然后传递给链接程序.
  • -llibrary 指定编译的时候使用的库 例如: gcc -lcurses hello.c
  • -Ldir 指定编译的时候,搜索库的路径。如果不指定,编译器将只在标准库的目录找。
  • -O0-O1-O2-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
  • -g 指示编译器,在编译的时候,产生调试信息。
  • -gstabs 此选项以stabs格式生成调试信息,但是不包括gdb调试信息。
  • -gstabs+此选项以stabs格式生成调试信息,并且包含仅供gdb使用的额外调试信息。
  • -ggdb 此选项将尽可能的生成gdb可以使用的调试信息。
  • -static 此选项将禁止使用动态库。
  • -share 此选项将尽量使用动态库。
  • -traditional 试图让编译器支持传统的C语言特性
  • -w 不生成任何警告信息。默认选项
  • -Wall 生成所有警告信息。

objdump

简单来说objdump工具就是用来展示目标文件各种信息的。其manpage的描述为:
display information from object files

常用参数

  • -a: 如果目标文件是归档文件(archive, .a),展示归档头部信息(archive header infomation),类似ls -l
    • 可以使用ar tvobjdump -a展示每个成员的文件格式
  • -g: 显示调试信息
  • -d, --disassemble: 用于反汇编。Display the assembler mnemonics for the machine instructions from the input file.
    • This option only disassembles those sections which are expected to contain instructions.
  • -D, --disassemble-all: Like -d, but disassemble the contents of all sections, not just those expected to contain instructions.
  • -f: Display summary information from the overall header of each of the objfile files.
  • -H: 简短的帮助信息
  • -s: 显示指定section的完整内容。默认所有的非空section都会被显示

仅供参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
--archive-headers
-a
显示档案库的成员信息,类似ls -l将lib*.a的信息列出。

-b bfdname
--target=bfdname
指定目标码格式。这不是必须的,objdump能自动识别许多格式,比如:

objdump -b oasys -m vax -h fu.o
显示fu.o的头部摘要信息,明确指出该文件是Vax系统下用Oasys编译器生成的目标文件。
objdump -i将给出这里可以指定的目标码格式列表。

-C
--demangle
将底层的符号名解码成用户级名字,除了去掉所开头的下划线之外,
还使得C++函数名以可理解的方式显示出来。

--debugging
-g
显示调试信息。企图解析保存在文件中的调试信息并以C语言的语法显示出来。
仅仅支持某些类型的调试信息。有些其他的格式被readelf -w支持。

-e
--debugging-tags
类似-g选项,但是生成的信息是和ctags工具相兼容的格式。

--disassemble
-d
从objfile中反汇编那些特定指令机器码的section。

-D
--disassemble-all
与 -d 类似,但反汇编所有section.

--prefix-addresses
反汇编的时候,显示每一行的完整地址。
这是一种比较老的反汇编格式。

-EB
-EL
--endian={big|little}
指定目标文件的小端。这个项将影响反汇编出来的指令。
在反汇编的文件没描述小端信息的时候用。例如S-records.

-f
--file-headers
显示objfile中每个文件的整体头部摘要信息。

-h
--section-headers
--headers
显示目标文件各个section的头部摘要信息。

-H
--help
简短的帮助信息。

-i
--info
显示对于 -b 或者 -m 选项可用的架构和目标格式列表。

-j name
--section=name
仅仅显示指定名称为name的section的信息

-l
--line-numbers
用文件名和行号标注相应的目标代码,
仅仅和-d、-D或者-r一起使用使用-ld和使用-d的区别不是很大,
在源码级调试的时候有用,要求编译时使用了-g之类的调试编译选项。

-m machine
--architecture=machine
指定反汇编目标文件时使用的架构,
当待反汇编文件本身没描述架构信息的时候(比如S-records),这个选项很有用。
可以用-i选项列出这里能够指定的架构.

--reloc
-r
显示文件的重定位入口。
如果和-d或者-D一起使用,重定位部分以反汇编后的格式显示出来。

--dynamic-reloc
-R
显示文件的动态重定位入口,仅仅对于动态目标文件意义,比如某些共享库。

-s
--full-contents
显示指定section的完整内容。默认所有的非空section都会被显示。

-S
--source
尽可能反汇编出源代码,
尤其当编译的时候指定了-g这种调试参数时,效果比较明显。
隐含了-d参数。

--show-raw-insn
反汇编的时候,显示每条汇编指令对应的机器码,
如不指定--prefix-addresses,这将是缺省选项。

--no-show-raw-insn
反汇编时,不显示汇编指令的机器码,
如不指定--prefix-addresses,这将是缺省选项。

--start-address=address
从指定地址开始显示数据,该选项影响-d、-r和-s选项的输出。

--stop-address=address
显示数据直到指定地址为止,该项影响-d、-r和-s选项的输出。

-t
--syms
显示文件的符号表入口。类似于nm -s提供的信息

-T
--dynamic-syms
显示文件的动态符号表入口,仅仅对动态目标文件意义,比如某些共享库。
它显示的信息类似于 nm -D|--dynamic 显示的信息。

-V
--version
版本信息

--all-headers
-x
显示所可用的头信息,包括符号表、重定位入口。
-x 等价于-a -f -h -r -t 同时指定。

-z
--disassemble-zeroes
一般反汇编输出将省略大块的零,该选项使得这些零块也被反汇编。

@file 可以将选项集中到一个文件中,然后使用这个@file选项载入。

strace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

-c
统计每个系统调用的时间、次数和错误,并在程序退出时报告摘要


-C
类似于 -c,但在进程运行时也打印常规输出


-D
将跟踪进程作为分离的孙进程运行,而不是作为跟踪对象的父进程运行。
这通过保持跟踪对象是调用进程的直接子进程来减少 strace 的可见效果


-d
输出 strace 关于标准错误的调试信息


-f
跟踪由 fork(2), vfork(2) and clone(2) 调用所产生的子进程


-ff
如果提供 -o FILENAME,则所有进程的跟踪结果输出到相应的 FILENAME.pid 中,
pid 是各进程的进程号


-F
该选项已废弃,作用等同于 -f


-h
输出简要的帮助信息


-i
在系统调用时打印指令指针


-q
禁止附加、分离等信息。
当输出被重定向到文件并直接运行命令而不是附加命令时,这将自动发生


-qq
如果给定两次,则禁止关于进程退出状态的消息


-r
在每次系统调用进入时打印相对时间戳。它记录连续系统调用开始之间的时间差


-t
在输出中的每一行前加上时间信息


-tt
如果给定两次,在输出中的每一行前加上微秒级的时间信息


-ttt
如果给定三次,则打印的时间将包括微秒,并且开始部分将打印自纪元以来的秒数


-T
显示每一系统调用所耗的时间


-v
输出所有的系统调用。
一些调用关于环境变量,状态,输入输出等调用,由于使用频繁默认不输出


-V
输出 strace 的版本信息.


-x
以十六进制形式输出非标准字符串


-xx
所有字符串以十六进制形式输出


-y
与文件描述符参数关联的打印路径


-a COLUMN
设置返回值的输出位置,默认为40


-b SYSCALL
如果达到指定的系统调用,与跟踪进程分离。目前,只支持 execve。
如果希望跟踪多线程进程,因此需要 -f,但不希望跟踪其(可能非常复杂的)子进程,则此选项非常有用


-e EXPR
指定一个表达式,用来控制如何跟踪。格式如下:
[qualifier=][!]value1[,value2]...
qualifier 只能是 trace, abbrev, verbose, raw, signal, read, write 其中之一。
value 是用来限定的符号或数字。默认的 qualifier 是 trace,感叹号是否定符号。
例如:-e open 等价于 -e trace=open,表示只跟踪 open 调用。
而 -etrace=!open 表示跟踪除了 ope 以外的所有其他调用。有两个特殊的符号 all 和 none,
分别表示跟踪所有和不跟踪任何系统调用。
注意有些 Shell 使用 ! 来执行历史记录里的命令,所以要使用反斜杠对 ! 进行转义


-e trace=SET
只跟踪指定的系统调用。
例如: -e trace=open,close,rean,write 表示只跟踪这四个系统调用,默认的为 trace=all


-e trace=file
只跟踪有关文件操作的系统调用


-e trace=process
只跟踪有关进程控制的系统调用


-e trace=network
跟踪与网络有关的所有系统调用


-e strace=signal
跟踪所有与系统信号有关的系统调用


-e trace=ipc
跟踪所有与进程通讯有关的系统调用


-e trace=desc
跟踪所有与文件描述符相关的系统调用


-e trace=memory
跟踪所有与内存映射相关的系统调用


-e abbrev=SET
缩写打印大型结构的每个成员的输出。
默认值是 abbrev=all。-v 选项的效果是 abbrev=none


-e verbose=SET
为指定的系统调用集取消引用结构。默认是 verbose=all


-e raw=SET
将指定的系统调用的参数以十六进制显示


-e signal=SET
指定跟踪的系统信号,默认为 signal=all。
如 signal=!SIGIO(或 signal=!io),表示不跟踪 SIGIO 信号


-e read=SET
输出从指定文件描述符中读出的数据。例如:-e read=3,5


-e write=SET
输出写入到指定文件中的数据


-o FILENAME
将 strace 的输出写入指定文件


-O OVERHEAD
将跟踪系统调用的开销设置为指定的微秒


-p PID
跟踪指定的进程


-P PATH
只跟踪系统调用的访问路径。多个 -P 选项可用于指定多个路径


-s STRSIZE
指定输出的字符串的最大长度,默认为 32。
注意,文件名不被认为是字符串,总是全部打印


-S SORTBY
根据指定的条件对 -c 选项打印的直方图的输出进行排序。
SORTBY 合法值是 time、calls、name 和 nothing,默认值是 time


-u USERNAME
以指定用户的 UID、GID 和补充组执行被跟踪的命令


-E VAR=VAL
为命令设置环境变量


-E VAR
从继承的环境变量列表中删除变量 VAR,然后将其传递给命令