如何为LLVM .bc文件使用UBSAN进行插桩?
为LLVM IR文件添加UBSAN插桩(LLVM 12.0.1)
针对你的场景,LLVM 12.0.1中没有直接对应Attribute::SanitizeUndefined的枚举值,因为UBSAN采用细粒度的检查属性控制。你可以通过添加模块级UBSAN标志或函数级具体检查属性的方式,让clang触发UBSAN插桩,以下是两种可行方案:
方案一:编写LLVM Pass添加UBSAN属性
1. 编写Pass代码(pass2.cpp)
这个Pass会给模块添加全局UBSAN启用标志,同时给每个函数添加默认UBSAN检查对应的属性:
#include "llvm/IR/Module.h" #include "llvm/Pass.h" using namespace llvm; namespace { struct UBSANInstrumentPass : public ModulePass { static char ID; UBSANInstrumentPass() : ModulePass(ID) {} bool runOnModule(Module &M) override { // 添加模块级标志,启用默认UBSAN检查集合 M.addModuleFlag(Module::Override, "SanitizeUndefined", 1); // 给每个函数添加具体UBSAN检查属性(对应-fsanitize=undefined的默认项) for (Function &F : M) { F.addFnAttr(Attribute::SanitizeShift); F.addFnAttr(Attribute::SanitizeIntegerDivideByZero); F.addFnAttr(Attribute::SanitizeUnreachable); F.addFnAttr(Attribute::SanitizeVLA); F.addFnAttr(Attribute::SanitizeNull); F.addFnAttr(Attribute::SanitizeReturn); F.addFnAttr(Attribute::SanitizeBounds); F.addFnAttr(Attribute::SanitizeAlignment); // 若需要额外检查(如浮点转换溢出),可添加对应属性: // F.addFnAttr(Attribute::SanitizeFloatCastOverflow); } return true; } }; } char UBSANInstrumentPass::ID = 0; static RegisterPass<UBSANInstrumentPass> X("ubsan-add-attrs", "Add UBSAN attributes for instrumentation", false, false);
2. 编译Pass为动态库
clang -fPIC -shared -o pass2.so pass2.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core passes` -O2
3. 处理原IR文件并生成UBSAN插桩后的文件
# 用Pass给put.bc添加UBSAN属性,生成临时文件 clang -Xclang -load -Xclang pass2.so -emit-llvm -o put-tem-ubsan.bc -c put.bc # 用clang触发UBSAN插桩,生成最终的put-ubsan.bc clang -fsanitize=undefined -emit-llvm -o put-ubsan.bc -c put-tem-ubsan.bc
方案二:直接用opt添加模块级标志(无需编写Pass)
如果不需要细粒度控制函数级属性,可以直接用opt给模块添加UBSAN启用标志,步骤更简洁:
# 添加模块级UBSAN标志到put.bc,生成临时文件 opt -module-flag "SanitizeUndefined=1" put.bc -o put-tem-ubsan.bc # 触发UBSAN插桩 clang -fsanitize=undefined -emit-llvm -o put-ubsan.bc -c put-tem-ubsan.bc
验证:生成的put-ubsan.bc中会包含ubsan_handle_开头的符号,说明UBSAN插桩成功。
内容的提问来源于stack exchange,提问作者user22906126
相关产品推荐
相关产品推荐

