dds(iceoryx、fastdds等)中間件采用了共享內存,如果app內存越界將共享內存踩踏壞了,將會形成災難。本插件可以檢測到app是否在寫共享內存,如果是,我們可以讓app assert。從而提高dds的穩定性
插件效果:
插件源碼:
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Pass.h"
#include "llvm/IR/Constants.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/IntrinsicInst.h"
using namespace llvm;
namespace {
struct InsertStubPass : public FunctionPass {
static char ID;
const char *LOG_FUNCTION_STR = "log_function_call"; // 日志打印函數調用
InsertStubPass() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
errs().write_escaped(F.getName()) << "-----------\n";
if(F.getName() != "init_ring_buffer")
return true;
// 字符串類型
Type *StringType = Type::getInt8PtrTy(F.getParent()->getContext());
// void type
Type *voidTy = Type::getVoidTy(F.getParent()->getContext());
bool isVarArg = false;
std::vector<Type*> functionCallParams;
functionCallParams.push_back(StringType);
FunctionType *functionCallType = FunctionType::get(
voidTy, functionCallParams, isVarArg
);
F.getParent()->getOrInsertFunction(LOG_FUNCTION_STR, functionCallType);
Function *logFunction = F.getParent()->getFunction(LOG_FUNCTION_STR);
for (BasicBlock &BB : F) {
for (Instruction &I : BB) {
errs() << I << "+++\n";
// 檢查是否為mov指令
if ( auto *MOV = dyn_cast<StoreInst>(&I) ) {
errs().write_escaped("store ins") << "-----------\n";
// 在mov指令前插入一個空的call指令作為插樁
IRBuilder<> builder(MOV);
// ReturnInst i;
Value *PointerOperand = MOV->getPointerOperand();
errs() << "Store address: " << *PointerOperand << "\n";
Value *AddrOp = builder.CreatePointerCast(PointerOperand, builder.getInt8PtrTy());
// 該函數的指針變量
// Value *strPointer = builder.CreateGlobalStringPtr(f.getName());
// 自己定義的 日志函數
std::vector<Value *> args;
args.push_back(AddrOp); // 生成日志函數 的參數列表
// 創建自己的日志函數 并傳入 本函數的函數指針
CallInst::Create(logFunction, args, "", MOV);
// 可以在這里添加插樁的相關信息,例如標記插樁的名稱或其他屬性
// StubCall->setName("stub_instruction");
// 如果需要追蹤插樁的執行情況,可以在這里添加分析或者斷言
// e.g., llvm::Assume(Builder.CreateICmpEQ(StubCall, StubCall));
}
}
}
return true;
}
};
}
char InsertStubPass::ID = 0;
static RegisterPass<InsertStubPass> X("insert-stub", "Insert a stub instruction before mov instructions", false, false);