blob: 3f1c9843cb5c702e0dcb1d80c6324576d0c6fb0a [file] [log] [blame]
Kostya Serebryany800e03f2011-11-16 01:35:23 +00001//===-- AddressSanitizer.cpp - memory error detector ------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11// Details of the algorithm:
12// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
13//
14//===----------------------------------------------------------------------===//
15
16#define DEBUG_TYPE "asan"
17
Kostya Serebryanya1c45042012-03-14 23:22:10 +000018#include "FunctionBlackList.h"
Chandler Carruth06cb8ed2012-06-29 12:38:19 +000019#include "llvm/Function.h"
20#include "llvm/IRBuilder.h"
21#include "llvm/IntrinsicInst.h"
22#include "llvm/LLVMContext.h"
23#include "llvm/Module.h"
24#include "llvm/Type.h"
Kostya Serebryany800e03f2011-11-16 01:35:23 +000025#include "llvm/ADT/ArrayRef.h"
26#include "llvm/ADT/OwningPtr.h"
27#include "llvm/ADT/SmallSet.h"
28#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringExtras.h"
Evgeniy Stepanov06fdbaa2012-05-23 11:52:12 +000031#include "llvm/ADT/Triple.h"
Kostya Serebryany800e03f2011-11-16 01:35:23 +000032#include "llvm/Support/CommandLine.h"
33#include "llvm/Support/DataTypes.h"
34#include "llvm/Support/Debug.h"
Kostya Serebryany800e03f2011-11-16 01:35:23 +000035#include "llvm/Support/raw_ostream.h"
36#include "llvm/Support/system_error.h"
37#include "llvm/Target/TargetData.h"
38#include "llvm/Target/TargetMachine.h"
39#include "llvm/Transforms/Instrumentation.h"
40#include "llvm/Transforms/Utils/BasicBlockUtils.h"
41#include "llvm/Transforms/Utils/ModuleUtils.h"
Kostya Serebryany800e03f2011-11-16 01:35:23 +000042
43#include <string>
44#include <algorithm>
45
46using namespace llvm;
47
48static const uint64_t kDefaultShadowScale = 3;
49static const uint64_t kDefaultShadowOffset32 = 1ULL << 29;
50static const uint64_t kDefaultShadowOffset64 = 1ULL << 44;
Evgeniy Stepanov06fdbaa2012-05-23 11:52:12 +000051static const uint64_t kDefaultShadowOffsetAndroid = 0;
Kostya Serebryany800e03f2011-11-16 01:35:23 +000052
53static const size_t kMaxStackMallocSize = 1 << 16; // 64K
54static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3;
55static const uintptr_t kRetiredStackFrameMagic = 0x45E0360E;
56
57static const char *kAsanModuleCtorName = "asan.module_ctor";
Kostya Serebryany7bcfc992011-12-15 21:59:03 +000058static const char *kAsanModuleDtorName = "asan.module_dtor";
59static const int kAsanCtorAndCtorPriority = 1;
Kostya Serebryany800e03f2011-11-16 01:35:23 +000060static const char *kAsanReportErrorTemplate = "__asan_report_";
61static const char *kAsanRegisterGlobalsName = "__asan_register_globals";
Kostya Serebryany7bcfc992011-12-15 21:59:03 +000062static const char *kAsanUnregisterGlobalsName = "__asan_unregister_globals";
Kostya Serebryany800e03f2011-11-16 01:35:23 +000063static const char *kAsanInitName = "__asan_init";
Kostya Serebryany95e3cf42012-02-08 21:36:17 +000064static const char *kAsanHandleNoReturnName = "__asan_handle_no_return";
Kostya Serebryany800e03f2011-11-16 01:35:23 +000065static const char *kAsanMappingOffsetName = "__asan_mapping_offset";
66static const char *kAsanMappingScaleName = "__asan_mapping_scale";
67static const char *kAsanStackMallocName = "__asan_stack_malloc";
68static const char *kAsanStackFreeName = "__asan_stack_free";
69
70static const int kAsanStackLeftRedzoneMagic = 0xf1;
71static const int kAsanStackMidRedzoneMagic = 0xf2;
72static const int kAsanStackRightRedzoneMagic = 0xf3;
73static const int kAsanStackPartialRedzoneMagic = 0xf4;
74
75// Command-line flags.
76
77// This flag may need to be replaced with -f[no-]asan-reads.
78static cl::opt<bool> ClInstrumentReads("asan-instrument-reads",
79 cl::desc("instrument read instructions"), cl::Hidden, cl::init(true));
80static cl::opt<bool> ClInstrumentWrites("asan-instrument-writes",
81 cl::desc("instrument write instructions"), cl::Hidden, cl::init(true));
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +000082static cl::opt<bool> ClInstrumentAtomics("asan-instrument-atomics",
83 cl::desc("instrument atomic instructions (rmw, cmpxchg)"),
84 cl::Hidden, cl::init(true));
Kostya Serebryany324cbb82012-06-28 09:34:41 +000085// This flags limits the number of instructions to be instrumented
86// in any given BB. Normally, this should be set to unlimited (INT_MAX),
87// but due to http://llvm.org/bugs/show_bug.cgi?id=12652 we temporary
88// set it to 10000.
89static cl::opt<int> ClMaxInsnsToInstrumentPerBB("asan-max-ins-per-bb",
90 cl::init(10000),
91 cl::desc("maximal number of instructions to instrument in any given BB"),
92 cl::Hidden);
Kostya Serebryany800e03f2011-11-16 01:35:23 +000093// This flag may need to be replaced with -f[no]asan-stack.
94static cl::opt<bool> ClStack("asan-stack",
95 cl::desc("Handle stack memory"), cl::Hidden, cl::init(true));
96// This flag may need to be replaced with -f[no]asan-use-after-return.
97static cl::opt<bool> ClUseAfterReturn("asan-use-after-return",
98 cl::desc("Check return-after-free"), cl::Hidden, cl::init(false));
99// This flag may need to be replaced with -f[no]asan-globals.
100static cl::opt<bool> ClGlobals("asan-globals",
101 cl::desc("Handle global objects"), cl::Hidden, cl::init(true));
102static cl::opt<bool> ClMemIntrin("asan-memintrin",
103 cl::desc("Handle memset/memcpy/memmove"), cl::Hidden, cl::init(true));
104// This flag may need to be replaced with -fasan-blacklist.
105static cl::opt<std::string> ClBlackListFile("asan-blacklist",
106 cl::desc("File containing the list of functions to ignore "
107 "during instrumentation"), cl::Hidden);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000108
109// These flags allow to change the shadow mapping.
110// The shadow mapping looks like
111// Shadow = (Mem >> scale) + (1 << offset_log)
112static cl::opt<int> ClMappingScale("asan-mapping-scale",
113 cl::desc("scale of asan shadow mapping"), cl::Hidden, cl::init(0));
114static cl::opt<int> ClMappingOffsetLog("asan-mapping-offset-log",
115 cl::desc("offset of asan shadow mapping"), cl::Hidden, cl::init(-1));
116
117// Optimization flags. Not user visible, used mostly for testing
118// and benchmarking the tool.
119static cl::opt<bool> ClOpt("asan-opt",
120 cl::desc("Optimize instrumentation"), cl::Hidden, cl::init(true));
121static cl::opt<bool> ClOptSameTemp("asan-opt-same-temp",
122 cl::desc("Instrument the same temp just once"), cl::Hidden,
123 cl::init(true));
124static cl::opt<bool> ClOptGlobals("asan-opt-globals",
125 cl::desc("Don't instrument scalar globals"), cl::Hidden, cl::init(true));
126
127// Debug flags.
128static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
129 cl::init(0));
130static cl::opt<int> ClDebugStack("asan-debug-stack", cl::desc("debug stack"),
131 cl::Hidden, cl::init(0));
132static cl::opt<std::string> ClDebugFunc("asan-debug-func",
133 cl::Hidden, cl::desc("Debug func"));
134static cl::opt<int> ClDebugMin("asan-debug-min", cl::desc("Debug min inst"),
135 cl::Hidden, cl::init(-1));
136static cl::opt<int> ClDebugMax("asan-debug-max", cl::desc("Debug man inst"),
137 cl::Hidden, cl::init(-1));
138
139namespace {
140
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000141/// AddressSanitizer: instrument the code in module to find memory bugs.
142struct AddressSanitizer : public ModulePass {
143 AddressSanitizer();
Alexander Potapenko25878042012-01-23 11:22:43 +0000144 virtual const char *getPassName() const;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000145 void instrumentMop(Instruction *I);
146 void instrumentAddress(Instruction *OrigIns, IRBuilder<> &IRB,
147 Value *Addr, uint32_t TypeSize, bool IsWrite);
148 Instruction *generateCrashCode(IRBuilder<> &IRB, Value *Addr,
149 bool IsWrite, uint32_t TypeSize);
150 bool instrumentMemIntrinsic(MemIntrinsic *MI);
151 void instrumentMemIntrinsicParam(Instruction *OrigIns, Value *Addr,
152 Value *Size,
153 Instruction *InsertBefore, bool IsWrite);
154 Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
155 bool handleFunction(Module &M, Function &F);
Kostya Serebryanya1a8a322012-01-30 23:50:10 +0000156 bool maybeInsertAsanInitAtFunctionEntry(Function &F);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000157 bool poisonStackInFunction(Module &M, Function &F);
158 virtual bool runOnModule(Module &M);
159 bool insertGlobalRedzones(Module &M);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000160 static char ID; // Pass identification, replacement for typeid
161
162 private:
163
164 uint64_t getAllocaSizeInBytes(AllocaInst *AI) {
165 Type *Ty = AI->getAllocatedType();
Evgeniy Stepanovd8313be2012-03-02 10:41:08 +0000166 uint64_t SizeInBytes = TD->getTypeAllocSize(Ty);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000167 return SizeInBytes;
168 }
169 uint64_t getAlignedSize(uint64_t SizeInBytes) {
170 return ((SizeInBytes + RedzoneSize - 1)
171 / RedzoneSize) * RedzoneSize;
172 }
173 uint64_t getAlignedAllocaSize(AllocaInst *AI) {
174 uint64_t SizeInBytes = getAllocaSizeInBytes(AI);
175 return getAlignedSize(SizeInBytes);
176 }
177
Alexander Potapenko55cabae2012-04-23 10:47:31 +0000178 Function *checkInterfaceFunction(Constant *FuncOrBitcast);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000179 void PoisonStack(const ArrayRef<AllocaInst*> &AllocaVec, IRBuilder<> IRB,
180 Value *ShadowBase, bool DoPoison);
Kostya Serebryany5a3a9c92011-11-18 01:41:06 +0000181 bool LooksLikeCodeInBug11395(Instruction *I);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000182
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000183 LLVMContext *C;
184 TargetData *TD;
185 uint64_t MappingOffset;
186 int MappingScale;
187 size_t RedzoneSize;
188 int LongSize;
189 Type *IntptrTy;
190 Type *IntptrPtrTy;
191 Function *AsanCtorFunction;
192 Function *AsanInitFunction;
193 Instruction *CtorInsertBefore;
Kostya Serebryanya1c45042012-03-14 23:22:10 +0000194 OwningPtr<FunctionBlackList> BL;
Kostya Serebryany9db5b5f2012-07-16 14:09:42 +0000195 // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
196 static const size_t kNumberOfAccessSizes = 5;
197 // This array is indexed by AccessIsWrite and log2(AccessSize).
198 Function *AsanErrorCallback[2][kNumberOfAccessSizes];
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000199};
200} // namespace
201
202char AddressSanitizer::ID = 0;
203INITIALIZE_PASS(AddressSanitizer, "asan",
204 "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
205 false, false)
206AddressSanitizer::AddressSanitizer() : ModulePass(ID) { }
207ModulePass *llvm::createAddressSanitizerPass() {
208 return new AddressSanitizer();
209}
210
Alexander Potapenko25878042012-01-23 11:22:43 +0000211const char *AddressSanitizer::getPassName() const {
212 return "AddressSanitizer";
213}
214
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000215// Create a constant for Str so that we can pass it to the run-time lib.
216static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) {
Chris Lattner18c7f802012-02-05 02:29:43 +0000217 Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000218 return new GlobalVariable(M, StrConst->getType(), true,
219 GlobalValue::PrivateLinkage, StrConst, "");
220}
221
222// Split the basic block and insert an if-then code.
223// Before:
224// Head
Kostya Serebryany56139bc2012-07-02 11:42:29 +0000225// Cmp
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000226// Tail
227// After:
228// Head
229// if (Cmp)
Kostya Serebryany56139bc2012-07-02 11:42:29 +0000230// ThenBlock
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000231// Tail
232//
Kostya Serebryany56139bc2012-07-02 11:42:29 +0000233// Returns the ThenBlock's terminator.
234static BranchInst *splitBlockAndInsertIfThen(Value *Cmp) {
235 Instruction *SplitBefore = cast<Instruction>(Cmp)->getNextNode();
Chandler Carruthc3c8db92012-07-16 08:58:53 +0000236 BasicBlock *Head = SplitBefore->getParent();
Chandler Carruth349f14c2012-07-16 10:01:02 +0000237 BasicBlock *Tail = Head->splitBasicBlock(SplitBefore);
Chandler Carruthc3c8db92012-07-16 08:58:53 +0000238 TerminatorInst *HeadOldTerm = Head->getTerminator();
Chandler Carruth349f14c2012-07-16 10:01:02 +0000239 LLVMContext &C = Head->getParent()->getParent()->getContext();
240 BasicBlock *ThenBlock = BasicBlock::Create(C, "", Head->getParent());
241 BranchInst *HeadNewTerm =
242 BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/Tail, Cmp);
243 ReplaceInstWithInst(HeadOldTerm, HeadNewTerm);
Chandler Carruthc3c8db92012-07-16 08:58:53 +0000244
Chandler Carruth349f14c2012-07-16 10:01:02 +0000245 BranchInst *CheckTerm = BranchInst::Create(Tail, ThenBlock);
246 return CheckTerm;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000247}
248
249Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
250 // Shadow >> scale
251 Shadow = IRB.CreateLShr(Shadow, MappingScale);
252 if (MappingOffset == 0)
253 return Shadow;
254 // (Shadow >> scale) | offset
255 return IRB.CreateOr(Shadow, ConstantInt::get(IntptrTy,
256 MappingOffset));
257}
258
259void AddressSanitizer::instrumentMemIntrinsicParam(Instruction *OrigIns,
260 Value *Addr, Value *Size, Instruction *InsertBefore, bool IsWrite) {
261 // Check the first byte.
262 {
263 IRBuilder<> IRB(InsertBefore);
264 instrumentAddress(OrigIns, IRB, Addr, 8, IsWrite);
265 }
266 // Check the last byte.
267 {
268 IRBuilder<> IRB(InsertBefore);
269 Value *SizeMinusOne = IRB.CreateSub(
270 Size, ConstantInt::get(Size->getType(), 1));
271 SizeMinusOne = IRB.CreateIntCast(SizeMinusOne, IntptrTy, false);
272 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
273 Value *AddrPlusSizeMinisOne = IRB.CreateAdd(AddrLong, SizeMinusOne);
274 instrumentAddress(OrigIns, IRB, AddrPlusSizeMinisOne, 8, IsWrite);
275 }
276}
277
278// Instrument memset/memmove/memcpy
279bool AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
280 Value *Dst = MI->getDest();
281 MemTransferInst *MemTran = dyn_cast<MemTransferInst>(MI);
282 Value *Src = MemTran ? MemTran->getSource() : NULL;
283 Value *Length = MI->getLength();
284
285 Constant *ConstLength = dyn_cast<Constant>(Length);
286 Instruction *InsertBefore = MI;
287 if (ConstLength) {
288 if (ConstLength->isNullValue()) return false;
289 } else {
290 // The size is not a constant so it could be zero -- check at run-time.
291 IRBuilder<> IRB(InsertBefore);
292
293 Value *Cmp = IRB.CreateICmpNE(Length,
Kostya Serebryany56139bc2012-07-02 11:42:29 +0000294 Constant::getNullValue(Length->getType()));
295 InsertBefore = splitBlockAndInsertIfThen(Cmp);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000296 }
297
298 instrumentMemIntrinsicParam(MI, Dst, Length, InsertBefore, true);
299 if (Src)
300 instrumentMemIntrinsicParam(MI, Src, Length, InsertBefore, false);
301 return true;
302}
303
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +0000304// If I is an interesting memory access, return the PointerOperand
305// and set IsWrite. Otherwise return NULL.
306static Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite) {
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000307 if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +0000308 if (!ClInstrumentReads) return NULL;
309 *IsWrite = false;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000310 return LI->getPointerOperand();
311 }
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +0000312 if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
313 if (!ClInstrumentWrites) return NULL;
314 *IsWrite = true;
315 return SI->getPointerOperand();
316 }
317 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
318 if (!ClInstrumentAtomics) return NULL;
319 *IsWrite = true;
320 return RMW->getPointerOperand();
321 }
322 if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
323 if (!ClInstrumentAtomics) return NULL;
324 *IsWrite = true;
325 return XCHG->getPointerOperand();
326 }
327 return NULL;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000328}
329
330void AddressSanitizer::instrumentMop(Instruction *I) {
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +0000331 bool IsWrite;
332 Value *Addr = isInterestingMemoryAccess(I, &IsWrite);
333 assert(Addr);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000334 if (ClOpt && ClOptGlobals && isa<GlobalVariable>(Addr)) {
335 // We are accessing a global scalar variable. Nothing to catch here.
336 return;
337 }
338 Type *OrigPtrTy = Addr->getType();
339 Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
340
341 assert(OrigTy->isSized());
342 uint32_t TypeSize = TD->getTypeStoreSizeInBits(OrigTy);
343
344 if (TypeSize != 8 && TypeSize != 16 &&
345 TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
346 // Ignore all unusual sizes.
347 return;
348 }
349
350 IRBuilder<> IRB(I);
351 instrumentAddress(I, IRB, Addr, TypeSize, IsWrite);
352}
353
Alexander Potapenko55cabae2012-04-23 10:47:31 +0000354// Validate the result of Module::getOrInsertFunction called for an interface
355// function of AddressSanitizer. If the instrumented module defines a function
356// with the same name, their prototypes must match, otherwise
357// getOrInsertFunction returns a bitcast.
358Function *AddressSanitizer::checkInterfaceFunction(Constant *FuncOrBitcast) {
359 if (isa<Function>(FuncOrBitcast)) return cast<Function>(FuncOrBitcast);
360 FuncOrBitcast->dump();
361 report_fatal_error("trying to redefine an AddressSanitizer "
362 "interface function");
363}
364
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000365Instruction *AddressSanitizer::generateCrashCode(
366 IRBuilder<> &IRB, Value *Addr, bool IsWrite, uint32_t TypeSize) {
Kostya Serebryany9db5b5f2012-07-16 14:09:42 +0000367 size_t AccessSizeIndex = CountTrailingZeros_32(TypeSize / 8);
368 assert(AccessSizeIndex < kNumberOfAccessSizes);
369 CallInst *Call = IRB.CreateCall(AsanErrorCallback[IsWrite][AccessSizeIndex],
370 Addr);
Kostya Serebryany3c7faae2012-01-06 18:09:21 +0000371 Call->setDoesNotReturn();
372 return Call;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000373}
374
375void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
376 IRBuilder<> &IRB, Value *Addr,
377 uint32_t TypeSize, bool IsWrite) {
378 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
379
380 Type *ShadowTy = IntegerType::get(
381 *C, std::max(8U, TypeSize >> MappingScale));
382 Type *ShadowPtrTy = PointerType::get(ShadowTy, 0);
383 Value *ShadowPtr = memToShadow(AddrLong, IRB);
384 Value *CmpVal = Constant::getNullValue(ShadowTy);
385 Value *ShadowValue = IRB.CreateLoad(
386 IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy));
387
388 Value *Cmp = IRB.CreateICmpNE(ShadowValue, CmpVal);
389
Kostya Serebryany56139bc2012-07-02 11:42:29 +0000390 Instruction *CheckTerm = splitBlockAndInsertIfThen(Cmp);
Chandler Carruth349f14c2012-07-16 10:01:02 +0000391 IRBuilder<> IRB2(CheckTerm);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000392
393 size_t Granularity = 1 << MappingScale;
394 if (TypeSize < 8 * Granularity) {
395 // Addr & (Granularity - 1)
Chandler Carruth349f14c2012-07-16 10:01:02 +0000396 Value *LastAccessedByte = IRB2.CreateAnd(
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000397 AddrLong, ConstantInt::get(IntptrTy, Granularity - 1));
398 // (Addr & (Granularity - 1)) + size - 1
Kostya Serebryany3f119982012-04-27 10:04:53 +0000399 if (TypeSize / 8 > 1)
Chandler Carruth349f14c2012-07-16 10:01:02 +0000400 LastAccessedByte = IRB2.CreateAdd(
Kostya Serebryany3f119982012-04-27 10:04:53 +0000401 LastAccessedByte, ConstantInt::get(IntptrTy, TypeSize / 8 - 1));
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000402 // (uint8_t) ((Addr & (Granularity-1)) + size - 1)
Chandler Carruth349f14c2012-07-16 10:01:02 +0000403 LastAccessedByte = IRB2.CreateIntCast(
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000404 LastAccessedByte, IRB.getInt8Ty(), false);
405 // ((uint8_t) ((Addr & (Granularity-1)) + size - 1)) >= ShadowValue
Chandler Carruth349f14c2012-07-16 10:01:02 +0000406 Value *Cmp2 = IRB2.CreateICmpSGE(LastAccessedByte, ShadowValue);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000407
Kostya Serebryany56139bc2012-07-02 11:42:29 +0000408 CheckTerm = splitBlockAndInsertIfThen(Cmp2);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000409 }
410
Chandler Carruth349f14c2012-07-16 10:01:02 +0000411 IRBuilder<> IRB1(CheckTerm);
412 Instruction *Crash = generateCrashCode(IRB1, AddrLong, IsWrite, TypeSize);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000413 Crash->setDebugLoc(OrigIns->getDebugLoc());
Kostya Serebryanycc1d8562011-12-01 18:54:53 +0000414 ReplaceInstWithInst(CheckTerm, new UnreachableInst(*C));
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000415}
416
417// This function replaces all global variables with new variables that have
418// trailing redzones. It also creates a function that poisons
419// redzones and inserts this function into llvm.global_ctors.
420bool AddressSanitizer::insertGlobalRedzones(Module &M) {
421 SmallVector<GlobalVariable *, 16> GlobalsToChange;
422
423 for (Module::GlobalListType::iterator G = M.getGlobalList().begin(),
424 E = M.getGlobalList().end(); G != E; ++G) {
425 Type *Ty = cast<PointerType>(G->getType())->getElementType();
426 DEBUG(dbgs() << "GLOBAL: " << *G);
427
428 if (!Ty->isSized()) continue;
429 if (!G->hasInitializer()) continue;
Kostya Serebryany7cf2a042011-11-17 23:14:59 +0000430 // Touch only those globals that will not be defined in other modules.
431 // Don't handle ODR type linkages since other modules may be built w/o asan.
Kostya Serebryany2e7fb2f2011-11-17 23:37:53 +0000432 if (G->getLinkage() != GlobalVariable::ExternalLinkage &&
433 G->getLinkage() != GlobalVariable::PrivateLinkage &&
434 G->getLinkage() != GlobalVariable::InternalLinkage)
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000435 continue;
Kostya Serebryanyd2703de2011-11-23 02:10:54 +0000436 // Two problems with thread-locals:
437 // - The address of the main thread's copy can't be computed at link-time.
438 // - Need to poison all copies, not just the main thread's one.
439 if (G->isThreadLocal())
440 continue;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000441 // For now, just ignore this Alloca if the alignment is large.
442 if (G->getAlignment() > RedzoneSize) continue;
443
444 // Ignore all the globals with the names starting with "\01L_OBJC_".
445 // Many of those are put into the .cstring section. The linker compresses
446 // that section by removing the spare \0s after the string terminator, so
447 // our redzones get broken.
448 if ((G->getName().find("\01L_OBJC_") == 0) ||
449 (G->getName().find("\01l_OBJC_") == 0)) {
450 DEBUG(dbgs() << "Ignoring \\01L_OBJC_* global: " << *G);
451 continue;
452 }
453
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000454 if (G->hasSection()) {
455 StringRef Section(G->getSection());
Alexander Potapenko8375bc92012-01-30 10:40:22 +0000456 // Ignore the globals from the __OBJC section. The ObjC runtime assumes
457 // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to
458 // them.
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000459 if ((Section.find("__OBJC,") == 0) ||
460 (Section.find("__DATA, __objc_") == 0)) {
461 DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G);
462 continue;
463 }
Alexander Potapenko8375bc92012-01-30 10:40:22 +0000464 // See http://code.google.com/p/address-sanitizer/issues/detail?id=32
465 // Constant CFString instances are compiled in the following way:
466 // -- the string buffer is emitted into
467 // __TEXT,__cstring,cstring_literals
468 // -- the constant NSConstantString structure referencing that buffer
469 // is placed into __DATA,__cfstring
470 // Therefore there's no point in placing redzones into __DATA,__cfstring.
471 // Moreover, it causes the linker to crash on OS X 10.7
472 if (Section.find("__DATA,__cfstring") == 0) {
473 DEBUG(dbgs() << "Ignoring CFString: " << *G);
474 continue;
475 }
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000476 }
477
478 GlobalsToChange.push_back(G);
479 }
480
481 size_t n = GlobalsToChange.size();
482 if (n == 0) return false;
483
484 // A global is described by a structure
485 // size_t beg;
486 // size_t size;
487 // size_t size_with_redzone;
488 // const char *name;
489 // We initialize an array of such structures and pass it to a run-time call.
490 StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy,
491 IntptrTy, IntptrTy, NULL);
492 SmallVector<Constant *, 16> Initializers(n);
493
494 IRBuilder<> IRB(CtorInsertBefore);
495
496 for (size_t i = 0; i < n; i++) {
497 GlobalVariable *G = GlobalsToChange[i];
498 PointerType *PtrTy = cast<PointerType>(G->getType());
499 Type *Ty = PtrTy->getElementType();
Kostya Serebryany208a4ff2012-03-21 15:28:50 +0000500 uint64_t SizeInBytes = TD->getTypeAllocSize(Ty);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000501 uint64_t RightRedzoneSize = RedzoneSize +
502 (RedzoneSize - (SizeInBytes % RedzoneSize));
503 Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize);
504
505 StructType *NewTy = StructType::get(Ty, RightRedZoneTy, NULL);
506 Constant *NewInitializer = ConstantStruct::get(
507 NewTy, G->getInitializer(),
508 Constant::getNullValue(RightRedZoneTy), NULL);
509
Kostya Serebryanya4b2b1d2011-12-15 22:55:55 +0000510 SmallString<2048> DescriptionOfGlobal = G->getName();
511 DescriptionOfGlobal += " (";
512 DescriptionOfGlobal += M.getModuleIdentifier();
513 DescriptionOfGlobal += ")";
514 GlobalVariable *Name = createPrivateGlobalForString(M, DescriptionOfGlobal);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000515
516 // Create a new global variable with enough space for a redzone.
517 GlobalVariable *NewGlobal = new GlobalVariable(
518 M, NewTy, G->isConstant(), G->getLinkage(),
Hans Wennborgce718ff2012-06-23 11:37:03 +0000519 NewInitializer, "", G, G->getThreadLocalMode());
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000520 NewGlobal->copyAttributesFrom(G);
521 NewGlobal->setAlignment(RedzoneSize);
522
523 Value *Indices2[2];
524 Indices2[0] = IRB.getInt32(0);
525 Indices2[1] = IRB.getInt32(0);
526
527 G->replaceAllUsesWith(
Kostya Serebryanyf1639ab2012-01-28 04:27:16 +0000528 ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true));
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000529 NewGlobal->takeName(G);
530 G->eraseFromParent();
531
532 Initializers[i] = ConstantStruct::get(
533 GlobalStructTy,
534 ConstantExpr::getPointerCast(NewGlobal, IntptrTy),
535 ConstantInt::get(IntptrTy, SizeInBytes),
536 ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
537 ConstantExpr::getPointerCast(Name, IntptrTy),
538 NULL);
539 DEBUG(dbgs() << "NEW GLOBAL:\n" << *NewGlobal);
540 }
541
542 ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n);
543 GlobalVariable *AllGlobals = new GlobalVariable(
544 M, ArrayOfGlobalStructTy, false, GlobalVariable::PrivateLinkage,
545 ConstantArray::get(ArrayOfGlobalStructTy, Initializers), "");
546
Alexander Potapenko55cabae2012-04-23 10:47:31 +0000547 Function *AsanRegisterGlobals = checkInterfaceFunction(M.getOrInsertFunction(
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000548 kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL));
549 AsanRegisterGlobals->setLinkage(Function::ExternalLinkage);
550
551 IRB.CreateCall2(AsanRegisterGlobals,
552 IRB.CreatePointerCast(AllGlobals, IntptrTy),
553 ConstantInt::get(IntptrTy, n));
554
Kostya Serebryany7bcfc992011-12-15 21:59:03 +0000555 // We also need to unregister globals at the end, e.g. when a shared library
556 // gets closed.
557 Function *AsanDtorFunction = Function::Create(
558 FunctionType::get(Type::getVoidTy(*C), false),
559 GlobalValue::InternalLinkage, kAsanModuleDtorName, &M);
560 BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction);
561 IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB));
Alexander Potapenko55cabae2012-04-23 10:47:31 +0000562 Function *AsanUnregisterGlobals =
563 checkInterfaceFunction(M.getOrInsertFunction(
564 kAsanUnregisterGlobalsName,
565 IRB.getVoidTy(), IntptrTy, IntptrTy, NULL));
Kostya Serebryany7bcfc992011-12-15 21:59:03 +0000566 AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage);
567
568 IRB_Dtor.CreateCall2(AsanUnregisterGlobals,
569 IRB.CreatePointerCast(AllGlobals, IntptrTy),
570 ConstantInt::get(IntptrTy, n));
571 appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndCtorPriority);
572
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000573 DEBUG(dbgs() << M);
574 return true;
575}
576
577// virtual
578bool AddressSanitizer::runOnModule(Module &M) {
579 // Initialize the private fields. No one has accessed them before.
580 TD = getAnalysisIfAvailable<TargetData>();
581 if (!TD)
582 return false;
Kostya Serebryanya1c45042012-03-14 23:22:10 +0000583 BL.reset(new FunctionBlackList(ClBlackListFile));
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000584
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000585 C = &(M.getContext());
586 LongSize = TD->getPointerSizeInBits();
587 IntptrTy = Type::getIntNTy(*C, LongSize);
588 IntptrPtrTy = PointerType::get(IntptrTy, 0);
589
590 AsanCtorFunction = Function::Create(
591 FunctionType::get(Type::getVoidTy(*C), false),
592 GlobalValue::InternalLinkage, kAsanModuleCtorName, &M);
593 BasicBlock *AsanCtorBB = BasicBlock::Create(*C, "", AsanCtorFunction);
594 CtorInsertBefore = ReturnInst::Create(*C, AsanCtorBB);
595
596 // call __asan_init in the module ctor.
597 IRBuilder<> IRB(CtorInsertBefore);
Alexander Potapenko55cabae2012-04-23 10:47:31 +0000598 AsanInitFunction = checkInterfaceFunction(
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000599 M.getOrInsertFunction(kAsanInitName, IRB.getVoidTy(), NULL));
600 AsanInitFunction->setLinkage(Function::ExternalLinkage);
601 IRB.CreateCall(AsanInitFunction);
602
Kostya Serebryany9db5b5f2012-07-16 14:09:42 +0000603 // Create __asan_report* callbacks.
604 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
605 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
606 AccessSizeIndex++) {
607 // IsWrite and TypeSize are encoded in the function name.
608 std::string FunctionName = std::string(kAsanReportErrorTemplate) +
609 (AccessIsWrite ? "store" : "load") + itostr(1 << AccessSizeIndex);
610 AsanErrorCallback[AccessIsWrite][AccessSizeIndex] = cast<Function>(
611 M.getOrInsertFunction(FunctionName, IRB.getVoidTy(), IntptrTy, NULL));
612 }
613 }
614
Evgeniy Stepanov06fdbaa2012-05-23 11:52:12 +0000615 llvm::Triple targetTriple(M.getTargetTriple());
616 bool isAndroid = targetTriple.getEnvironment() == llvm::Triple::ANDROIDEABI;
617
618 MappingOffset = isAndroid ? kDefaultShadowOffsetAndroid :
619 (LongSize == 32 ? kDefaultShadowOffset32 : kDefaultShadowOffset64);
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000620 if (ClMappingOffsetLog >= 0) {
621 if (ClMappingOffsetLog == 0) {
622 // special case
623 MappingOffset = 0;
624 } else {
625 MappingOffset = 1ULL << ClMappingOffsetLog;
626 }
627 }
628 MappingScale = kDefaultShadowScale;
629 if (ClMappingScale) {
630 MappingScale = ClMappingScale;
631 }
632 // Redzone used for stack and globals is at least 32 bytes.
633 // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively.
634 RedzoneSize = std::max(32, (int)(1 << MappingScale));
635
636 bool Res = false;
637
638 if (ClGlobals)
639 Res |= insertGlobalRedzones(M);
640
Kostya Serebryany8c0134a2012-03-19 16:40:35 +0000641 if (ClMappingOffsetLog >= 0) {
642 // Tell the run-time the current values of mapping offset and scale.
643 GlobalValue *asan_mapping_offset =
644 new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage,
645 ConstantInt::get(IntptrTy, MappingOffset),
646 kAsanMappingOffsetName);
647 // Read the global, otherwise it may be optimized away.
648 IRB.CreateLoad(asan_mapping_offset, true);
649 }
650 if (ClMappingScale) {
651 GlobalValue *asan_mapping_scale =
652 new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage,
653 ConstantInt::get(IntptrTy, MappingScale),
654 kAsanMappingScaleName);
655 // Read the global, otherwise it may be optimized away.
656 IRB.CreateLoad(asan_mapping_scale, true);
657 }
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000658
659
660 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
661 if (F->isDeclaration()) continue;
662 Res |= handleFunction(M, *F);
663 }
664
Kostya Serebryany7bcfc992011-12-15 21:59:03 +0000665 appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndCtorPriority);
Kostya Serebryany9b027412011-12-12 18:01:46 +0000666
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000667 return Res;
668}
669
Kostya Serebryanya1a8a322012-01-30 23:50:10 +0000670bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {
671 // For each NSObject descendant having a +load method, this method is invoked
672 // by the ObjC runtime before any of the static constructors is called.
673 // Therefore we need to instrument such methods with a call to __asan_init
674 // at the beginning in order to initialize our runtime before any access to
675 // the shadow memory.
676 // We cannot just ignore these methods, because they may call other
677 // instrumented functions.
678 if (F.getName().find(" load]") != std::string::npos) {
679 IRBuilder<> IRB(F.begin()->begin());
680 IRB.CreateCall(AsanInitFunction);
681 return true;
682 }
683 return false;
684}
685
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000686bool AddressSanitizer::handleFunction(Module &M, Function &F) {
687 if (BL->isIn(F)) return false;
688 if (&F == AsanCtorFunction) return false;
Kostya Serebryanya1a8a322012-01-30 23:50:10 +0000689
690 // If needed, insert __asan_init before checking for AddressSafety attr.
691 maybeInsertAsanInitAtFunctionEntry(F);
692
Kostya Serebryany0307b9a2012-01-24 19:34:43 +0000693 if (!F.hasFnAttr(Attribute::AddressSafety)) return false;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000694
695 if (!ClDebugFunc.empty() && ClDebugFunc != F.getName())
696 return false;
697 // We want to instrument every address only once per basic block
698 // (unless there are calls between uses).
699 SmallSet<Value*, 16> TempsToInstrument;
700 SmallVector<Instruction*, 16> ToInstrument;
Kostya Serebryany95e3cf42012-02-08 21:36:17 +0000701 SmallVector<Instruction*, 8> NoReturnCalls;
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +0000702 bool IsWrite;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000703
704 // Fill the set of memory operations to instrument.
705 for (Function::iterator FI = F.begin(), FE = F.end();
706 FI != FE; ++FI) {
707 TempsToInstrument.clear();
Kostya Serebryany324cbb82012-06-28 09:34:41 +0000708 int NumInsnsPerBB = 0;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000709 for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
710 BI != BE; ++BI) {
Kostya Serebryanybcb55ce2012-01-11 18:15:23 +0000711 if (LooksLikeCodeInBug11395(BI)) return false;
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +0000712 if (Value *Addr = isInterestingMemoryAccess(BI, &IsWrite)) {
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000713 if (ClOpt && ClOptSameTemp) {
714 if (!TempsToInstrument.insert(Addr))
715 continue; // We've seen this temp in the current BB.
716 }
717 } else if (isa<MemIntrinsic>(BI) && ClMemIntrin) {
718 // ok, take it.
719 } else {
Kostya Serebryany95e3cf42012-02-08 21:36:17 +0000720 if (CallInst *CI = dyn_cast<CallInst>(BI)) {
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000721 // A call inside BB.
722 TempsToInstrument.clear();
Kostya Serebryany95e3cf42012-02-08 21:36:17 +0000723 if (CI->doesNotReturn()) {
724 NoReturnCalls.push_back(CI);
725 }
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000726 }
727 continue;
728 }
729 ToInstrument.push_back(BI);
Kostya Serebryany324cbb82012-06-28 09:34:41 +0000730 NumInsnsPerBB++;
731 if (NumInsnsPerBB >= ClMaxInsnsToInstrumentPerBB)
732 break;
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000733 }
734 }
735
736 // Instrument.
737 int NumInstrumented = 0;
738 for (size_t i = 0, n = ToInstrument.size(); i != n; i++) {
739 Instruction *Inst = ToInstrument[i];
740 if (ClDebugMin < 0 || ClDebugMax < 0 ||
741 (NumInstrumented >= ClDebugMin && NumInstrumented <= ClDebugMax)) {
Kostya Serebryanye6cf2e02012-05-30 09:04:06 +0000742 if (isInterestingMemoryAccess(Inst, &IsWrite))
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000743 instrumentMop(Inst);
744 else
745 instrumentMemIntrinsic(cast<MemIntrinsic>(Inst));
746 }
747 NumInstrumented++;
748 }
749
750 DEBUG(dbgs() << F);
751
752 bool ChangedStack = poisonStackInFunction(M, F);
Kostya Serebryany95e3cf42012-02-08 21:36:17 +0000753
754 // We must unpoison the stack before every NoReturn call (throw, _exit, etc).
755 // See e.g. http://code.google.com/p/address-sanitizer/issues/detail?id=37
756 for (size_t i = 0, n = NoReturnCalls.size(); i != n; i++) {
757 Instruction *CI = NoReturnCalls[i];
758 IRBuilder<> IRB(CI);
759 IRB.CreateCall(M.getOrInsertFunction(kAsanHandleNoReturnName,
760 IRB.getVoidTy(), NULL));
761 }
762
763 return NumInstrumented > 0 || ChangedStack || !NoReturnCalls.empty();
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000764}
765
766static uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize) {
767 if (ShadowRedzoneSize == 1) return PoisonByte;
768 if (ShadowRedzoneSize == 2) return (PoisonByte << 8) + PoisonByte;
769 if (ShadowRedzoneSize == 4)
770 return (PoisonByte << 24) + (PoisonByte << 16) +
771 (PoisonByte << 8) + (PoisonByte);
Craig Topper85814382012-02-07 05:05:23 +0000772 llvm_unreachable("ShadowRedzoneSize is either 1, 2 or 4");
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000773}
774
775static void PoisonShadowPartialRightRedzone(uint8_t *Shadow,
776 size_t Size,
777 size_t RedzoneSize,
778 size_t ShadowGranularity,
779 uint8_t Magic) {
780 for (size_t i = 0; i < RedzoneSize;
781 i+= ShadowGranularity, Shadow++) {
782 if (i + ShadowGranularity <= Size) {
783 *Shadow = 0; // fully addressable
784 } else if (i >= Size) {
785 *Shadow = Magic; // unaddressable
786 } else {
787 *Shadow = Size - i; // first Size-i bytes are addressable
788 }
789 }
790}
791
792void AddressSanitizer::PoisonStack(const ArrayRef<AllocaInst*> &AllocaVec,
793 IRBuilder<> IRB,
794 Value *ShadowBase, bool DoPoison) {
795 size_t ShadowRZSize = RedzoneSize >> MappingScale;
796 assert(ShadowRZSize >= 1 && ShadowRZSize <= 4);
797 Type *RZTy = Type::getIntNTy(*C, ShadowRZSize * 8);
798 Type *RZPtrTy = PointerType::get(RZTy, 0);
799
800 Value *PoisonLeft = ConstantInt::get(RZTy,
801 ValueForPoison(DoPoison ? kAsanStackLeftRedzoneMagic : 0LL, ShadowRZSize));
802 Value *PoisonMid = ConstantInt::get(RZTy,
803 ValueForPoison(DoPoison ? kAsanStackMidRedzoneMagic : 0LL, ShadowRZSize));
804 Value *PoisonRight = ConstantInt::get(RZTy,
805 ValueForPoison(DoPoison ? kAsanStackRightRedzoneMagic : 0LL, ShadowRZSize));
806
807 // poison the first red zone.
808 IRB.CreateStore(PoisonLeft, IRB.CreateIntToPtr(ShadowBase, RZPtrTy));
809
810 // poison all other red zones.
811 uint64_t Pos = RedzoneSize;
812 for (size_t i = 0, n = AllocaVec.size(); i < n; i++) {
813 AllocaInst *AI = AllocaVec[i];
814 uint64_t SizeInBytes = getAllocaSizeInBytes(AI);
815 uint64_t AlignedSize = getAlignedAllocaSize(AI);
816 assert(AlignedSize - SizeInBytes < RedzoneSize);
817 Value *Ptr = NULL;
818
819 Pos += AlignedSize;
820
821 assert(ShadowBase->getType() == IntptrTy);
822 if (SizeInBytes < AlignedSize) {
823 // Poison the partial redzone at right
824 Ptr = IRB.CreateAdd(
825 ShadowBase, ConstantInt::get(IntptrTy,
826 (Pos >> MappingScale) - ShadowRZSize));
827 size_t AddressableBytes = RedzoneSize - (AlignedSize - SizeInBytes);
828 uint32_t Poison = 0;
829 if (DoPoison) {
830 PoisonShadowPartialRightRedzone((uint8_t*)&Poison, AddressableBytes,
831 RedzoneSize,
832 1ULL << MappingScale,
833 kAsanStackPartialRedzoneMagic);
834 }
835 Value *PartialPoison = ConstantInt::get(RZTy, Poison);
836 IRB.CreateStore(PartialPoison, IRB.CreateIntToPtr(Ptr, RZPtrTy));
837 }
838
839 // Poison the full redzone at right.
840 Ptr = IRB.CreateAdd(ShadowBase,
841 ConstantInt::get(IntptrTy, Pos >> MappingScale));
842 Value *Poison = i == AllocaVec.size() - 1 ? PoisonRight : PoisonMid;
843 IRB.CreateStore(Poison, IRB.CreateIntToPtr(Ptr, RZPtrTy));
844
845 Pos += RedzoneSize;
846 }
847}
848
Kostya Serebryany5a3a9c92011-11-18 01:41:06 +0000849// Workaround for bug 11395: we don't want to instrument stack in functions
850// with large assembly blobs (32-bit only), otherwise reg alloc may crash.
Kostya Serebryanyd2703de2011-11-23 02:10:54 +0000851// FIXME: remove once the bug 11395 is fixed.
Kostya Serebryany5a3a9c92011-11-18 01:41:06 +0000852bool AddressSanitizer::LooksLikeCodeInBug11395(Instruction *I) {
853 if (LongSize != 32) return false;
854 CallInst *CI = dyn_cast<CallInst>(I);
855 if (!CI || !CI->isInlineAsm()) return false;
856 if (CI->getNumArgOperands() <= 5) return false;
857 // We have inline assembly with quite a few arguments.
858 return true;
859}
860
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000861// Find all static Alloca instructions and put
862// poisoned red zones around all of them.
863// Then unpoison everything back before the function returns.
864//
865// Stack poisoning does not play well with exception handling.
866// When an exception is thrown, we essentially bypass the code
867// that unpoisones the stack. This is why the run-time library has
868// to intercept __cxa_throw (as well as longjmp, etc) and unpoison the entire
869// stack in the interceptor. This however does not work inside the
870// actual function which catches the exception. Most likely because the
871// compiler hoists the load of the shadow value somewhere too high.
872// This causes asan to report a non-existing bug on 453.povray.
873// It sounds like an LLVM bug.
874bool AddressSanitizer::poisonStackInFunction(Module &M, Function &F) {
875 if (!ClStack) return false;
876 SmallVector<AllocaInst*, 16> AllocaVec;
877 SmallVector<Instruction*, 8> RetVec;
878 uint64_t TotalSize = 0;
879
880 // Filter out Alloca instructions we want (and can) handle.
881 // Collect Ret instructions.
882 for (Function::iterator FI = F.begin(), FE = F.end();
883 FI != FE; ++FI) {
884 BasicBlock &BB = *FI;
885 for (BasicBlock::iterator BI = BB.begin(), BE = BB.end();
886 BI != BE; ++BI) {
Kostya Serebryany800e03f2011-11-16 01:35:23 +0000887 if (isa<ReturnInst>(BI)) {
888 RetVec.push_back(BI);
889 continue;
890 }
891
892 AllocaInst *AI = dyn_cast<AllocaInst>(BI);
893 if (!AI) continue;
894 if (AI->isArrayAllocation()) continue;
895 if (!AI->isStaticAlloca()) continue;
896 if (!AI->getAllocatedType()->isSized()) continue;
897 if (AI->getAlignment() > RedzoneSize) continue;
898 AllocaVec.push_back(AI);
899 uint64_t AlignedSize = getAlignedAllocaSize(AI);
900 TotalSize += AlignedSize;
901 }
902 }
903
904 if (AllocaVec.empty()) return false;
905
906 uint64_t LocalStackSize = TotalSize + (AllocaVec.size() + 1) * RedzoneSize;
907
908 bool DoStackMalloc = ClUseAfterReturn
909 && LocalStackSize <= kMaxStackMallocSize;
910
911 Instruction *InsBefore = AllocaVec[0];
912 IRBuilder<> IRB(InsBefore);
913
914
915 Type *ByteArrayTy = ArrayType::get(IRB.getInt8Ty(), LocalStackSize);
916 AllocaInst *MyAlloca =
917 new AllocaInst(ByteArrayTy, "MyAlloca", InsBefore);
918 MyAlloca->setAlignment(RedzoneSize);
919 assert(MyAlloca->isStaticAlloca());
920 Value *OrigStackBase = IRB.CreatePointerCast(MyAlloca, IntptrTy);
921 Value *LocalStackBase = OrigStackBase;
922
923 if (DoStackMalloc) {
924 Value *AsanStackMallocFunc = M.getOrInsertFunction(
925 kAsanStackMallocName, IntptrTy, IntptrTy, IntptrTy, NULL);
926 LocalStackBase = IRB.CreateCall2(AsanStackMallocFunc,
927 ConstantInt::get(IntptrTy, LocalStackSize), OrigStackBase);
928 }
929
930 // This string will be parsed by the run-time (DescribeStackAddress).
931 SmallString<2048> StackDescriptionStorage;
932 raw_svector_ostream StackDescription(StackDescriptionStorage);
933 StackDescription << F.getName() << " " << AllocaVec.size() << " ";
934
935 uint64_t Pos = RedzoneSize;
936 // Replace Alloca instructions with base+offset.
937 for (size_t i = 0, n = AllocaVec.size(); i < n; i++) {
938 AllocaInst *AI = AllocaVec[i];
939 uint64_t SizeInBytes = getAllocaSizeInBytes(AI);
940 StringRef Name = AI->getName();
941 StackDescription << Pos << " " << SizeInBytes << " "
942 << Name.size() << " " << Name << " ";
943 uint64_t AlignedSize = getAlignedAllocaSize(AI);
944 assert((AlignedSize % RedzoneSize) == 0);
945 AI->replaceAllUsesWith(
946 IRB.CreateIntToPtr(
947 IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Pos)),
948 AI->getType()));
949 Pos += AlignedSize + RedzoneSize;
950 }
951 assert(Pos == LocalStackSize);
952
953 // Write the Magic value and the frame description constant to the redzone.
954 Value *BasePlus0 = IRB.CreateIntToPtr(LocalStackBase, IntptrPtrTy);
955 IRB.CreateStore(ConstantInt::get(IntptrTy, kCurrentStackFrameMagic),
956 BasePlus0);
957 Value *BasePlus1 = IRB.CreateAdd(LocalStackBase,
958 ConstantInt::get(IntptrTy, LongSize/8));
959 BasePlus1 = IRB.CreateIntToPtr(BasePlus1, IntptrPtrTy);
960 Value *Description = IRB.CreatePointerCast(
961 createPrivateGlobalForString(M, StackDescription.str()),
962 IntptrTy);
963 IRB.CreateStore(Description, BasePlus1);
964
965 // Poison the stack redzones at the entry.
966 Value *ShadowBase = memToShadow(LocalStackBase, IRB);
967 PoisonStack(ArrayRef<AllocaInst*>(AllocaVec), IRB, ShadowBase, true);
968
969 Value *AsanStackFreeFunc = NULL;
970 if (DoStackMalloc) {
971 AsanStackFreeFunc = M.getOrInsertFunction(
972 kAsanStackFreeName, IRB.getVoidTy(),
973 IntptrTy, IntptrTy, IntptrTy, NULL);
974 }
975
976 // Unpoison the stack before all ret instructions.
977 for (size_t i = 0, n = RetVec.size(); i < n; i++) {
978 Instruction *Ret = RetVec[i];
979 IRBuilder<> IRBRet(Ret);
980
981 // Mark the current frame as retired.
982 IRBRet.CreateStore(ConstantInt::get(IntptrTy, kRetiredStackFrameMagic),
983 BasePlus0);
984 // Unpoison the stack.
985 PoisonStack(ArrayRef<AllocaInst*>(AllocaVec), IRBRet, ShadowBase, false);
986
987 if (DoStackMalloc) {
988 IRBRet.CreateCall3(AsanStackFreeFunc, LocalStackBase,
989 ConstantInt::get(IntptrTy, LocalStackSize),
990 OrigStackBase);
991 }
992 }
993
994 if (ClDebugStack) {
995 DEBUG(dbgs() << F);
996 }
997
998 return true;
999}