2021-10-15 Linux MAKEFILE 编译C++ 带符号 并调试

这篇博客介绍了如何使用MakeFile进行C++程序的编译和调试。主要步骤包括:使用gcc命令生成目标文件dhcp.o,然后链接库stdc++生成可执行文件dhcp,同时添加调试符号。此外,还提供了清理目标文件的指令。

MakeFile文件:

dhcp : dhcp.o
    gcc     -o     dhcp dhcp.o -lstdc++  #lstdc++  指使用 libstdc++ 链接
dhcp.o : dhcp.cpp dhcp.h
    gcc      -c -g dhcp.cpp        # -g 加入调试符号
clean :
    rm  dhcp.o

编译调试 :

<think>好的,用户的问题是关于如何在编译时生成调试信息从中提取符号表。我需要结合用户提供的引用和之前的对话内容来回答。 首先,用户提到的引用[1]指出,使用clang的-s选项可以关闭符号表生成,但调试时会困难。所以用户可能想知道如何开启调试信息,应该使用相反的选项,比如-g。引用[2]提到Android Studio用CMake编译so包保留符号信息和调试信息,这说明不同编译工具有不同的配置方法。引用[3]提到使用strip去除调试信息,这也反向说明在发布时需要移除这些信息,而编译时需要保留。引用[4]讨论了符号表的存放路径,这对提取步骤可能有帮助。引用[5]展示了Qt项目的配置,可能涉及QMAKE_CXXFLAGS的设置,但用户的问题更通用,可能需要涵盖不同编译工具。 用户之前的问题是关于提取符号表的方法和工具,之前的回答已经涵盖了静态分析工具、动态恢复工具、调试信息解析等方法。现在用户想了解的是在编译阶段如何生成调试信息,然后提取其中的符号表。需要分步骤说明,包括不同编译器(GCC、Clang、MSVC)、构建工具(CMake、Makefile、Qt)的配置,以及提取符号表的具体命令(如objcopy、dwarfdump等)。 要注意用户可能需要跨平台的解决方案,所以需要涵盖Linux/macOS和Windows的工具。同时,用户可能对调试信息与符号表的关系不太清楚,需要简要说明两者的区别和联系。例如,调试信息通常包含符号表,但更详细,如变量、行号信息。 另外,用户可能关心实际应用场景,比如在发布版本前如何处理调试信息,如何确保符号表被正确保存以供后续调试使用。可能需要提到符号文件(如Windows的PDB,Linux的.dSYM或.debug文件)的生成和管理,以及如何配置构建系统来保留这些信息。 最后,要确保回答结构清晰,分步骤讲解,提供示例命令,让用户能直接应用。同时,相关问题部分需要引导用户深入了解,比如如何验证符号表、处理剥离后的影响等,与之前的问题相呼应。</think>### 如何生成调试信息提取符号表 --- #### **一、编译时生成调试信息** 调试信息包含符号地址、变量名称、源码行号等元数据,是调试和分析程序的关键。以下是主流编译器的配置方法: 1. **GCC/Clang编译器** 使用 `-g` 选项生成调试信息(默认生成DWARF格式)[^1]: ```bash gcc -g -o my_program my_program.c # 保留完整调试信息 clang -g -O0 my_program.c -o my_program # -O0禁用优化,确保调试信息完整 ``` **关键参数对比**: | 参数组合 | 作用 | |-------------------|--------------------------------| | `-g -O0` | 完整调试信息,无优化 | | `-g -O2` | 优化代码,可能丢失部分调试信息 | | `-g3` | 包含宏定义信息(GCC扩展) | 2. **CMake项目配置** 在 `CMakeLists.txt` 中显式启用调试符号[^2]: ```cmake set(CMAKE_BUILD_TYPE Debug) # 自动添加 -g # 或强制添加调试标志 add_compile_options(-g) ``` 3. **Qt项目(QMake)** 在 `.pro` 文件中配置调试信息保留[^5]: ```qmake CONFIG(release) { QMAKE_CXXFLAGS += /Zi /DEBUG # Windows MSVC QMAKE_LFLAGS += /DEBUG } ``` 4. **Android NDK(动态库)** 在 `build.gradle` 中配置保留符号表: ```groovy android { ndk { // 强制保留调试符号 debuggable true cFlags "-g" } } ``` --- #### **二、调试信息与符号表的提取方法** 调试信息通常存储在可执行文件或独立的调试文件中,提取方式如下: 1. **分离调试信息文件(Linux/macOS)** 使用 `objcopy` 将调试信息剥离为独立文件[^4]: ```bash objcopy --only-keep-debug my_program my_program.debug # 生成独立调试文件 strip --strip-debug my_program # 从主程序移除调试信息 ``` **符号表存放路径**: - `/usr/lib/debug/`(系统默认路径) - `/home/TestDemon/.debug/`(进程执行路径下的.debug目录)[^4] 2. **解析DWARF调试信息** 使用 `dwarfdump` 工具提取符号表: ```bash dwarfdump --debug-info my_program > symbols.txt # 导出符号地址与源码映射 dwarfdump --debug-line my_program > line_info.txt # 提取行号信息 ``` 3. **Windows平台(PDB文件)** - MSVC编译器默认生成 `.pdb` 文件(符号数据库) - 使用 `dumpbin` 工具查看符号: ```powershell dumpbin /SYMBOLS my_program.exe ``` 4. **动态库符号提取** 使用 `nm` 工具提取导出符号: ```bash nm -D --defined-only libmylib.so # 显示动态库导出的全局符号 ``` --- #### **三、调试信息与符号表的关系** | **特性** | **调试信息** | **符号表** | |-----------------|---------------------------------|----------------------------| | **内容** | 符号地址、变量类型、源码行号等 | 符号名称与地址的映射 | | **格式** | DWARF(Linux)、PDB(Windows) | ELF符号段、Mach-O符号表 | | **用途** | 支持单步调试、变量监视 | 崩溃分析、堆栈解析 | | **文件大小** | 较大(可能占程序体积50%+) | 较小(仅基础映射) | | **生产环境** | 通常剥离以减小体积[^3] | 部分保留(如崩溃报告场景) | --- #### **四、验证与调试** 1. **检查调试信息完整性** ```bash file my_program # 查看是否包含"with debug_info" readelf -S my_program | grep debug # ELF文件检查调试段 ``` 2. **GDB调试验证** ```bash gdb my_program (gdb) break main # 测试能否设置源码级断点 (gdb) run ``` --- #### **五、实际应用示例** **场景:为C++项目生成调试符号提取** 1. 编译时保留调试信息: ```bash g++ -g -O0 -std=c++11 main.cpp -o app ``` 2. 提取符号表: ```bash objdump -t app > app.symbols # 导出完整符号表 objcopy --only-keep-debug app app.debug # 生成独立调试文件 ``` --- ### 相关问题 1. 如何在不同编译器中控制调试信息的详细程度? 2. 调试信息剥离后如何关联崩溃报告的地址与源码? 3. Windows PDB文件与Linux DWARF格式有何本质区别?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值