GNU编译调试工具链手册
概述
GNU软件开发环境(GDE)提供了全功能的、协作式的开发环境。它包含众多了强大的开发工具,这些工具或者(标准)提供了开发高质量产品软件的高效的环境。另外,GDE的工具都可以免费获得下载,而且很多软件还关联着活跃的开源社区。GDE不等同于集成开发环境(IDE),它在工具的选择上有更多灵活性。
GCC
Make
Lex和Yacc
M4
M4是通用Unix宏处理器,它接受输入流,并将输入流中的宏进行扩展后拷贝到输出。宏可以是内置的也可以是用户自定义的。M4作为微型语言,不仅仅可以完成宏扩展功能,它还可以通过内置函数完成命名文件、执行Unix命令、算术运算、操作文本字符和递归。M4不但可以作为宏处理器,也可以作为编译器的前端。某种程度上说,m4是完备图灵机。M4最大的使用场景是在GNU Autoconf工具中。
C语言提供了对于宏的支持,但一般认为要慎用宏。使用宏最然可以避免相比使用函数调用带来的开销,但却容易使程序变得看起来复杂,违背清晰和透明的原则。
详细手册可以参看info m4或浏览在线资源 M4 手册。
Beware that m4 may be dangerous for the health of compulsive programmers.
基本格式:
define(宏名,宏体)(宏本身也会被m4展开,不过展开为空字符)。宏也可以带参数,使用$1,%2,…,$9表示。m4 的宏名名规则是:只允许使用字母、数字以及下划线构造宏名,并且宏名只能以字母或下划线开头。只有符合宏名规则的宏,m4 才会将它视为真正的宏。m4 将一切没有引号的文本都视为宏。对于已定义的宏,m4 会将其展开;对于未定义的宏,m4 会按其字面将其输出。加了引号的文本,m4 不再检测它们是不是宏,而是将其作为普通文本按字面输出。需要注意的是,define本身就是宏,后面括号内是它的参数,从这点来说,它和用它定义的用户宏没有区别。条件宏:
ifdef(``a',b),如果a是已定义的宏,则该条件宏被展开为bifdef(``a’,b,c),如果a是已定义的宏,则该条件宏被展开为b;如果未定义,则展开为c。ifelse(a,b,c,d)比较字符串 a 与 b 是否相同,如果它们相同,这条语句的展开结果是字符串 c,否则展开为字符串 d。递归:
执行shell命令:
esyscmd
参看中文博客 M4简介 。牢记:宏是用来缩写那些复杂但是又经常重复出现的文本模式的。
Autoconf
Autoconf工具致力于保证程序的可移植性,使得不需要为不同的系统开发不同的源程序,特别是当系统之间的差异比想象中的大的情况下。首先,源程序会按照一个理想的机器模型(POSIX)编程;然后,当源程序拷贝到用户系统时,autoconf会尽力假装用户系统时满足POSIX的标准的。Autoconf会帮助源程序的维护者学习用户的系统,诊断该系统不满足POSIX标准的地方,然后提供变通的方法。审核程序可以直接使用shell来编写,但shell本身的兼容性使得编写脚本非常复杂,就像编写汇编语言。Autoconf则使得不需要专门写shell脚本来对系统进行审核。
Autoconf可以基本上认为是一个M4的宏库,但m4代码太过底层,且Autoconf要生成shell脚本,因此Autoconf是工作在m4变体m4sh之上的高层代码。
任何Autoconf脚本必须以AC_INIT开头,例如:
1 | AC_INIT(Auditor, 1.0) |
Automake
Automake是从Makefile.am(定义一系列make变量的文件)自动生成Makefile.in文件的工具。生成的Makefile.in符合GNU Makefile 标准。
Libtool
Libtool同样为解决软件可移植性问题而设计,不过它关注的是动态链接库。使用 GNU Libtool 可以容易的在不同的系统中建立动态链接库。
Autotest
Gdb
开始和停止
quit: 退出GDBrun [命令行参数]: 运行程序(并给出命令行参数)kill:停止程序断点
break sum:在函数sum入口处设置断点break *0x80483625:在地址0x80483625处设置断点delete 1:删除断点1delete:删除所有断点commands <断点号>:在到达断点时执行命令执行
stepi:执行1条指令stepi 4:执行4条指令nexti:执行下一条指令continue: 继续执行finish:运行直到当前函数返回检查代码
disas:反汇编当前函数disas sum:反汇编sum函数disas 0x8048397:反汇编0x8048397附近的函数disas 0xA 0xB:反汇编指定地址范围内的代码print /x $eip:以16进制打印寄存器的值检查数据
print $eipprint /t $eipprint 0x100print /x 555print /x ($ebp+8)print *(int*) 0xfff076b0:输出地址0xfff076b0处的整数print *(int*) ($ebp+8):输出地址($ebp+8)处的整数x/2w 0xfff076b0:检查从0xfff076b0地址处开始的双字x/20b sum:检查函数sum的前20个字节backtrace:打印程序栈list [行号或函数名]:打印当前位置(或指定位置)处周围代码@<number>:打印指定数目的数组元素display <exp>信息
info frame:打印当前栈帧info registers:打印寄存器help:帮助
Profiling and Optimising
- gprof
- valgrind
ARM开发工具链
参考 GNU Arm开发工具链