llvm.org GIT mirror llvm / d47b5b3
Hardware-assisted AddressSanitizer (llvm part). Summary: This is LLVM instrumentation for the new HWASan tool. It is basically a stripped down copy of ASan at this point, w/o stack or global support. Instrumenation adds a global constructor + runtime callbacks for every load and store. HWASan comes with its own IR attribute. A brief design document can be found in clang/docs/HardwareAssistedAddressSanitizerDesign.rst (submitted earlier). Reviewers: kcc, pcc, alekseyshl Subscribers: srhines, mehdi_amini, mgorny, javed.absar, eraman, llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D40932 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320217 91177308-0d34-0410-b5e6-96231b3b80d8 Evgeniy Stepanov 1 year, 10 months ago
30 changed file(s) with 676 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
10531053 * code 52: ``writeonly``
10541054 * code 53: ``speculatable``
10551055 * code 54: ``strictfp``
1056 * code 55: ``sanitize_hwaddress``
10561057
10571058 .. note::
10581059 The ``allocsize`` attribute has a special encoding for its arguments. Its two
15961596 ``sanitize_thread``
15971597 This attribute indicates that ThreadSanitizer checks
15981598 (dynamic thread safety analysis) are enabled for this function.
1599 ``sanitize_hwaddress``
1600 This attribute indicates that HWAddressSanitizer checks
1601 (dynamic address safety analysis based on tagged pointers) are enabled for
1602 this function.
15991603 ``speculatable``
16001604 This function attribute indicates that the function does not have any
16011605 effects besides calculating its result and does not have undefined behavior.
559559 ATTR_KIND_WRITEONLY = 52,
560560 ATTR_KIND_SPECULATABLE = 53,
561561 ATTR_KIND_STRICT_FP = 54,
562 ATTR_KIND_SANITIZE_HWADDRESS = 55,
562563 };
563564
564565 enum ComdatSelectionKindCodes {
162162
163163 /// MemorySanitizer is on.
164164 def SanitizeMemory : EnumAttr<"sanitize_memory">;
165
166 /// HWAddressSanitizer is on.
167 def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">;
165168
166169 /// Argument is swift error.
167170 def SwiftError : EnumAttr<"swifterror">;
199202 def : CompatRule<"isEqual">;
200203 def : CompatRule<"isEqual">;
201204 def : CompatRule<"isEqual">;
205 def : CompatRule<"isEqual">;
202206 def : CompatRule<"isEqual">;
203207
204208 class MergeRule {
359359 void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
360360 void initializeStripSymbolsPass(PassRegistry&);
361361 void initializeStructurizeCFGPass(PassRegistry&);
362 void initializeHWAddressSanitizerPass(PassRegistry&);
362363 void initializeTailCallElimPass(PassRegistry&);
363364 void initializeTailDuplicatePassPass(PassRegistry&);
364365 void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);
131131 // Insert MemorySanitizer instrumentation (detection of uninitialized reads)
132132 FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0,
133133 bool Recover = false);
134
135 FunctionPass *createHWAddressSanitizerPass();
134136
135137 // Insert ThreadSanitizer (race detection) instrumentation
136138 FunctionPass *createThreadSanitizerPass();
305305 return 0;
306306
307307 if (LIOffs + NewLoadByteSize > MemLocEnd &&
308 LI->getParent()->getParent()->hasFnAttribute(
309 Attribute::SanitizeAddress))
308 (LI->getParent()->getParent()->hasFnAttribute(
309 Attribute::SanitizeAddress) ||
310 LI->getParent()->getParent()->hasFnAttribute(
311 Attribute::SanitizeHWAddress)))
310312 // We will be reading past the location accessed by the original program.
311313 // While this is safe in a regular build, Address Safety analysis tools
312314 // may start reporting false warnings. So, don't do widening.
35103510 // Speculative load may create a race that did not exist in the source.
35113511 LI->getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
35123512 // Speculative load may load data from dirty regions.
3513 LI->getFunction()->hasFnAttribute(Attribute::SanitizeAddress))
3513 LI->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
3514 LI->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
35143515 return false;
35153516 const DataLayout &DL = LI->getModule()->getDataLayout();
35163517 return isDereferenceableAndAlignedPointer(LI->getPointerOperand(),
663663 KEYWORD(strictfp);
664664 KEYWORD(safestack);
665665 KEYWORD(sanitize_address);
666 KEYWORD(sanitize_hwaddress);
666667 KEYWORD(sanitize_thread);
667668 KEYWORD(sanitize_memory);
668669 KEYWORD(swifterror);
11431143 case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break;
11441144 case lltok::kw_sanitize_address:
11451145 B.addAttribute(Attribute::SanitizeAddress); break;
1146 case lltok::kw_sanitize_hwaddress:
1147 B.addAttribute(Attribute::SanitizeHWAddress); break;
11461148 case lltok::kw_sanitize_thread:
11471149 B.addAttribute(Attribute::SanitizeThread); break;
11481150 case lltok::kw_sanitize_memory:
14671469 case lltok::kw_optsize:
14681470 case lltok::kw_returns_twice:
14691471 case lltok::kw_sanitize_address:
1472 case lltok::kw_sanitize_hwaddress:
14701473 case lltok::kw_sanitize_memory:
14711474 case lltok::kw_sanitize_thread:
14721475 case lltok::kw_ssp:
15591562 case lltok::kw_optsize:
15601563 case lltok::kw_returns_twice:
15611564 case lltok::kw_sanitize_address:
1565 case lltok::kw_sanitize_hwaddress:
15621566 case lltok::kw_sanitize_memory:
15631567 case lltok::kw_sanitize_thread:
15641568 case lltok::kw_ssp:
171171 kw_alwaysinline,
172172 kw_argmemonly,
173173 kw_sanitize_address,
174 kw_sanitize_hwaddress,
174175 kw_builtin,
175176 kw_byval,
176177 kw_inalloca,
11551155 case Attribute::WriteOnly: return 1ULL << 53;
11561156 case Attribute::Speculatable: return 1ULL << 54;
11571157 case Attribute::StrictFP: return 1ULL << 55;
1158 case Attribute::SanitizeHWAddress: return 1ULL << 56;
11581159 case Attribute::Dereferenceable:
11591160 llvm_unreachable("dereferenceable attribute not supported in raw format");
11601161 break;
13671368 return Attribute::StructRet;
13681369 case bitc::ATTR_KIND_SANITIZE_ADDRESS:
13691370 return Attribute::SanitizeAddress;
1371 case bitc::ATTR_KIND_SANITIZE_HWADDRESS:
1372 return Attribute::SanitizeHWAddress;
13701373 case bitc::ATTR_KIND_SANITIZE_THREAD:
13711374 return Attribute::SanitizeThread;
13721375 case bitc::ATTR_KIND_SANITIZE_MEMORY:
662662 return bitc::ATTR_KIND_STRUCT_RET;
663663 case Attribute::SanitizeAddress:
664664 return bitc::ATTR_KIND_SANITIZE_ADDRESS;
665 case Attribute::SanitizeHWAddress:
666 return bitc::ATTR_KIND_SANITIZE_HWADDRESS;
665667 case Attribute::SanitizeThread:
666668 return bitc::ATTR_KIND_SANITIZE_THREAD;
667669 case Attribute::SanitizeMemory:
557557 switch (EnableShrinkWrapOpt) {
558558 case cl::BOU_UNSET:
559559 return TFI->enableShrinkWrapping(MF) &&
560 // Windows with CFI has some limitations that make it impossible
561 // to use shrink-wrapping.
562 !MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
563 // Sanitizers look at the value of the stack at the location
564 // of the crash. Since a crash can happen anywhere, the
565 // frame must be lowered before anything else happen for the
566 // sanitizers to be able to get a correct stack frame.
567 !(MF.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
568 MF.getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
569 MF.getFunction()->hasFnAttribute(Attribute::SanitizeMemory));
560 // Windows with CFI has some limitations that make it impossible
561 // to use shrink-wrapping.
562 !MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
563 // Sanitizers look at the value of the stack at the location
564 // of the crash. Since a crash can happen anywhere, the
565 // frame must be lowered before anything else happen for the
566 // sanitizers to be able to get a correct stack frame.
567 !(MF.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
568 MF.getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
569 MF.getFunction()->hasFnAttribute(Attribute::SanitizeMemory) ||
570 MF.getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress));
570571 // If EnableShrinkWrap is set, it takes precedence on whatever the
571572 // target sets. The rational is that we assume we want to test
572573 // something related to shrink-wrapping.
244244
245245 if (hasAttribute(Attribute::SanitizeAddress))
246246 return "sanitize_address";
247 if (hasAttribute(Attribute::SanitizeHWAddress))
248 return "sanitize_hwaddress";
247249 if (hasAttribute(Attribute::AlwaysInline))
248250 return "alwaysinline";
249251 if (hasAttribute(Attribute::ArgMemOnly))
13741374 case Attribute::NonLazyBind:
13751375 case Attribute::ReturnsTwice:
13761376 case Attribute::SanitizeAddress:
1377 case Attribute::SanitizeHWAddress:
13771378 case Attribute::SanitizeThread:
13781379 case Attribute::SanitizeMemory:
13791380 case Attribute::MinSize:
5151 .Case("returns_twice", Attribute::ReturnsTwice)
5252 .Case("safestack", Attribute::SafeStack)
5353 .Case("sanitize_address", Attribute::SanitizeAddress)
54 .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
5455 .Case("sanitize_memory", Attribute::SanitizeMemory)
5556 .Case("sanitize_thread", Attribute::SanitizeThread)
5657 .Case("ssp", Attribute::StackProtect)
36063606 case Intrinsic::lifetime_start:
36073607 // Asan needs to poison memory to detect invalid access which is possible
36083608 // even for empty lifetime range.
3609 if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress))
3609 if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
3610 II->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
36103611 break;
36113612
36123613 if (removeTriviallyEmptyRange(*II, Intrinsic::lifetime_start,
1111 SanitizerCoverage.cpp
1212 ThreadSanitizer.cpp
1313 EfficiencySanitizer.cpp
14 HWAddressSanitizer.cpp
1415
1516 ADDITIONAL_HEADER_DIRS
1617 ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
0 //===- HWAddressSanitizer.cpp - detector of uninitialized reads -------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// \file
10 /// This file is a part of HWAddressSanitizer, an address sanity checker
11 /// based on tagged addressing.
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/Triple.h"
18 #include "llvm/IR/Attributes.h"
19 #include "llvm/IR/BasicBlock.h"
20 #include "llvm/IR/Constant.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/DataLayout.h"
23 #include "llvm/IR/DerivedTypes.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/IRBuilder.h"
26 #include "llvm/IR/InlineAsm.h"
27 #include "llvm/IR/InstVisitor.h"
28 #include "llvm/IR/Instruction.h"
29 #include "llvm/IR/Instructions.h"
30 #include "llvm/IR/IntrinsicInst.h"
31 #include "llvm/IR/Intrinsics.h"
32 #include "llvm/IR/LLVMContext.h"
33 #include "llvm/IR/Module.h"
34 #include "llvm/IR/Type.h"
35 #include "llvm/IR/Value.h"
36 #include "llvm/Pass.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Transforms/Instrumentation.h"
41 #include "llvm/Transforms/Utils/ModuleUtils.h"
42
43 using namespace llvm;
44
45 #define DEBUG_TYPE "hwasan"
46
47 static const char *const kHwasanModuleCtorName = "hwasan.module_ctor";
48 static const char *const kHwasanInitName = "__hwasan_init";
49
50 // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
51 static const size_t kNumberOfAccessSizes = 5;
52
53 static cl::opt ClMemoryAccessCallbackPrefix(
54 "hwasan-memory-access-callback-prefix",
55 cl::desc("Prefix for memory access callbacks"), cl::Hidden,
56 cl::init("__hwasan_"));
57
58 static cl::opt ClInstrumentReads("hwasan-instrument-reads",
59 cl::desc("instrument read instructions"),
60 cl::Hidden, cl::init(true));
61
62 static cl::opt ClInstrumentWrites(
63 "hwasan-instrument-writes", cl::desc("instrument write instructions"),
64 cl::Hidden, cl::init(true));
65
66 static cl::opt ClInstrumentAtomics(
67 "hwasan-instrument-atomics",
68 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
69 cl::init(true));
70
71 namespace {
72
73 /// \brief An instrumentation pass implementing detection of addressability bugs
74 /// using tagged pointers.
75 class HWAddressSanitizer : public FunctionPass {
76 public:
77 // Pass identification, replacement for typeid.
78 static char ID;
79
80 HWAddressSanitizer() : FunctionPass(ID) {}
81
82 StringRef getPassName() const override { return "HWAddressSanitizer"; }
83
84 bool runOnFunction(Function &F) override;
85 bool doInitialization(Module &M) override;
86
87 void initializeCallbacks(Module &M);
88 bool instrumentMemAccess(Instruction *I);
89 Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
90 uint64_t *TypeSize, unsigned *Alignment,
91 Value **MaybeMask);
92
93 private:
94 LLVMContext *C;
95 Type *IntptrTy;
96
97 Function *HwasanCtorFunction;
98
99 Function *HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
100 Function *HwasanMemoryAccessCallbackSized[2];
101 };
102
103 } // end anonymous namespace
104
105 char HWAddressSanitizer::ID = 0;
106
107 INITIALIZE_PASS_BEGIN(
108 HWAddressSanitizer, "hwasan",
109 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false)
110 INITIALIZE_PASS_END(
111 HWAddressSanitizer, "hwasan",
112 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false)
113
114 FunctionPass *llvm::createHWAddressSanitizerPass() {
115 return new HWAddressSanitizer();
116 }
117
118 /// \brief Module-level initialization.
119 ///
120 /// inserts a call to __hwasan_init to the module's constructor list.
121 bool HWAddressSanitizer::doInitialization(Module &M) {
122 DEBUG(dbgs() << "Init " << M.getName() << "\n");
123 auto &DL = M.getDataLayout();
124
125 Triple TargetTriple(M.getTargetTriple());
126
127 C = &(M.getContext());
128 IRBuilder<> IRB(*C);
129 IntptrTy = IRB.getIntPtrTy(DL);
130
131 std::tie(HwasanCtorFunction, std::ignore) =
132 createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName,
133 kHwasanInitName,
134 /*InitArgTypes=*/{},
135 /*InitArgs=*/{});
136 appendToGlobalCtors(M, HwasanCtorFunction, 0);
137 return true;
138 }
139
140 void HWAddressSanitizer::initializeCallbacks(Module &M) {
141 IRBuilder<> IRB(*C);
142 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
143 const std::string TypeStr = AccessIsWrite ? "store" : "load";
144
145 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
146 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
147 ClMemoryAccessCallbackPrefix + TypeStr,
148 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false)));
149
150 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
151 AccessSizeIndex++) {
152 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
153 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
154 ClMemoryAccessCallbackPrefix + TypeStr +
155 itostr(1ULL << AccessSizeIndex),
156 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false)));
157 }
158 }
159 }
160
161 Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I,
162 bool *IsWrite,
163 uint64_t *TypeSize,
164 unsigned *Alignment,
165 Value **MaybeMask) {
166 // Skip memory accesses inserted by another instrumentation.
167 if (I->getMetadata("nosanitize")) return nullptr;
168
169 Value *PtrOperand = nullptr;
170 const DataLayout &DL = I->getModule()->getDataLayout();
171 if (LoadInst *LI = dyn_cast(I)) {
172 if (!ClInstrumentReads) return nullptr;
173 *IsWrite = false;
174 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType());
175 *Alignment = LI->getAlignment();
176 PtrOperand = LI->getPointerOperand();
177 } else if (StoreInst *SI = dyn_cast(I)) {
178 if (!ClInstrumentWrites) return nullptr;
179 *IsWrite = true;
180 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType());
181 *Alignment = SI->getAlignment();
182 PtrOperand = SI->getPointerOperand();
183 } else if (AtomicRMWInst *RMW = dyn_cast(I)) {
184 if (!ClInstrumentAtomics) return nullptr;
185 *IsWrite = true;
186 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType());
187 *Alignment = 0;
188 PtrOperand = RMW->getPointerOperand();
189 } else if (AtomicCmpXchgInst *XCHG = dyn_cast(I)) {
190 if (!ClInstrumentAtomics) return nullptr;
191 *IsWrite = true;
192 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType());
193 *Alignment = 0;
194 PtrOperand = XCHG->getPointerOperand();
195 }
196
197 if (PtrOperand) {
198 // Do not instrument acesses from different address spaces; we cannot deal
199 // with them.
200 Type *PtrTy = cast(PtrOperand->getType()->getScalarType());
201 if (PtrTy->getPointerAddressSpace() != 0)
202 return nullptr;
203
204 // Ignore swifterror addresses.
205 // swifterror memory addresses are mem2reg promoted by instruction
206 // selection. As such they cannot have regular uses like an instrumentation
207 // function and it makes no sense to track them as memory.
208 if (PtrOperand->isSwiftError())
209 return nullptr;
210 }
211
212 return PtrOperand;
213 }
214
215 static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
216 size_t Res = countTrailingZeros(TypeSize / 8);
217 assert(Res < kNumberOfAccessSizes);
218 return Res;
219 }
220
221 bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) {
222 DEBUG(dbgs() << "Instrumenting: " << *I << "\n");
223 bool IsWrite = false;
224 unsigned Alignment = 0;
225 uint64_t TypeSize = 0;
226 Value *MaybeMask = nullptr;
227 Value *Addr =
228 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask);
229
230 if (!Addr)
231 return false;
232
233 if (MaybeMask)
234 return false; //FIXME
235
236 IRBuilder<> IRB(I);
237 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
238 if (isPowerOf2_64(TypeSize) &&
239 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1)))) {
240 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
241 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex],
242 AddrLong);
243 } else {
244 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite],
245 {AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8)});
246 }
247
248 return true;
249 }
250
251 bool HWAddressSanitizer::runOnFunction(Function &F) {
252 if (&F == HwasanCtorFunction)
253 return false;
254
255 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress))
256 return false;
257
258 DEBUG(dbgs() << "Function: " << F.getName() << "\n");
259
260 initializeCallbacks(*F.getParent());
261
262 bool Changed = false;
263 SmallVector ToInstrument;
264 for (auto &BB : F) {
265 for (auto &Inst : BB) {
266 Value *MaybeMask = nullptr;
267 bool IsWrite;
268 unsigned Alignment;
269 uint64_t TypeSize;
270 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize,
271 &Alignment, &MaybeMask);
272 if (Addr || isa(Inst))
273 ToInstrument.push_back(&Inst);
274 }
275 }
276
277 for (auto Inst : ToInstrument)
278 Changed |= instrumentMemAccess(Inst);
279
280 return Changed;
281 }
6565 initializePGOMemOPSizeOptLegacyPassPass(Registry);
6666 initializeInstrProfilingLegacyPassPass(Registry);
6767 initializeMemorySanitizerPass(Registry);
68 initializeHWAddressSanitizerPass(Registry);
6869 initializeThreadSanitizerPass(Registry);
6970 initializeSanitizerCoverageModulePass(Registry);
7071 initializeDataFlowSanitizerPass(Registry);
12981298 /// non-local by performing PHI construction.
12991299 bool GVN::processNonLocalLoad(LoadInst *LI) {
13001300 // non-local speculations are not allowed under asan.
1301 if (LI->getParent()->getParent()->hasFnAttribute(Attribute::SanitizeAddress))
1301 if (LI->getParent()->getParent()->hasFnAttribute(
1302 Attribute::SanitizeAddress) ||
1303 LI->getParent()->getParent()->hasFnAttribute(
1304 Attribute::SanitizeHWAddress))
13021305 return false;
13031306
13041307 // Step 1: Find the non-local dependencies of the load.
203203 ; CHECK: define void @f34()
204204 {
205205 call void @nobuiltin() nobuiltin
206 ; CHECK: call void @nobuiltin() #34
206 ; CHECK: call void @nobuiltin() #35
207207 ret void;
208208 }
209209
336336 ; CHECK: define void @f57() #33
337337 define void @f57() speculatable {
338338 ret void
339 }
340
341 ; CHECK: define void @f58() #34
342 define void @f58() sanitize_hwaddress
343 {
344 ret void;
339345 }
340346
341347 ; CHECK: attributes #0 = { noreturn }
372378 ; CHECK: attributes #31 = { allocsize(0,1) }
373379 ; CHECK: attributes #32 = { writeonly }
374380 ; CHECK: attributes #33 = { speculatable }
375 ; CHECK: attributes #34 = { nobuiltin }
381 ; CHECK: attributes #34 = { sanitize_hwaddress }
382 ; CHECK: attributes #35 = { nobuiltin }
0 ; Test basic address sanitizer instrumentation.
1 ;
2 ; RUN: opt < %s -hwasan -S | FileCheck %s
3
4 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
5 target triple = "aarch64--linux-android"
6
7 define void @atomicrmw(i64* %ptr) sanitize_hwaddress {
8 ; CHECK-LABEL: @atomicrmw(
9 ; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64
10 ; CHECK: call void @__hwasan_store8(i64 %[[A]])
11
12 entry:
13 %0 = atomicrmw add i64* %ptr, i64 1 seq_cst
14 ret void
15 }
16
17 define void @cmpxchg(i64* %ptr, i64 %compare_to, i64 %new_value) sanitize_hwaddress {
18 ; CHECK-LABEL: @cmpxchg(
19 ; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64
20 ; CHECK: call void @__hwasan_store8(i64 %[[A]])
21
22 entry:
23 %0 = cmpxchg i64* %ptr, i64 %compare_to, i64 %new_value seq_cst seq_cst
24 ret void
25 }
0 ; Test basic address sanitizer instrumentation.
1 ;
2 ; RUN: opt < %s -hwasan -S | FileCheck %s
3
4 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
5 target triple = "aarch64--linux-android"
6
7 define i8 @test_load8(i8* %a) sanitize_hwaddress {
8 ; CHECK-LABEL: @test_load8(
9 ; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
10 ; CHECK: call void @__hwasan_load1(i64 %[[A]])
11 ; CHECK: %[[B:[^ ]*]] = load i8, i8* %a
12 ; CHECK: ret i8 %[[B]]
13
14 entry:
15 %b = load i8, i8* %a, align 4
16 ret i8 %b
17 }
18
19 define i16 @test_load16(i16* %a) sanitize_hwaddress {
20 ; CHECK-LABEL: @test_load16(
21 ; CHECK: %[[A:[^ ]*]] = ptrtoint i16* %a to i64
22 ; CHECK: call void @__hwasan_load2(i64 %[[A]])
23 ; CHECK: %[[B:[^ ]*]] = load i16, i16* %a
24 ; CHECK: ret i16 %[[B]]
25
26 entry:
27 %b = load i16, i16* %a, align 4
28 ret i16 %b
29 }
30
31 define i32 @test_load32(i32* %a) sanitize_hwaddress {
32 ; CHECK-LABEL: @test_load32(
33 ; CHECK: %[[A:[^ ]*]] = ptrtoint i32* %a to i64
34 ; CHECK: call void @__hwasan_load4(i64 %[[A]])
35 ; CHECK: %[[B:[^ ]*]] = load i32, i32* %a
36 ; CHECK: ret i32 %[[B]]
37
38 entry:
39 %b = load i32, i32* %a, align 4
40 ret i32 %b
41 }
42
43 define i64 @test_load64(i64* %a) sanitize_hwaddress {
44 ; CHECK-LABEL: @test_load64(
45 ; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64
46 ; CHECK: call void @__hwasan_load8(i64 %[[A]])
47 ; CHECK: %[[B:[^ ]*]] = load i64, i64* %a
48 ; CHECK: ret i64 %[[B]]
49
50 entry:
51 %b = load i64, i64* %a, align 8
52 ret i64 %b
53 }
54
55 define i128 @test_load128(i128* %a) sanitize_hwaddress {
56 ; CHECK-LABEL: @test_load128(
57 ; CHECK: %[[A:[^ ]*]] = ptrtoint i128* %a to i64
58 ; CHECK: call void @__hwasan_load16(i64 %[[A]])
59 ; CHECK: %[[B:[^ ]*]] = load i128, i128* %a
60 ; CHECK: ret i128 %[[B]]
61
62 entry:
63 %b = load i128, i128* %a, align 16
64 ret i128 %b
65 }
66
67 define i40 @test_load40(i40* %a) sanitize_hwaddress {
68 ; CHECK-LABEL: @test_load40(
69 ; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
70 ; CHECK: call void @__hwasan_load(i64 %[[A]], i64 5)
71 ; CHECK: %[[B:[^ ]*]] = load i40, i40* %a
72 ; CHECK: ret i40 %[[B]]
73
74 entry:
75 %b = load i40, i40* %a, align 4
76 ret i40 %b
77 }
78
79 define void @test_store8(i8* %a, i8 %b) sanitize_hwaddress {
80 ; CHECK-LABEL: @test_store8(
81 ; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
82 ; CHECK: call void @__hwasan_store1(i64 %[[A]])
83 ; CHECK: store i8 %b, i8* %a
84 ; CHECK: ret void
85
86 entry:
87 store i8 %b, i8* %a, align 4
88 ret void
89 }
90
91 define void @test_store16(i16* %a, i16 %b) sanitize_hwaddress {
92 ; CHECK-LABEL: @test_store16(
93 ; CHECK: %[[A:[^ ]*]] = ptrtoint i16* %a to i64
94 ; CHECK: call void @__hwasan_store2(i64 %[[A]])
95 ; CHECK: store i16 %b, i16* %a
96 ; CHECK: ret void
97
98 entry:
99 store i16 %b, i16* %a, align 4
100 ret void
101 }
102
103 define void @test_store32(i32* %a, i32 %b) sanitize_hwaddress {
104 ; CHECK-LABEL: @test_store32(
105 ; CHECK: %[[A:[^ ]*]] = ptrtoint i32* %a to i64
106 ; CHECK: call void @__hwasan_store4(i64 %[[A]])
107 ; CHECK: store i32 %b, i32* %a
108 ; CHECK: ret void
109
110 entry:
111 store i32 %b, i32* %a, align 4
112 ret void
113 }
114
115 define void @test_store64(i64* %a, i64 %b) sanitize_hwaddress {
116 ; CHECK-LABEL: @test_store64(
117 ; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64
118 ; CHECK: call void @__hwasan_store8(i64 %[[A]])
119 ; CHECK: store i64 %b, i64* %a
120 ; CHECK: ret void
121
122 entry:
123 store i64 %b, i64* %a, align 4
124 ret void
125 }
126
127 define void @test_store128(i128* %a, i128 %b) sanitize_hwaddress {
128 ; CHECK-LABEL: @test_store128(
129 ; CHECK: %[[A:[^ ]*]] = ptrtoint i128* %a to i64
130 ; CHECK: call void @__hwasan_store16(i64 %[[A]])
131 ; CHECK: store i128 %b, i128* %a
132 ; CHECK: ret void
133
134 entry:
135 store i128 %b, i128* %a, align 4
136 ret void
137 }
138
139 define void @test_store40(i40* %a, i40 %b) sanitize_hwaddress {
140 ; CHECK-LABEL: @test_store40(
141 ; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
142 ; CHECK: call void @__hwasan_store(i64 %[[A]], i64 5)
143 ; CHECK: store i40 %b, i40* %a
144 ; CHECK: ret void
145
146 entry:
147 store i40 %b, i40* %a, align 4
148 ret void
149 }
150
151 define i8 @test_load_noattr(i8* %a) {
152 ; CHECK-LABEL: @test_load_noattr(
153 ; CHECK-NEXT: entry:
154 ; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8* %a
155 ; CHECK-NEXT: ret i8 %[[B]]
156
157 entry:
158 %b = load i8, i8* %a, align 4
159 ret i8 %b
160 }
161
162 define i8 @test_load_notmyattr(i8* %a) sanitize_address {
163 ; CHECK-LABEL: @test_load_notmyattr(
164 ; CHECK-NEXT: entry:
165 ; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8* %a
166 ; CHECK-NEXT: ret i8 %[[B]]
167
168 entry:
169 %b = load i8, i8* %a, align 4
170 ret i8 %b
171 }
172
173 define i8 @test_load_addrspace(i8 addrspace(256)* %a) sanitize_hwaddress {
174 ; CHECK-LABEL: @test_load_addrspace(
175 ; CHECK-NEXT: entry:
176 ; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8 addrspace(256)* %a
177 ; CHECK-NEXT: ret i8 %[[B]]
178
179 entry:
180 %b = load i8, i8 addrspace(256)* %a, align 4
181 ret i8 %b
182 }
183
184 ; CHECK: declare void @__hwasan_init()
185
186 ; CHECK: define internal void @hwasan.module_ctor() {
187 ; CHECK-NEXT: call void @__hwasan_init()
188 ; CHECK-NEXT: ret void
189 ; CHECK-NEXT: }
5252 ; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
5353 ; CHECK: {{.*}} = phi
5454
55
56 define i32 @TestHWAsan() sanitize_hwaddress {
57 %1 = tail call noalias i8* @_Znam(i64 2)
58 %2 = getelementptr inbounds i8, i8* %1, i64 1
59 store i8 0, i8* %2, align 1
60 store i8 0, i8* %1, align 1
61 %3 = bitcast i8* %1 to i16*
62 %4 = load i16, i16* %3, align 4
63 %5 = icmp eq i16 %4, 0
64 br i1 %5, label %11, label %6
65
66 ;
67 %7 = getelementptr inbounds i8, i8* %1, i64 2
68 %8 = bitcast i8* %7 to i16*
69 %9 = load i16, i16* %8, align 2
70 %10 = sext i16 %9 to i32
71 br label %11
72
73 ;
74 %12 = phi i32 [ %10, %6 ], [ 0, %0 ]
75 ret i32 %12
76 }
77
78 ; CHECK-LABEL: @TestHWAsan
79 ; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
80 ; CHECK: {{.*}} = phi
81
99 ret i32 %i
1010 }
1111
12 define i32 @sanitize_hwaddress_callee(i32 %i) sanitize_hwaddress {
13 ret i32 %i
14 }
15
1216 define i32 @sanitize_thread_callee(i32 %i) sanitize_thread {
1317 ret i32 %i
1418 }
2630 }
2731
2832 define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address {
33 ret i32 %i
34 }
35
36 define i32 @alwaysinline_sanitize_hwaddress_callee(i32 %i) alwaysinline sanitize_hwaddress {
2937 ret i32 %i
3038 }
3139
5866 ; CHECK-NEXT: ret i32
5967 }
6068
69 define i32 @test_no_sanitize_hwaddress(i32 %arg) {
70 %x1 = call i32 @noattr_callee(i32 %arg)
71 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
72 %x3 = call i32 @alwaysinline_callee(i32 %x2)
73 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
74 ret i32 %x4
75 ; CHECK-LABEL: @test_no_sanitize_hwaddress(
76 ; CHECK-NEXT: @sanitize_hwaddress_callee
77 ; CHECK-NEXT: ret i32
78 }
79
6180 define i32 @test_no_sanitize_memory(i32 %arg) {
6281 %x1 = call i32 @noattr_callee(i32 %arg)
6382 %x2 = call i32 @sanitize_memory_callee(i32 %x1)
97116 ; CHECK-NEXT: ret i32
98117 }
99118
119 define i32 @test_sanitize_hwaddress(i32 %arg) sanitize_hwaddress {
120 %x1 = call i32 @noattr_callee(i32 %arg)
121 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
122 %x3 = call i32 @alwaysinline_callee(i32 %x2)
123 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
124 ret i32 %x4
125 ; CHECK-LABEL: @test_sanitize_hwaddress(
126 ; CHECK-NEXT: @noattr_callee
127 ; CHECK-NEXT: ret i32
128 }
129
100130 define i32 @test_sanitize_memory(i32 %arg) sanitize_memory {
101131 %x1 = call i32 @noattr_callee(i32 %arg)
102132 %x2 = call i32 @sanitize_memory_callee(i32 %x1)
1818 ret void
1919 }
2020
21 define void @hwasan() sanitize_hwaddress {
22 entry:
23 ; CHECK-LABEL: @hwasan(
24 %text = alloca i8, align 1
25
26 call void @llvm.lifetime.start.p0i8(i64 1, i8* %text)
27 call void @llvm.lifetime.end.p0i8(i64 1, i8* %text)
28 ; CHECK: call void @llvm.lifetime.start
29 ; CHECK-NEXT: call void @llvm.lifetime.end
30
31 call void @foo(i8* %text) ; Keep alloca alive
32
33 ret void
34 }
2135
2236 define void @no_asan() {
2337 entry:
5252 ; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
5353 ; CHECK: {{.*}} = phi
5454
55 define i32 @TestHWAsan() sanitize_hwaddress {
56 %1 = tail call noalias i8* @_Znam(i64 2)
57 %2 = getelementptr inbounds i8, i8* %1, i64 1
58 store i8 0, i8* %2, align 1
59 store i8 0, i8* %1, align 1
60 %3 = bitcast i8* %1 to i16*
61 %4 = load i16, i16* %3, align 4
62 %5 = icmp eq i16 %4, 0
63 br i1 %5, label %11, label %6
64
65 ;
66 %7 = getelementptr inbounds i8, i8* %1, i64 2
67 %8 = bitcast i8* %7 to i16*
68 %9 = load i16, i16* %8, align 2
69 %10 = sext i16 %9 to i32
70 br label %11
71
72 ;
73 %12 = phi i32 [ %10, %6 ], [ 0, %0 ]
74 ret i32 %12
75 }
76
77 ; CHECK-LABEL: @TestHWAsan
78 ; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
79 ; CHECK: {{.*}} = phi
80
3737 ; CHECK: br label
3838 ; CHECK: ret i32
3939 }
40
41 define i32 @TestHWAsan(i32 %cond) nounwind readonly uwtable sanitize_hwaddress {
42 entry:
43 %tobool = icmp eq i32 %cond, 0
44 br i1 %tobool, label %return, label %if.then
45
46 if.then: ; preds = %entry
47 %0 = load i32, i32* @g, align 4
48 br label %return
49
50 return: ; preds = %entry, %if.then
51 %retval = phi i32 [ %0, %if.then ], [ 0, %entry ]
52 ret i32 %retval
53 ; CHECK-LABEL: @TestHWAsan
54 ; CHECK: br i1
55 ; CHECK: load i32, i32* @g
56 ; CHECK: br label
57 ; CHECK: ret i32
58 }