LLVM无法生成调试行信息:配置后lldb无行号问题求助
解决LLVM生成无效调试行信息的问题
核心问题分析
从你提供的代码和生成的元数据来看,导致LLDB无法识别调试行信息的关键问题如下:
- DILocation的line值为0:调试器会忽略
line:0的调试位置,这不是合法的源码行标识(即便用column存储文件偏移,line字段也需设置为大于0的有效值)。 - 编译单元的directory为空:
!DIFile的directory字段是空字符串,调试器无法定位源文件combined.pp_1的实际路径,无法关联行信息与源码。 - DISubprogram未绑定到LLVM函数IR:仅创建
DISubprogram元数据,但未将其附加到对应的LLVM Function对象上,调试器无法将二进制函数与调试元数据关联。 - DISubprogram构造参数不完整:函数定义的行号参数设为0,缺少有效源码行标识。
具体修复步骤
1. 修正DILocation的line字段
不要将line设为0,替换为实际的源码行号;若前端仅能获取文件偏移,至少设为1以保证调试器识别:
// 将0替换为实际源码行号,或至少设为1 llvmbuilder->SetCurrentDebugLocation(llvm::DILocation::get(*llvmctx, 1, mypos, llvmsub));
2. 补全编译单元的directory路径
创建DIFile时传入源文件的实际目录,而非空字符串:
// 将""替换为源文件所在的真实目录,例如"/home/user/src" auto sourceFile = llvmdibuilder->createFile(std::string{modulename}, "/home/user/src"); llvmcu = llvmdibuilder->createCompileUnit(llvm::dwarf::DW_LANG_C, sourceFile, "regularc", false, "", 0);
3. 将DISubprogram绑定到LLVM函数
创建llvmsub后,必须将其附加到对应的LLVM Function对象上:
// 假设currfunc对应的LLVM函数对象为llvmFunc llvm::Function* llvmFunc = ...; // 你的前端生成的LLVM函数实例 llvmFunc->setSubprogram(llvmsub);
4. 优化DISubprogram的构造参数
调整DISubprogram::getDistinct的参数,补充函数定义的行号并完善标识:
llvmsub = llvm::DISubprogram::getDistinct( *llvmctx, llvmcu->getFile(), currfunc->identifier, currfunc->linkage, llvmcu->getFile(), 15, // 替换为函数定义所在的实际源码行号 nullptr, 0, nullptr, 0, 0, llvm::DINode::DIFlags::FlagPrototyped, // 若为带原型的C函数,添加该标识 llvm::DISubprogram::toSPFlags(false, true, false), llvmcu );
5. 确保编译流程保留调试信息
使用llc编译时需添加-g参数以保留调试元数据,再用clang链接:
llc -g your_module.ll -o your_module.s clang -g your_module.s -o a.out
验证修复后的元数据
修复后生成的元数据应类似如下格式,其中line字段为有效值,directory路径完整:
0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "regularc", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) !1 = !DIFile(filename: "combined.pp_1", directory: "/home/user/src") !2 = !{i32 2, !"Debug Info Version", i32 3} !3 = distinct !DISubprogram(name: "checkkeyb", scope: !1, file: !1, line: 15, spFlags: DISPFlagDefinition, unit: !0) !4 = !DILocation(line: 20, column: 49179, scope: !3)
此时LLDB就能正确解析调试行信息,调用栈会显示对应的源码行号。
内容的提问来源于stack exchange,提问作者AnArrayOfFunctions
相关产品推荐
相关产品推荐

