diff options
author | Alexey Samsonov <vonosmas@gmail.com> | 2014-05-29 00:51:15 +0000 |
---|---|---|
committer | Alexey Samsonov <vonosmas@gmail.com> | 2014-05-29 00:51:15 +0000 |
commit | b18eabd2d88e95746c83a88d76ab31fed1e2903c (patch) | |
tree | f2991e6c3c582fd58ddfdb29c820c748783abc7d /lib/Transforms/Instrumentation | |
parent | 1d4e8baa9c7f9dfc14156a762d2cd0016ceca034 (diff) | |
download | llvm-b18eabd2d88e95746c83a88d76ab31fed1e2903c.tar.gz llvm-b18eabd2d88e95746c83a88d76ab31fed1e2903c.tar.bz2 llvm-b18eabd2d88e95746c83a88d76ab31fed1e2903c.tar.xz |
[ASan] Use llvm.global_ctors to insert init-order checking calls into ASan runtime.
Don't assume that dynamically initialized globals are all initialized from
_GLOBAL__<module_name>I_ function. Instead, scan the llvm.global_ctors and
insert poison/unpoison calls to each function there.
Patch by Nico Weber!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209780 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Instrumentation')
-rw-r--r-- | lib/Transforms/Instrumentation/AddressSanitizer.cpp | 57 |
1 files changed, 23 insertions, 34 deletions
diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index f8cdb9f8f3..94050e47da 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -391,6 +391,7 @@ class AddressSanitizerModule : public ModulePass { void initializeCallbacks(Module &M); bool ShouldInstrumentGlobal(GlobalVariable *G); + void poisonOneInitializer(Function &GlobalInit, GlobalValue *ModuleName); void createInitializerPoisonCalls(Module &M, GlobalValue *ModuleName); size_t MinRedzoneSizeForGlobal() const { return RedzoneSizeForScale(Mapping.Scale); @@ -851,48 +852,36 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns, Crash->setDebugLoc(OrigIns->getDebugLoc()); } -void AddressSanitizerModule::createInitializerPoisonCalls( - Module &M, GlobalValue *ModuleName) { - // We do all of our poisoning and unpoisoning within a global constructor. - // These are called _GLOBAL__(sub_)?I_.*. - // TODO: Consider looking through the functions in - // M.getGlobalVariable("llvm.global_ctors") instead of using this stringly - // typed approach. - Function *GlobalInit = nullptr; - for (auto &F : M.getFunctionList()) { - StringRef FName = F.getName(); - - const char kGlobalPrefix[] = "_GLOBAL__"; - if (!FName.startswith(kGlobalPrefix)) - continue; - FName = FName.substr(strlen(kGlobalPrefix)); - - const char kOptionalSub[] = "sub_"; - if (FName.startswith(kOptionalSub)) - FName = FName.substr(strlen(kOptionalSub)); - - if (FName.startswith("I_")) { - GlobalInit = &F; - break; - } - } - // If that function is not present, this TU contains no globals, or they have - // all been optimized away - if (!GlobalInit) - return; - +void AddressSanitizerModule::poisonOneInitializer(Function &GlobalInit, + GlobalValue *ModuleName) { // Set up the arguments to our poison/unpoison functions. - IRBuilder<> IRB(GlobalInit->begin()->getFirstInsertionPt()); + IRBuilder<> IRB(GlobalInit.begin()->getFirstInsertionPt()); // Add a call to poison all external globals before the given function starts. Value *ModuleNameAddr = ConstantExpr::getPointerCast(ModuleName, IntptrTy); IRB.CreateCall(AsanPoisonGlobals, ModuleNameAddr); // Add calls to unpoison all globals before each return instruction. - for (Function::iterator I = GlobalInit->begin(), E = GlobalInit->end(); - I != E; ++I) { - if (ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator())) { + for (auto &BB : GlobalInit.getBasicBlockList()) + if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) CallInst::Create(AsanUnpoisonGlobals, "", RI); +} + +void AddressSanitizerModule::createInitializerPoisonCalls( + Module &M, GlobalValue *ModuleName) { + GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); + + ConstantArray *CA = cast<ConstantArray>(GV->getInitializer()); + for (Use &OP : CA->operands()) { + if (isa<ConstantAggregateZero>(OP)) + continue; + ConstantStruct *CS = cast<ConstantStruct>(OP); + + // Must have a function or null ptr. + // (CS->getOperand(0) is the init priority.) + if (Function* F = dyn_cast<Function>(CS->getOperand(1))) { + if (F->getName() != kAsanModuleCtorName) + poisonOneInitializer(*F, ModuleName); } } } |