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是已定义的宏,则该条件宏被展开为b ifdef(``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
2
3
4
AC_INIT(Auditor, 1.0)
AC_PROG_CC # 检测C编译器
AC_CONFIG_FILES([Makefile], [chmod +x Makefile]) # 模板文件
AC_OUTPUT

Automake

  Automake是从Makefile.am(定义一系列make变量的文件)自动生成Makefile.in文件的工具。生成的Makefile.in符合GNU Makefile 标准。

Libtool

  Libtool同样为解决软件可移植性问题而设计,不过它关注的是动态链接库。使用 GNU Libtool 可以容易的在不同的系统中建立动态链接库。

Autotest

Gdb

  • 开始和停止

    quit : 退出GDB
    run [命令行参数]: 运行程序(并给出命令行参数)
    kill:停止程序

  • 断点

    break sum:在函数sum入口处设置断点
    break *0x80483625:在地址0x80483625处设置断点
    delete 1:删除断点1
    delete:删除所有断点
    commands <断点号>:在到达断点时执行命令

  • 执行

    stepi:执行1条指令
    stepi 4:执行4条指令
    nexti:执行下一条指令
    continue : 继续执行
    finish:运行直到当前函数返回

  • 检查代码

    disas:反汇编当前函数
    disas sum:反汇编sum函数
    disas 0x8048397:反汇编0x8048397附近的函数
    disas 0xA 0xB:反汇编指定地址范围内的代码
    print /x $eip:以16进制打印寄存器的值

  • 检查数据

    print $eip
    print /t $eip
    print 0x100
    print /x 555
    print /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开发工具链