GCC 的一些实用的方法。
到底使用了哪个头文件?
一个 SDK 中可能存在多个同名的 .h 文件,如何确定 .c 中到底使用的是哪个 .h 呢?
GCC 有一个选项 -M 可以输出 .c 所包含的所有 .h,使用此方法能确定 .c 使用的 .h 文件。
开发 5062 时遇到了编译错误:error: 'errno' undeclared
,可能是 .c 使用了一个错误的非系统的 errno.h,于是到 build 目录下去查找对应的 .d 文件,发现果然用的是一个原厂自己写的 errno.h,其中没有声明 errno。
屏蔽编译 warning 输出
有时候 warning 太多,淹没了 error,可以用 -w 选项屏蔽 warning 输出。
使用 strip 精简静态库的大小
arm-none-eabi-strip -o lib.strip.a lib.a --strip-debug
静态库只能使用--strip-debug
选项,去除库中的 debug 信息,可以把一个 16M 的静态库精简到 280K。
注意:使用ar -M < script
方式将多个 .a 打包成的静态库不能使用 strip 命令。
在 map 表内查找静态变量和函数地址
静态变量和函数其实在 map 表内也能查到的,首先要使能 GCC 的编译选项-fdata-sections -ffunction-sections
,为变量和函数生成一个专有的段名称。
以静态变量来举例说明:
ota.c
1 | static uint8_t flash_data_buf; |
main.c
1 | void hal_init(void) |
对于在函数外的静态变量,在 map 表中形式如下:
1 | .bss.flash_data_buf |
对于函数内的静态变量,在 map 表中形式如下:
1 | .bss.flash_data_buf.5993 |
这种情况就要结合反汇编来确定了。
__builtin_return_address() 获取调用者的地址
void * __builtin_return_address (unsigned int level)
是 GCC 的一个内建函数,__builtin_return_address(0)
的含义是,得到当前函数返回地址,即此函数被别的函数调用,然后此函数执行完毕返回后的下一条地址。
1 | printf("%s(0) = %p\r\n", __FUNCTION__, __builtin_return_address(0)); |
反汇编如下:
1 | ... |
所以这个函数其实就是返回 LR 的值。
AR
http://sourceware.org/binutils/docs-2.31/binutils/ar-cmdline.html#ar-cmdline
ar -rcs archive objects
将 objects 文件打包成库
c
- create,创建新库
r
- replace,替换已有库中的目标文件
s
- 更新库中的索引
d
- delete,删除库中的目标文件
x
- extract,解压出库中的目标文件
t
- 列出库中所有的目标文件