可执行文件符号表导出与使用

工作中用到了, 就稍微写下.

可执行文件处理

编译时加入 debug 信息选项

1
2
3
4
5
6
7
CFLAG += -Og -g3

# -Og 该标识会精心挑选部分与 -g 选项不冲突的优化选项, 当然就能提供合理的优化水平, 同时产生较好的可调试信息和对语言标准的遵循程度.
# -g0 不产生 debug 信息
# -g1 产生极少数 debug 信息
# -g, -g2 默认的 debug 级别, 产生正常数量的 debug 信息
# -g3 会生成额外的 debug 信息, 比如说提供宏展开功能

导出符号表

1
objcopy --only-keep-debug <exec_file> <debug_path>/<symbol_file>

生成的 symbol 文件是只包含 debug 信息的符号表文件。

清理可执行文件中的符号表

1
2
3
4
objcopy --strip-all <exec_file>

# 也可以使用 strip 进行清理
strip --strip-debug --strip-unneeded <exec_file>

可以使用 objdump 检查是否真正去除,如果显示无符号表信息则为正常。

1
2
3
4
5
objdump -t <exec_file>

# objdump - display information from object files.
# -t | --syms 打印该文件的符号表信息, 类似 nm 程序
# -T | --dynamic-syms 打印该文件的动态连接符号表信息, 类似 nm -D

添加符号表导入地址

1
objcopy --add-gnu-debuglink=<debug_path>/<symbol_file> <exec_file>

这一步的目的是给清理之后的可执行文件添加 .gnu_debuglink 的段地址,这个段地址指向 <debug_path>/<symbol_file> 符号表文件,用于加载符号表信息。

使用

把导出的符号表文件放入 <debug_path>/<symbol_file> 路径下,再使用 gdb 进行 debug 即可。<debug_path> 可以是相对路径也可以是绝对路径。

1
2
3
# 把符号表放到对应路径下
mkdir -p <debug_path>
cp <symbol_file> <debug_path>/<symbol_file>
  • 对运行时的无符号表可执行程序 debug
1
2
3
4
5
# 获取 program 的进程号
ps -ef | grep <program>

# pid 是 program 的进程号
gdb -p <pid>
  • 对无符号表可执行程序生成的 coredump 文件 debug
1
gdb -c <coredump_file> -e <exec_file>

参考

1
2
3
4
5
6
7
objcopy - copy and translate object files.

--only-keep-debug
Strip a file, removing contents of any sections that would not be stripped by --strip-debug and leaving the debugging sections intact. In ELF files, this preserves all note sections in the output.

--add-gnu-debuglink
创建 .gun_debuglink 字段并包含到符号文件的引用添加到目标文件中

objcopy manual

objdump manual

gcc 优化参数文档

gcc Debug 参数文档

GCC中-O1 -O2 -O3 优化的原理是什么?