如何在LLVM Pass中遍历IR文件调试符号并解析DICompositeType元数据
LLVM Pass 遍历调试元数据(含DICompositeType)实现方案
实现思路
所有调试元数据都挂载在Module的llvm.dbg.cu命名元数据下,所有编译单元(DICompileUnit)都会在此处注册,你可以从编译单元出发遍历所有类型元数据,也可以全局遍历Module的所有元数据节点过滤得到目标DICompositeType。
必要头文件
#include "llvm/IR/Module.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/BinaryFormat/Dwarf.h"
具体实现步骤
- 第一步:遍历编译单元获取结构体调试元数据
从当前Module获取llvm.dbg.cu命名元数据,遍历每一个节点转为DICompileUnit后,过滤得到目标结构体类型的DICompositeType:bool runOnModule(Module &M) override { NamedMDNode *DbgCUNodes = M.getNamedMetadata("llvm.dbg.cu"); if (!DbgCUNodes) { return false; // 无调试信息直接返回 } for (MDNode *Node : DbgCUNodes->operands()) { DICompileUnit *CU = cast<DICompileUnit>(Node); // 遍历编译单元下所有保留类型 for (DIType *Ty : CU->getRetainedTypes()) { // 尝试转为DICompositeType if (auto *CompositeTy = dyn_cast<DICompositeType>(Ty)) { // 过滤结构体类型 if (CompositeTy->getTag() == dwarf::DW_TAG_structure_type) { // 这里就拿到了你要的结构体调试元数据 errs() << "找到结构体类型: " << CompositeTy->getName().str() << "\n"; errs() << "定义行号: " << CompositeTy->getLine() << "\n"; errs() << "大小: " << CompositeTy->getSizeInBits() << "bit\n"; // 遍历结构体成员 for (DINode *Elem : CompositeTy->getElements()) { if (auto *MemberTy = dyn_cast<DIDerivedType>(Elem)) { errs() << " 成员: " << MemberTy->getName().str() << "\n"; } } } } } } return false; } - 第二步:DICompositeType与IR StructType关联
如果你需要对应到getIdentifiedStructTypes()返回的IR结构体类型,可以调用getTypeForDIType接口做映射:StructType *IRStructTy = cast<StructType>(CompositeTy->getTypeForDIType(CompositeTy, M.getContext())); // 之后就可以和你从getIdentifiedStructTypes拿到的结构体指针做匹配 - 全局遍历补充方案
如果有部分复合类型没有在编译单元的保留类型中注册,可以直接遍历Module的所有元数据节点过滤,该方式覆盖所有场景但性能略低于从编译单元遍历。
DebugInfoFinder扩展说明
你之前使用的llvm::DebugInfoFinder没有直接返回DICompositeType的接口,但可以继承它扩展功能,它内部已经遍历了所有类型元数据,只需新增接口返回存储DICompositeType的容器即可。
内容的提问来源于stack exchange,提问作者Sigterm
相关产品推荐
相关产品推荐

