From 3c7faae346f548c55cad86d82a2e242443001f23 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Fri, 6 Jan 2012 18:09:21 +0000 Subject: [asan] cleanup: remove the SIGILL-related code (compiler part) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147667 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/AddressSanitizer.cpp | 76 +++------------------- 1 file changed, 8 insertions(+), 68 deletions(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 4cc5727..dbd9eba 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -22,7 +22,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Function.h" -#include "llvm/InlineAsm.h" #include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" @@ -93,9 +92,6 @@ static cl::opt ClMemIntrin("asan-memintrin", static cl::opt ClBlackListFile("asan-blacklist", cl::desc("File containing the list of functions to ignore " "during instrumentation"), cl::Hidden); -static cl::opt ClUseCall("asan-use-call", - cl::desc("Use function call to generate a crash"), cl::Hidden, - cl::init(true)); // These flags allow to change the shadow mapping. // The shadow mapping looks like @@ -332,70 +328,14 @@ void AddressSanitizer::instrumentMop(Instruction *I) { Instruction *AddressSanitizer::generateCrashCode( IRBuilder<> &IRB, Value *Addr, bool IsWrite, uint32_t TypeSize) { - - if (ClUseCall) { - // Here we use a call instead of arch-specific asm to report an error. - // This is almost always slower (because the codegen needs to generate - // prologue/epilogue for otherwise leaf functions) and generates more code. - // This mode could be useful if we can not use SIGILL for some reason. - // - // IsWrite and TypeSize are encoded in the function name. - std::string FunctionName = std::string(kAsanReportErrorTemplate) + - (IsWrite ? "store" : "load") + itostr(TypeSize / 8); - Value *ReportWarningFunc = CurrentModule->getOrInsertFunction( - FunctionName, IRB.getVoidTy(), IntptrTy, NULL); - CallInst *Call = IRB.CreateCall(ReportWarningFunc, Addr); - Call->setDoesNotReturn(); - return Call; - } - - uint32_t LogOfSizeInBytes = CountTrailingZeros_32(TypeSize / 8); - assert(8U * (1 << LogOfSizeInBytes) == TypeSize); - uint8_t TelltaleValue = IsWrite * 8 + LogOfSizeInBytes; - assert(TelltaleValue < 16); - - // Move the failing address to %rax/%eax - FunctionType *Fn1Ty = FunctionType::get( - IRB.getVoidTy(), ArrayRef(IntptrTy), false); - const char *MovStr = LongSize == 32 - ? "mov $0, %eax" : "mov $0, %rax"; - Value *AsmMov = InlineAsm::get( - Fn1Ty, StringRef(MovStr), StringRef("r"), true); - IRB.CreateCall(AsmMov, Addr); - - // crash with ud2; could use int3, but it is less friendly to gdb. - // after ud2 put a 1-byte instruction that encodes the access type and size. - - const char *TelltaleInsns[16] = { - "push %eax", // 0x50 - "push %ecx", // 0x51 - "push %edx", // 0x52 - "push %ebx", // 0x53 - "push %esp", // 0x54 - "push %ebp", // 0x55 - "push %esi", // 0x56 - "push %edi", // 0x57 - "pop %eax", // 0x58 - "pop %ecx", // 0x59 - "pop %edx", // 0x5a - "pop %ebx", // 0x5b - "pop %esp", // 0x5c - "pop %ebp", // 0x5d - "pop %esi", // 0x5e - "pop %edi" // 0x5f - }; - - std::string AsmStr = "ud2;"; - AsmStr += TelltaleInsns[TelltaleValue]; - Value *MyAsm = InlineAsm::get(FunctionType::get(Type::getVoidTy(*C), false), - StringRef(AsmStr), StringRef(""), true); - CallInst *AsmCall = IRB.CreateCall(MyAsm); - - // This saves us one jump, but triggers a bug in RA (or somewhere else): - // while building 483.xalancbmk the compiler goes into infinite loop in - // llvm::SpillPlacement::iterate() / RAGreedy::growRegion - // AsmCall->setDoesNotReturn(); - return AsmCall; + // IsWrite and TypeSize are encoded in the function name. + std::string FunctionName = std::string(kAsanReportErrorTemplate) + + (IsWrite ? "store" : "load") + itostr(TypeSize / 8); + Value *ReportWarningFunc = CurrentModule->getOrInsertFunction( + FunctionName, IRB.getVoidTy(), IntptrTy, NULL); + CallInst *Call = IRB.CreateCall(ReportWarningFunc, Addr); + Call->setDoesNotReturn(); + return Call; } void AddressSanitizer::instrumentAddress(Instruction *OrigIns, -- cgit v1.1 From bcb55ce3862bbbedac4e09d7099c9e0efc434e4b Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Wed, 11 Jan 2012 18:15:23 +0000 Subject: [asan] extend the workaround for http://llvm.org/bugs/show_bug.cgi?id=11395: don't instrument the function at all on x86_32 if it has a large asm blob git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147953 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index dbd9eba..e645a9f 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -617,6 +617,7 @@ bool AddressSanitizer::handleFunction(Module &M, Function &F) { TempsToInstrument.clear(); for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { + if (LooksLikeCodeInBug11395(BI)) return false; if ((isa(BI) && ClInstrumentReads) || (isa(BI) && ClInstrumentWrites)) { Value *Addr = getLDSTOperand(BI); @@ -792,7 +793,6 @@ bool AddressSanitizer::poisonStackInFunction(Module &M, Function &F) { BasicBlock &BB = *FI; for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) { - if (LooksLikeCodeInBug11395(BI)) return false; if (isa(BI)) { RetVec.push_back(BI); continue; -- cgit v1.1 From 25878042030e85c244b41bfcdfad27c32360e2ec Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Mon, 23 Jan 2012 11:22:43 +0000 Subject: Implemented AddressSanitizer::getPassName() git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148697 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index e645a9f..6ee9550 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -143,6 +143,7 @@ class BlackList { /// AddressSanitizer: instrument the code in module to find memory bugs. struct AddressSanitizer : public ModulePass { AddressSanitizer(); + virtual const char *getPassName() const; void instrumentMop(Instruction *I); void instrumentAddress(Instruction *OrigIns, IRBuilder<> &IRB, Value *Addr, uint32_t TypeSize, bool IsWrite); @@ -205,6 +206,10 @@ ModulePass *llvm::createAddressSanitizerPass() { return new AddressSanitizer(); } +const char *AddressSanitizer::getPassName() const { + return "AddressSanitizer"; +} + // Create a constant for Str so that we can pass it to the run-time lib. static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { Constant *StrConst = ConstantArray::get(M.getContext(), Str); -- cgit v1.1 From 0307b9a88574d7e54459181afaa656ac92971847 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Tue, 24 Jan 2012 19:34:43 +0000 Subject: [asan] enable asan only for the functions that have Attribute::AddressSafety git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148846 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 6ee9550..3f06815 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -608,6 +608,7 @@ bool AddressSanitizer::runOnModule(Module &M) { bool AddressSanitizer::handleFunction(Module &M, Function &F) { if (BL->isIn(F)) return false; if (&F == AsanCtorFunction) return false; + if (!F.hasFnAttr(Attribute::AddressSafety)) return false; if (!ClDebugFunc.empty() && ClDebugFunc != F.getName()) return false; -- cgit v1.1 From f1639abf1aaba1448f719f595156cd0f4cd560cc Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Sat, 28 Jan 2012 04:27:16 +0000 Subject: [asan] correctly use ConstantExpr::getGetElementPtr. Catch by NAKAMURA Takumi git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149172 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 3f06815..e8fb4d5 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -484,7 +484,7 @@ bool AddressSanitizer::insertGlobalRedzones(Module &M) { Indices2[1] = IRB.getInt32(0); G->replaceAllUsesWith( - ConstantExpr::getGetElementPtr(NewGlobal, Indices2, 2)); + ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true)); NewGlobal->takeName(G); G->eraseFromParent(); -- cgit v1.1 From 8375bc923638299410e75e8f668524fc1aa113bd Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Mon, 30 Jan 2012 10:40:22 +0000 Subject: Fix compilation of ASan tests on OS X Lion (see http://code.google.com/p/address-sanitizer/issues/detail?id=32) The redzones emitted by AddressSanitizer for CFString instances confuse the linker and are of little use, so we shouldn't add them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149243 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index e8fb4d5..f0bcc53 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -422,16 +422,28 @@ bool AddressSanitizer::insertGlobalRedzones(Module &M) { continue; } - // Ignore the globals from the __OBJC section. The ObjC runtime assumes - // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to - // them. if (G->hasSection()) { StringRef Section(G->getSection()); + // Ignore the globals from the __OBJC section. The ObjC runtime assumes + // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to + // them. if ((Section.find("__OBJC,") == 0) || (Section.find("__DATA, __objc_") == 0)) { DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G); continue; } + // See http://code.google.com/p/address-sanitizer/issues/detail?id=32 + // Constant CFString instances are compiled in the following way: + // -- the string buffer is emitted into + // __TEXT,__cstring,cstring_literals + // -- the constant NSConstantString structure referencing that buffer + // is placed into __DATA,__cfstring + // Therefore there's no point in placing redzones into __DATA,__cfstring. + // Moreover, it causes the linker to crash on OS X 10.7 + if (Section.find("__DATA,__cfstring") == 0) { + DEBUG(dbgs() << "Ignoring CFString: " << *G); + continue; + } } GlobalsToChange.push_back(G); -- cgit v1.1 From a1a8a323f43a95620fc4c6b5aad8d5ff5e5eb590 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Mon, 30 Jan 2012 23:50:10 +0000 Subject: [asan] fix the ObjC support (asan Issue #33) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149300 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/AddressSanitizer.cpp | 34 +++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index f0bcc53..c638600 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -155,6 +155,7 @@ struct AddressSanitizer : public ModulePass { Instruction *InsertBefore, bool IsWrite); Value *memToShadow(Value *Shadow, IRBuilder<> &IRB); bool handleFunction(Module &M, Function &F); + bool maybeInsertAsanInitAtFunctionEntry(Function &F); bool poisonStackInFunction(Module &M, Function &F); virtual bool runOnModule(Module &M); bool insertGlobalRedzones(Module &M); @@ -617,9 +618,29 @@ bool AddressSanitizer::runOnModule(Module &M) { return Res; } +bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) { + // For each NSObject descendant having a +load method, this method is invoked + // by the ObjC runtime before any of the static constructors is called. + // Therefore we need to instrument such methods with a call to __asan_init + // at the beginning in order to initialize our runtime before any access to + // the shadow memory. + // We cannot just ignore these methods, because they may call other + // instrumented functions. + if (F.getName().find(" load]") != std::string::npos) { + IRBuilder<> IRB(F.begin()->begin()); + IRB.CreateCall(AsanInitFunction); + return true; + } + return false; +} + bool AddressSanitizer::handleFunction(Module &M, Function &F) { if (BL->isIn(F)) return false; if (&F == AsanCtorFunction) return false; + + // If needed, insert __asan_init before checking for AddressSafety attr. + maybeInsertAsanInitAtFunctionEntry(F); + if (!F.hasFnAttr(Attribute::AddressSafety)) return false; if (!ClDebugFunc.empty() && ClDebugFunc != F.getName()) @@ -673,19 +694,6 @@ bool AddressSanitizer::handleFunction(Module &M, Function &F) { DEBUG(dbgs() << F); bool ChangedStack = poisonStackInFunction(M, F); - - // For each NSObject descendant having a +load method, this method is invoked - // by the ObjC runtime before any of the static constructors is called. - // Therefore we need to instrument such methods with a call to __asan_init - // at the beginning in order to initialize our runtime before any access to - // the shadow memory. - // We cannot just ignore these methods, because they may call other - // instrumented functions. - if (F.getName().find(" load]") != std::string::npos) { - IRBuilder<> IRB(F.begin()->begin()); - IRB.CreateCall(AsanInitFunction); - } - return NumInstrumented > 0 || ChangedStack; } -- cgit v1.1 From 6a89228faca4b30c4abc29b5dec98bdac011ea4c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 31 Jan 2012 06:18:43 +0000 Subject: eliminate the "string" form of ConstantArray::get, using ConstantDataArray::getString instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149365 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index c638600..b8ead89 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -213,7 +213,7 @@ const char *AddressSanitizer::getPassName() const { // Create a constant for Str so that we can pass it to the run-time lib. static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { - Constant *StrConst = ConstantArray::get(M.getContext(), Str); + Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); return new GlobalVariable(M, StrConst->getType(), true, GlobalValue::PrivateLinkage, StrConst, ""); } -- cgit v1.1 From 91766fe066efe6e0969ba805a2e3726a70ed34a3 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 1 Feb 2012 04:51:17 +0000 Subject: Revert Chris' commits up to r149348 that started causing VMCoreTests unit test to fail. These are: r149348 r149351 r149352 r149354 r149356 r149357 r149361 r149362 r149364 r149365 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149470 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index b8ead89..c638600 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -213,7 +213,7 @@ const char *AddressSanitizer::getPassName() const { // Create a constant for Str so that we can pass it to the run-time lib. static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { - Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); + Constant *StrConst = ConstantArray::get(M.getContext(), Str); return new GlobalVariable(M, StrConst->getType(), true, GlobalValue::PrivateLinkage, StrConst, ""); } -- cgit v1.1 From 18c7f80b3e83ab584bd8572695a3cde8bafd9d3c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 5 Feb 2012 02:29:43 +0000 Subject: reapply the patches reverted in r149470 that reenable ConstantDataArray, but with a critical fix to the SelectionDAG code that optimizes copies from strings into immediate stores: the previous code was stopping reading string data at the first nul. Address this by adding a new argument to llvm::getConstantStringInfo, preserving the behavior before the patch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149800 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index c638600..b8ead89 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -213,7 +213,7 @@ const char *AddressSanitizer::getPassName() const { // Create a constant for Str so that we can pass it to the run-time lib. static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { - Constant *StrConst = ConstantArray::get(M.getContext(), Str); + Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); return new GlobalVariable(M, StrConst->getType(), true, GlobalValue::PrivateLinkage, StrConst, ""); } -- cgit v1.1 From 858143816d43e58b17bfd11cb1b57afbd7f0f893 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 7 Feb 2012 05:05:23 +0000 Subject: Convert assert(0) to llvm_unreachable git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149967 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index b8ead89..150868d 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -703,8 +703,7 @@ static uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize) { if (ShadowRedzoneSize == 4) return (PoisonByte << 24) + (PoisonByte << 16) + (PoisonByte << 8) + (PoisonByte); - assert(0 && "ShadowRedzoneSize is either 1, 2 or 4"); - return 0; + llvm_unreachable("ShadowRedzoneSize is either 1, 2 or 4"); } static void PoisonShadowPartialRightRedzone(uint8_t *Shadow, -- cgit v1.1 From 95e3cf44a9d4672655dee3bd558bfeefa631dd55 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Wed, 8 Feb 2012 21:36:17 +0000 Subject: [asan] unpoison the stack before every noreturn call. Fixes asan issue 37. llvm part git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150102 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 150868d..ce5d43a 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -60,6 +60,7 @@ static const char *kAsanReportErrorTemplate = "__asan_report_"; static const char *kAsanRegisterGlobalsName = "__asan_register_globals"; static const char *kAsanUnregisterGlobalsName = "__asan_unregister_globals"; static const char *kAsanInitName = "__asan_init"; +static const char *kAsanHandleNoReturnName = "__asan_handle_no_return"; static const char *kAsanMappingOffsetName = "__asan_mapping_offset"; static const char *kAsanMappingScaleName = "__asan_mapping_scale"; static const char *kAsanStackMallocName = "__asan_stack_malloc"; @@ -649,6 +650,7 @@ bool AddressSanitizer::handleFunction(Module &M, Function &F) { // (unless there are calls between uses). SmallSet TempsToInstrument; SmallVector ToInstrument; + SmallVector NoReturnCalls; // Fill the set of memory operations to instrument. for (Function::iterator FI = F.begin(), FE = F.end(); @@ -667,9 +669,12 @@ bool AddressSanitizer::handleFunction(Module &M, Function &F) { } else if (isa(BI) && ClMemIntrin) { // ok, take it. } else { - if (isa(BI)) { + if (CallInst *CI = dyn_cast(BI)) { // A call inside BB. TempsToInstrument.clear(); + if (CI->doesNotReturn()) { + NoReturnCalls.push_back(CI); + } } continue; } @@ -694,7 +699,17 @@ bool AddressSanitizer::handleFunction(Module &M, Function &F) { DEBUG(dbgs() << F); bool ChangedStack = poisonStackInFunction(M, F); - return NumInstrumented > 0 || ChangedStack; + + // We must unpoison the stack before every NoReturn call (throw, _exit, etc). + // See e.g. http://code.google.com/p/address-sanitizer/issues/detail?id=37 + for (size_t i = 0, n = NoReturnCalls.size(); i != n; i++) { + Instruction *CI = NoReturnCalls[i]; + IRBuilder<> IRB(CI); + IRB.CreateCall(M.getOrInsertFunction(kAsanHandleNoReturnName, + IRB.getVoidTy(), NULL)); + } + + return NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty(); } static uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize) { -- cgit v1.1 From d8313be41031e4d768f5b38199904d4debff88cd Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Fri, 2 Mar 2012 10:41:08 +0000 Subject: ASan: use getTypeAllocSize instead of getTypeStoreSize. This change replaces getTypeStoreSize with getTypeAllocSize in AddressSanitizer instrumentation for stack allocations. One case where old behaviour produced undesired results is an optimization in InstCombine pass (PromoteCastOfAllocation), which can replace alloca(T) with alloca(S), where S has the same AllocSize, but a smaller StoreSize. Another case is memcpy(long double => long double), where ASan will poison bytes 10-15 of a stack-allocated long double (StoreSize 10, AllocSize 16, sizeof(long double) = 16). See http://llvm.org/bugs/show_bug.cgi?id=12047 for more context. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151887 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Transforms/Instrumentation/AddressSanitizer.cpp') diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index ce5d43a..123e399 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -167,7 +167,7 @@ struct AddressSanitizer : public ModulePass { uint64_t getAllocaSizeInBytes(AllocaInst *AI) { Type *Ty = AI->getAllocatedType(); - uint64_t SizeInBytes = TD->getTypeStoreSizeInBits(Ty) / 8; + uint64_t SizeInBytes = TD->getTypeAllocSize(Ty); return SizeInBytes; } uint64_t getAlignedSize(uint64_t SizeInBytes) { -- cgit v1.1