From cdd85e25410426cae81eaf6b1655973cc84cab7d Mon Sep 17 00:00:00 2001 From: purplepig4657 Date: Thu, 18 Jan 2024 18:09:34 +0000 Subject: [PATCH 1/4] PreciseLeakSanitizer: Change LLVM Pass skeleton structure --- PreciseLeakSanitizer/PreciseLeakSanitizer.cpp | 86 +++++++++++-------- PreciseLeakSanitizer/PreciseLeakSanitizer.h | 57 ++++++++++++ 2 files changed, 106 insertions(+), 37 deletions(-) create mode 100644 PreciseLeakSanitizer/PreciseLeakSanitizer.h diff --git a/PreciseLeakSanitizer/PreciseLeakSanitizer.cpp b/PreciseLeakSanitizer/PreciseLeakSanitizer.cpp index d6fcb4722..4e6d74906 100644 --- a/PreciseLeakSanitizer/PreciseLeakSanitizer.cpp +++ b/PreciseLeakSanitizer/PreciseLeakSanitizer.cpp @@ -1,63 +1,75 @@ -#include "llvm/Pass.h" +#include "PreciseLeakSanitizer.h" + +#include "llvm/IR/IRBuilder.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; -namespace { +void PreciseLeakSanVisitor::visitStoreInst(StoreInst &I) { return; } + +void PreciseLeakSanVisitor::visitReturnInst(ReturnInst &I) { return; } -struct PreciseLeakSanitizer : public PassInfoMixin { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { - bool transformed = false; - for (auto &F : M) { - for (auto &BB : F) { - for (auto &I : BB) { - if (auto *CI = dyn_cast(&I)) { - IRBuilder builder(CI); +void PreciseLeakSanVisitor::visitCallInst(CallInst &I) { return; } - if (CI->getName() == "malloc") { +void PreciseLeakSanVisitor::visitCallMalloc(CallInst &I) { return; } - } else if (CI->getName() == "calloc") { +void PreciseLeakSanVisitor::visitCallCalloc(CallInst &I) { return; } - } else if (CI->getName() == "realloc") { +void PreciseLeakSanVisitor::visitCallNew(CallInst &I) { return; } - } else if (CI->getName() == "new") { +void PreciseLeakSanVisitor::visitCallArrTyNew(CallInst &I) { return; } - } else if (CI->getName() == "new[]") { +void PreciseLeakSanVisitor::visitCallFree(CallInst &I) { return; } - } else if (CI->getName() == "free") { +void PreciseLeakSanVisitor::visitCallMemset(CallInst &I) { return; } - } else if (CI->getName() == "memset") { +void PreciseLeakSanVisitor::visitCallMemcpy(CallInst &I) { return; } - } else if (CI->getName() == "memcpy") { +void PreciseLeakSanVisitor::visitCallMemmove(CallInst &I) { return; } - } else if (CI->getName() == "memmove") { +void PreciseLeakSanVisitor::visitCallBzero(CallInst &I) { return; } - } else if (CI->getName() == "bzero") { - } - } else if (auto *SI = dyn_cast(&I)) { +bool PreciseLeakSanitizer::initializeModule(Module &M) { return false; } - } else if (auto *RI = dyn_cast(&I)) { - } - } +bool PreciseLeakSanitizer::run(Module &M) { + for (Function &F : M) { + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + PreciseLeakSanVisitor().visit(I); } } - return (transformed ? PreservedAnalyses::none() : PreservedAnalyses::all()); - }; -}; + } + return false; +} -} // namespace +PreservedAnalyses PreciseLeakSanitizerPass::run(Module &M, + ModuleAnalysisManager &) { + return (PreciseLeakSanitizer().run(M) ? PreservedAnalyses::none() + : PreservedAnalyses::all()); +} -extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo -llvmGetPassPluginInfo() { - return {.APIVersion = LLVM_PLUGIN_API_VERSION, - .PluginName = "PreciseLeakSanitizer", - .PluginVersion = "v0.1", - .RegisterPassBuilderCallbacks = [](PassBuilder &PB) { +llvm::PassPluginLibraryInfo getPreciseLeakSanitizerPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "precise-leak-sanitizer", + LLVM_VERSION_STRING, [](PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &MPM, + ArrayRef) { + if (Name == "precise-leak-sanitizer") { + MPM.addPass(PreciseLeakSanitizerPass()); + return true; + } + return false; + }); PB.registerPipelineStartEPCallback( [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(PreciseLeakSanitizer()); + MPM.addPass(PreciseLeakSanitizerPass()); }); }}; } + +extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return getPreciseLeakSanitizerPluginInfo(); +} diff --git a/PreciseLeakSanitizer/PreciseLeakSanitizer.h b/PreciseLeakSanitizer/PreciseLeakSanitizer.h new file mode 100644 index 000000000..59fa9d8f6 --- /dev/null +++ b/PreciseLeakSanitizer/PreciseLeakSanitizer.h @@ -0,0 +1,57 @@ +#ifndef PRECISE_LEAK_SANITIZER_H +#define PRECISE_LEAK_SANITIZER_H + +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +using namespace llvm; + +class PreciseLeakSanitizer { +private: + friend class PreciseLeakSanVisitor; + + Module *Mod; + LLVMContext *Ctx; + + // RT library functions + FunctionType *RefCountFnTy; + FunctionType *AllocSizeAlignFnTy; + FunctionType *InitDynAllocShadowMemFnTy; + FunctionCallee RefCountFn; + FunctionCallee AllocSizeAlignFn; + FunctionCallee InitDynAllocShadowMemFn; + StringRef RefCountFnName = "refCount"; + StringRef AllocSizeAlignFnName = "allocSizeAlign"; + StringRef InitDynAllocShadowMemFnName = "initDynAllocShadowMem"; + + bool initializeModule(Module &M); + +public: + bool run(Module &M); +}; + +class PreciseLeakSanVisitor : public InstVisitor { +public: + void visitStoreInst(StoreInst &I); + void visitReturnInst(ReturnInst &I); + void visitCallInst(CallInst &I); + +private: + void visitCallMalloc(CallInst &I); + void visitCallCalloc(CallInst &I); + void visitCallNew(CallInst &I); + void visitCallArrTyNew(CallInst &I); + void visitCallFree(CallInst &I); + void visitCallMemset(CallInst &I); + void visitCallMemcpy(CallInst &I); + void visitCallMemmove(CallInst &I); + void visitCallBzero(CallInst &I); +}; + +struct PreciseLeakSanitizerPass + : public PassInfoMixin { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &); +}; + +#endif From 311f47b3e705f05465cdbbf7d500a34f68f45929 Mon Sep 17 00:00:00 2001 From: purplepig4657 Date: Fri, 19 Jan 2024 20:19:00 +0000 Subject: [PATCH 2/4] PreciseLeakSanitizer: Setup runtime library structure --- RuntimeLibrary/plsan.cpp | 21 +++++++++++++++++++++ RuntimeLibrary/plsan.h | 26 ++++++++++++++++++++++++++ RuntimeLibrary/plsan_handler.cpp | 11 +++++++++++ RuntimeLibrary/plsan_handler.h | 21 +++++++++++++++++++++ RuntimeLibrary/plsan_shadow.cpp | 20 ++++++++++++++++++++ RuntimeLibrary/plsan_shadow.h | 23 +++++++++++++++++++++++ RuntimeLibrary/plsan_storage.cpp | 11 +++++++++++ RuntimeLibrary/plsan_storage.h | 19 +++++++++++++++++++ 8 files changed, 152 insertions(+) create mode 100644 RuntimeLibrary/plsan.h create mode 100644 RuntimeLibrary/plsan_handler.cpp create mode 100644 RuntimeLibrary/plsan_handler.h create mode 100644 RuntimeLibrary/plsan_shadow.cpp create mode 100644 RuntimeLibrary/plsan_shadow.h create mode 100644 RuntimeLibrary/plsan_storage.cpp create mode 100644 RuntimeLibrary/plsan_storage.h diff --git a/RuntimeLibrary/plsan.cpp b/RuntimeLibrary/plsan.cpp index 2c9d19471..fc16293e8 100644 --- a/RuntimeLibrary/plsan.cpp +++ b/RuntimeLibrary/plsan.cpp @@ -3,10 +3,13 @@ * collisons with the program. For example: __foo(), __bar(), etc. */ +#include "plsan.h" + #include /* Initialization routines called before main() */ __attribute__((constructor)) void __plsan_init() { /* TODO: */ + __plsan::Plsan *plsan; } void __plsan_alloc(void *addr, size_t size) { @@ -24,3 +27,21 @@ void __plsan_exit_func() { * 2) or the address of a buffer is return value */ } + +namespace __plsan { + +Plsan::Plsan() { + shadow = new PlsanShadow(); + storage = new PlsanStorage(); + handler = new PlsanHandler(); +} + +void Plsan::enter_func() { + // enter_func +} + +void Plsan::exit_func() { + // exit_func +} + +} // namespace __plsan diff --git a/RuntimeLibrary/plsan.h b/RuntimeLibrary/plsan.h new file mode 100644 index 000000000..5d0acccbf --- /dev/null +++ b/RuntimeLibrary/plsan.h @@ -0,0 +1,26 @@ +#ifndef PLSAN_H +#define PLSAN_H + +#include "plsan_handler.h" +#include "plsan_shadow.h" +#include "plsan_storage.h" + +namespace __plsan { + +class Plsan { +public: + Plsan(); + // long align_size(long size); + + void enter_func(); + void exit_func(); + +private: + PlsanShadow *shadow; + PlsanStorage *storage; + PlsanHandler *handler; +}; + +} // namespace __plsan + +#endif diff --git a/RuntimeLibrary/plsan_handler.cpp b/RuntimeLibrary/plsan_handler.cpp new file mode 100644 index 000000000..a2f2d022d --- /dev/null +++ b/RuntimeLibrary/plsan_handler.cpp @@ -0,0 +1,11 @@ +#include "plsan_handler.h" + +namespace __plsan { + +void PlsanHandler::exception_check(RefCountAnalysis ref_count_analysis) { + AddrType addrType; + ExceptionType exceptionType; + std::tie(addrType, exceptionType) = ref_count_analysis; +} + +} // namespace __plsan diff --git a/RuntimeLibrary/plsan_handler.h b/RuntimeLibrary/plsan_handler.h new file mode 100644 index 000000000..d015eb3bd --- /dev/null +++ b/RuntimeLibrary/plsan_handler.h @@ -0,0 +1,21 @@ +#ifndef PLSAN_HANDLER_H +#define PLSAN_HANDLER_H + +#include + +namespace __plsan { + +enum AddrType { NonDynAlloc, DynAlloc }; +enum ExceptionType { None, RefCountZero }; +// Something stack trace data structure here. + +using RefCountAnalysis = std::tuple; + +class PlsanHandler { +public: + void exception_check(RefCountAnalysis ref_count_analysis); +}; + +} // namespace __plsan + +#endif diff --git a/RuntimeLibrary/plsan_shadow.cpp b/RuntimeLibrary/plsan_shadow.cpp new file mode 100644 index 000000000..53f440dcc --- /dev/null +++ b/RuntimeLibrary/plsan_shadow.cpp @@ -0,0 +1,20 @@ +#include "plsan_shadow.h" + +#include + +namespace __plsan { + +PlsanShadow::PlsanShadow() { + shadow_addr = mmap(NULL, MMAP_SIZE, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0); + if (shadow_addr == MAP_FAILED) + throw "mmap failed\n"; +} + +void PlsanShadow::alloc_shadow(void *addr, size_t size) {} + +void PlsanShadow::update_reference(void **lhs, void *rhs) {} + +void *PlsanShadow::addr_to_shadow_addr(void *addr) { return 0; } + +} // namespace __plsan diff --git a/RuntimeLibrary/plsan_shadow.h b/RuntimeLibrary/plsan_shadow.h new file mode 100644 index 000000000..1d9f72556 --- /dev/null +++ b/RuntimeLibrary/plsan_shadow.h @@ -0,0 +1,23 @@ +#ifndef PLSAN_SHADOW_H +#define PLSAN_SHADOW_H + +#include + +namespace __plsan { + +#define MMAP_SIZE ((1L << 48) / 16) + +class PlsanShadow { +public: + PlsanShadow(); + void alloc_shadow(void *addr, size_t size); + void update_reference(void **lhs, void *rhs); + +private: + void *shadow_addr; + void *addr_to_shadow_addr(void *addr); +}; + +} // namespace __plsan + +#endif diff --git a/RuntimeLibrary/plsan_storage.cpp b/RuntimeLibrary/plsan_storage.cpp new file mode 100644 index 000000000..6deaadcbb --- /dev/null +++ b/RuntimeLibrary/plsan_storage.cpp @@ -0,0 +1,11 @@ +#include "plsan_storage.h" + +void PlsanStorage::push_function() {} + +void PlsanStorage::pop_function() {} + +void PlsanStorage::add_mem_addr() {} + +LocalDynAllocStorage PlsanStorage::get_function_stack() { + return function_stack; +} diff --git a/RuntimeLibrary/plsan_storage.h b/RuntimeLibrary/plsan_storage.h new file mode 100644 index 000000000..a00863ae8 --- /dev/null +++ b/RuntimeLibrary/plsan_storage.h @@ -0,0 +1,19 @@ +#ifndef PLSAN_STORAGE_H +#define PLSAN_STORAGE_H + +#include + +using LocalDynAllocStorage = std::stack>; + +class PlsanStorage { +public: + void push_function(); + void pop_function(); + void add_mem_addr(); + LocalDynAllocStorage get_function_stack(); + +private: + LocalDynAllocStorage function_stack; +}; + +#endif From 8c465c97eba8c032e27e12443986593914501baa Mon Sep 17 00:00:00 2001 From: purplepig4657 Date: Fri, 19 Jan 2024 21:24:02 +0000 Subject: [PATCH 3/4] PreciseLeakSanitizer: Add CMakelist.txt --- RuntimeLibrary/CMakeLists.txt | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/RuntimeLibrary/CMakeLists.txt b/RuntimeLibrary/CMakeLists.txt index 12c42f22d..028a92bd3 100644 --- a/RuntimeLibrary/CMakeLists.txt +++ b/RuntimeLibrary/CMakeLists.txt @@ -1 +1,25 @@ -add_library(plsan plsan.cpp) +cmake_minimum_required(VERSION 3.10) + +project(Plsan) + +# Add source files to the project +set(SOURCES + plsan.cpp + plsan_storage.cpp + plsan_handler.cpp + plsan_shadow.cpp +) + +# Add header files to the project +set(HEADERS + plsan.h + plsan_storage.h + plsan_handler.h + plsan_shadow.h +) + +# Add library target +add_library(plsan STATIC ${SOURCES} ${HEADERS}) + +# Specify include directories +target_include_directories(plsan PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) From 370fcccc77305a9c6d6f74ba61bd60edc21c731c Mon Sep 17 00:00:00 2001 From: purplepig4657 Date: Fri, 19 Jan 2024 21:42:50 +0000 Subject: [PATCH 4/4] PreciseLeakSanitizer: Add destructor --- RuntimeLibrary/plsan.cpp | 7 ++++++- RuntimeLibrary/plsan_shadow.cpp | 2 ++ RuntimeLibrary/plsan_shadow.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/RuntimeLibrary/plsan.cpp b/RuntimeLibrary/plsan.cpp index fc16293e8..f2d810772 100644 --- a/RuntimeLibrary/plsan.cpp +++ b/RuntimeLibrary/plsan.cpp @@ -7,11 +7,16 @@ #include +__plsan::Plsan *plsan; + /* Initialization routines called before main() */ __attribute__((constructor)) void __plsan_init() { /* TODO: */ - __plsan::Plsan *plsan; + plsan = new __plsan::Plsan(); } +/* finialization routines called after main()*/ +__attribute__((destructor)) void __plsan_fini() { delete plsan; } + void __plsan_alloc(void *addr, size_t size) { /* TODO: initialize references */ } diff --git a/RuntimeLibrary/plsan_shadow.cpp b/RuntimeLibrary/plsan_shadow.cpp index 53f440dcc..bc0f042c9 100644 --- a/RuntimeLibrary/plsan_shadow.cpp +++ b/RuntimeLibrary/plsan_shadow.cpp @@ -11,6 +11,8 @@ PlsanShadow::PlsanShadow() { throw "mmap failed\n"; } +PlsanShadow::~PlsanShadow() { munmap(shadow_addr, MMAP_SIZE); } + void PlsanShadow::alloc_shadow(void *addr, size_t size) {} void PlsanShadow::update_reference(void **lhs, void *rhs) {} diff --git a/RuntimeLibrary/plsan_shadow.h b/RuntimeLibrary/plsan_shadow.h index 1d9f72556..a0e395a15 100644 --- a/RuntimeLibrary/plsan_shadow.h +++ b/RuntimeLibrary/plsan_shadow.h @@ -10,6 +10,7 @@ namespace __plsan { class PlsanShadow { public: PlsanShadow(); + ~PlsanShadow(); void alloc_shadow(void *addr, size_t size); void update_reference(void **lhs, void *rhs);