/src/llvm-project/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- AddressSanitizer.cpp - memory error detector -----------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file is a part of AddressSanitizer, an address basic correctness |
10 | | // checker. |
11 | | // Details of the algorithm: |
12 | | // https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm |
13 | | // |
14 | | // FIXME: This sanitizer does not yet handle scalable vectors |
15 | | // |
16 | | //===----------------------------------------------------------------------===// |
17 | | |
18 | | #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" |
19 | | #include "llvm/ADT/ArrayRef.h" |
20 | | #include "llvm/ADT/DenseMap.h" |
21 | | #include "llvm/ADT/DepthFirstIterator.h" |
22 | | #include "llvm/ADT/SmallPtrSet.h" |
23 | | #include "llvm/ADT/SmallVector.h" |
24 | | #include "llvm/ADT/Statistic.h" |
25 | | #include "llvm/ADT/StringExtras.h" |
26 | | #include "llvm/ADT/StringRef.h" |
27 | | #include "llvm/ADT/Twine.h" |
28 | | #include "llvm/Analysis/GlobalsModRef.h" |
29 | | #include "llvm/Analysis/MemoryBuiltins.h" |
30 | | #include "llvm/Analysis/StackSafetyAnalysis.h" |
31 | | #include "llvm/Analysis/TargetLibraryInfo.h" |
32 | | #include "llvm/Analysis/ValueTracking.h" |
33 | | #include "llvm/BinaryFormat/MachO.h" |
34 | | #include "llvm/Demangle/Demangle.h" |
35 | | #include "llvm/IR/Argument.h" |
36 | | #include "llvm/IR/Attributes.h" |
37 | | #include "llvm/IR/BasicBlock.h" |
38 | | #include "llvm/IR/Comdat.h" |
39 | | #include "llvm/IR/Constant.h" |
40 | | #include "llvm/IR/Constants.h" |
41 | | #include "llvm/IR/DIBuilder.h" |
42 | | #include "llvm/IR/DataLayout.h" |
43 | | #include "llvm/IR/DebugInfoMetadata.h" |
44 | | #include "llvm/IR/DebugLoc.h" |
45 | | #include "llvm/IR/DerivedTypes.h" |
46 | | #include "llvm/IR/Function.h" |
47 | | #include "llvm/IR/GlobalAlias.h" |
48 | | #include "llvm/IR/GlobalValue.h" |
49 | | #include "llvm/IR/GlobalVariable.h" |
50 | | #include "llvm/IR/IRBuilder.h" |
51 | | #include "llvm/IR/InlineAsm.h" |
52 | | #include "llvm/IR/InstVisitor.h" |
53 | | #include "llvm/IR/InstrTypes.h" |
54 | | #include "llvm/IR/Instruction.h" |
55 | | #include "llvm/IR/Instructions.h" |
56 | | #include "llvm/IR/IntrinsicInst.h" |
57 | | #include "llvm/IR/Intrinsics.h" |
58 | | #include "llvm/IR/LLVMContext.h" |
59 | | #include "llvm/IR/MDBuilder.h" |
60 | | #include "llvm/IR/Metadata.h" |
61 | | #include "llvm/IR/Module.h" |
62 | | #include "llvm/IR/Type.h" |
63 | | #include "llvm/IR/Use.h" |
64 | | #include "llvm/IR/Value.h" |
65 | | #include "llvm/MC/MCSectionMachO.h" |
66 | | #include "llvm/Support/Casting.h" |
67 | | #include "llvm/Support/CommandLine.h" |
68 | | #include "llvm/Support/Debug.h" |
69 | | #include "llvm/Support/ErrorHandling.h" |
70 | | #include "llvm/Support/MathExtras.h" |
71 | | #include "llvm/Support/raw_ostream.h" |
72 | | #include "llvm/TargetParser/Triple.h" |
73 | | #include "llvm/Transforms/Instrumentation.h" |
74 | | #include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h" |
75 | | #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h" |
76 | | #include "llvm/Transforms/Utils/ASanStackFrameLayout.h" |
77 | | #include "llvm/Transforms/Utils/BasicBlockUtils.h" |
78 | | #include "llvm/Transforms/Utils/Local.h" |
79 | | #include "llvm/Transforms/Utils/ModuleUtils.h" |
80 | | #include "llvm/Transforms/Utils/PromoteMemToReg.h" |
81 | | #include <algorithm> |
82 | | #include <cassert> |
83 | | #include <cstddef> |
84 | | #include <cstdint> |
85 | | #include <iomanip> |
86 | | #include <limits> |
87 | | #include <sstream> |
88 | | #include <string> |
89 | | #include <tuple> |
90 | | |
91 | | using namespace llvm; |
92 | | |
93 | | #define DEBUG_TYPE "asan" |
94 | | |
95 | | static const uint64_t kDefaultShadowScale = 3; |
96 | | static const uint64_t kDefaultShadowOffset32 = 1ULL << 29; |
97 | | static const uint64_t kDefaultShadowOffset64 = 1ULL << 44; |
98 | | static const uint64_t kDynamicShadowSentinel = |
99 | | std::numeric_limits<uint64_t>::max(); |
100 | | static const uint64_t kSmallX86_64ShadowOffsetBase = 0x7FFFFFFF; // < 2G. |
101 | | static const uint64_t kSmallX86_64ShadowOffsetAlignMask = ~0xFFFULL; |
102 | | static const uint64_t kLinuxKasan_ShadowOffset64 = 0xdffffc0000000000; |
103 | | static const uint64_t kPPC64_ShadowOffset64 = 1ULL << 44; |
104 | | static const uint64_t kSystemZ_ShadowOffset64 = 1ULL << 52; |
105 | | static const uint64_t kMIPS_ShadowOffsetN32 = 1ULL << 29; |
106 | | static const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa0000; |
107 | | static const uint64_t kMIPS64_ShadowOffset64 = 1ULL << 37; |
108 | | static const uint64_t kAArch64_ShadowOffset64 = 1ULL << 36; |
109 | | static const uint64_t kLoongArch64_ShadowOffset64 = 1ULL << 46; |
110 | | static const uint64_t kRISCV64_ShadowOffset64 = 0xd55550000; |
111 | | static const uint64_t kFreeBSD_ShadowOffset32 = 1ULL << 30; |
112 | | static const uint64_t kFreeBSD_ShadowOffset64 = 1ULL << 46; |
113 | | static const uint64_t kFreeBSDAArch64_ShadowOffset64 = 1ULL << 47; |
114 | | static const uint64_t kFreeBSDKasan_ShadowOffset64 = 0xdffff7c000000000; |
115 | | static const uint64_t kNetBSD_ShadowOffset32 = 1ULL << 30; |
116 | | static const uint64_t kNetBSD_ShadowOffset64 = 1ULL << 46; |
117 | | static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff900000000000; |
118 | | static const uint64_t kPS_ShadowOffset64 = 1ULL << 40; |
119 | | static const uint64_t kWindowsShadowOffset32 = 3ULL << 28; |
120 | | static const uint64_t kEmscriptenShadowOffset = 0; |
121 | | |
122 | | // The shadow memory space is dynamically allocated. |
123 | | static const uint64_t kWindowsShadowOffset64 = kDynamicShadowSentinel; |
124 | | |
125 | | static const size_t kMinStackMallocSize = 1 << 6; // 64B |
126 | | static const size_t kMaxStackMallocSize = 1 << 16; // 64K |
127 | | static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3; |
128 | | static const uintptr_t kRetiredStackFrameMagic = 0x45E0360E; |
129 | | |
130 | | const char kAsanModuleCtorName[] = "asan.module_ctor"; |
131 | | const char kAsanModuleDtorName[] = "asan.module_dtor"; |
132 | | static const uint64_t kAsanCtorAndDtorPriority = 1; |
133 | | // On Emscripten, the system needs more than one priorities for constructors. |
134 | | static const uint64_t kAsanEmscriptenCtorAndDtorPriority = 50; |
135 | | const char kAsanReportErrorTemplate[] = "__asan_report_"; |
136 | | const char kAsanRegisterGlobalsName[] = "__asan_register_globals"; |
137 | | const char kAsanUnregisterGlobalsName[] = "__asan_unregister_globals"; |
138 | | const char kAsanRegisterImageGlobalsName[] = "__asan_register_image_globals"; |
139 | | const char kAsanUnregisterImageGlobalsName[] = |
140 | | "__asan_unregister_image_globals"; |
141 | | const char kAsanRegisterElfGlobalsName[] = "__asan_register_elf_globals"; |
142 | | const char kAsanUnregisterElfGlobalsName[] = "__asan_unregister_elf_globals"; |
143 | | const char kAsanPoisonGlobalsName[] = "__asan_before_dynamic_init"; |
144 | | const char kAsanUnpoisonGlobalsName[] = "__asan_after_dynamic_init"; |
145 | | const char kAsanInitName[] = "__asan_init"; |
146 | | const char kAsanVersionCheckNamePrefix[] = "__asan_version_mismatch_check_v"; |
147 | | const char kAsanPtrCmp[] = "__sanitizer_ptr_cmp"; |
148 | | const char kAsanPtrSub[] = "__sanitizer_ptr_sub"; |
149 | | const char kAsanHandleNoReturnName[] = "__asan_handle_no_return"; |
150 | | static const int kMaxAsanStackMallocSizeClass = 10; |
151 | | const char kAsanStackMallocNameTemplate[] = "__asan_stack_malloc_"; |
152 | | const char kAsanStackMallocAlwaysNameTemplate[] = |
153 | | "__asan_stack_malloc_always_"; |
154 | | const char kAsanStackFreeNameTemplate[] = "__asan_stack_free_"; |
155 | | const char kAsanGenPrefix[] = "___asan_gen_"; |
156 | | const char kODRGenPrefix[] = "__odr_asan_gen_"; |
157 | | const char kSanCovGenPrefix[] = "__sancov_gen_"; |
158 | | const char kAsanSetShadowPrefix[] = "__asan_set_shadow_"; |
159 | | const char kAsanPoisonStackMemoryName[] = "__asan_poison_stack_memory"; |
160 | | const char kAsanUnpoisonStackMemoryName[] = "__asan_unpoison_stack_memory"; |
161 | | |
162 | | // ASan version script has __asan_* wildcard. Triple underscore prevents a |
163 | | // linker (gold) warning about attempting to export a local symbol. |
164 | | const char kAsanGlobalsRegisteredFlagName[] = "___asan_globals_registered"; |
165 | | |
166 | | const char kAsanOptionDetectUseAfterReturn[] = |
167 | | "__asan_option_detect_stack_use_after_return"; |
168 | | |
169 | | const char kAsanShadowMemoryDynamicAddress[] = |
170 | | "__asan_shadow_memory_dynamic_address"; |
171 | | |
172 | | const char kAsanAllocaPoison[] = "__asan_alloca_poison"; |
173 | | const char kAsanAllocasUnpoison[] = "__asan_allocas_unpoison"; |
174 | | |
175 | | const char kAMDGPUAddressSharedName[] = "llvm.amdgcn.is.shared"; |
176 | | const char kAMDGPUAddressPrivateName[] = "llvm.amdgcn.is.private"; |
177 | | const char kAMDGPUBallotName[] = "llvm.amdgcn.ballot.i64"; |
178 | | const char kAMDGPUUnreachableName[] = "llvm.amdgcn.unreachable"; |
179 | | |
180 | | // Accesses sizes are powers of two: 1, 2, 4, 8, 16. |
181 | | static const size_t kNumberOfAccessSizes = 5; |
182 | | |
183 | | static const uint64_t kAllocaRzSize = 32; |
184 | | |
185 | | // ASanAccessInfo implementation constants. |
186 | | constexpr size_t kCompileKernelShift = 0; |
187 | | constexpr size_t kCompileKernelMask = 0x1; |
188 | | constexpr size_t kAccessSizeIndexShift = 1; |
189 | | constexpr size_t kAccessSizeIndexMask = 0xf; |
190 | | constexpr size_t kIsWriteShift = 5; |
191 | | constexpr size_t kIsWriteMask = 0x1; |
192 | | |
193 | | // Command-line flags. |
194 | | |
195 | | static cl::opt<bool> ClEnableKasan( |
196 | | "asan-kernel", cl::desc("Enable KernelAddressSanitizer instrumentation"), |
197 | | cl::Hidden, cl::init(false)); |
198 | | |
199 | | static cl::opt<bool> ClRecover( |
200 | | "asan-recover", |
201 | | cl::desc("Enable recovery mode (continue-after-error)."), |
202 | | cl::Hidden, cl::init(false)); |
203 | | |
204 | | static cl::opt<bool> ClInsertVersionCheck( |
205 | | "asan-guard-against-version-mismatch", |
206 | | cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden, |
207 | | cl::init(true)); |
208 | | |
209 | | // This flag may need to be replaced with -f[no-]asan-reads. |
210 | | static cl::opt<bool> ClInstrumentReads("asan-instrument-reads", |
211 | | cl::desc("instrument read instructions"), |
212 | | cl::Hidden, cl::init(true)); |
213 | | |
214 | | static cl::opt<bool> ClInstrumentWrites( |
215 | | "asan-instrument-writes", cl::desc("instrument write instructions"), |
216 | | cl::Hidden, cl::init(true)); |
217 | | |
218 | | static cl::opt<bool> |
219 | | ClUseStackSafety("asan-use-stack-safety", cl::Hidden, cl::init(true), |
220 | | cl::Hidden, cl::desc("Use Stack Safety analysis results"), |
221 | | cl::Optional); |
222 | | |
223 | | static cl::opt<bool> ClInstrumentAtomics( |
224 | | "asan-instrument-atomics", |
225 | | cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, |
226 | | cl::init(true)); |
227 | | |
228 | | static cl::opt<bool> |
229 | | ClInstrumentByval("asan-instrument-byval", |
230 | | cl::desc("instrument byval call arguments"), cl::Hidden, |
231 | | cl::init(true)); |
232 | | |
233 | | static cl::opt<bool> ClAlwaysSlowPath( |
234 | | "asan-always-slow-path", |
235 | | cl::desc("use instrumentation with slow path for all accesses"), cl::Hidden, |
236 | | cl::init(false)); |
237 | | |
238 | | static cl::opt<bool> ClForceDynamicShadow( |
239 | | "asan-force-dynamic-shadow", |
240 | | cl::desc("Load shadow address into a local variable for each function"), |
241 | | cl::Hidden, cl::init(false)); |
242 | | |
243 | | static cl::opt<bool> |
244 | | ClWithIfunc("asan-with-ifunc", |
245 | | cl::desc("Access dynamic shadow through an ifunc global on " |
246 | | "platforms that support this"), |
247 | | cl::Hidden, cl::init(true)); |
248 | | |
249 | | static cl::opt<bool> ClWithIfuncSuppressRemat( |
250 | | "asan-with-ifunc-suppress-remat", |
251 | | cl::desc("Suppress rematerialization of dynamic shadow address by passing " |
252 | | "it through inline asm in prologue."), |
253 | | cl::Hidden, cl::init(true)); |
254 | | |
255 | | // This flag limits the number of instructions to be instrumented |
256 | | // in any given BB. Normally, this should be set to unlimited (INT_MAX), |
257 | | // but due to http://llvm.org/bugs/show_bug.cgi?id=12652 we temporary |
258 | | // set it to 10000. |
259 | | static cl::opt<int> ClMaxInsnsToInstrumentPerBB( |
260 | | "asan-max-ins-per-bb", cl::init(10000), |
261 | | cl::desc("maximal number of instructions to instrument in any given BB"), |
262 | | cl::Hidden); |
263 | | |
264 | | // This flag may need to be replaced with -f[no]asan-stack. |
265 | | static cl::opt<bool> ClStack("asan-stack", cl::desc("Handle stack memory"), |
266 | | cl::Hidden, cl::init(true)); |
267 | | static cl::opt<uint32_t> ClMaxInlinePoisoningSize( |
268 | | "asan-max-inline-poisoning-size", |
269 | | cl::desc( |
270 | | "Inline shadow poisoning for blocks up to the given size in bytes."), |
271 | | cl::Hidden, cl::init(64)); |
272 | | |
273 | | static cl::opt<AsanDetectStackUseAfterReturnMode> ClUseAfterReturn( |
274 | | "asan-use-after-return", |
275 | | cl::desc("Sets the mode of detection for stack-use-after-return."), |
276 | | cl::values( |
277 | | clEnumValN(AsanDetectStackUseAfterReturnMode::Never, "never", |
278 | | "Never detect stack use after return."), |
279 | | clEnumValN( |
280 | | AsanDetectStackUseAfterReturnMode::Runtime, "runtime", |
281 | | "Detect stack use after return if " |
282 | | "binary flag 'ASAN_OPTIONS=detect_stack_use_after_return' is set."), |
283 | | clEnumValN(AsanDetectStackUseAfterReturnMode::Always, "always", |
284 | | "Always detect stack use after return.")), |
285 | | cl::Hidden, cl::init(AsanDetectStackUseAfterReturnMode::Runtime)); |
286 | | |
287 | | static cl::opt<bool> ClRedzoneByvalArgs("asan-redzone-byval-args", |
288 | | cl::desc("Create redzones for byval " |
289 | | "arguments (extra copy " |
290 | | "required)"), cl::Hidden, |
291 | | cl::init(true)); |
292 | | |
293 | | static cl::opt<bool> ClUseAfterScope("asan-use-after-scope", |
294 | | cl::desc("Check stack-use-after-scope"), |
295 | | cl::Hidden, cl::init(false)); |
296 | | |
297 | | // This flag may need to be replaced with -f[no]asan-globals. |
298 | | static cl::opt<bool> ClGlobals("asan-globals", |
299 | | cl::desc("Handle global objects"), cl::Hidden, |
300 | | cl::init(true)); |
301 | | |
302 | | static cl::opt<bool> ClInitializers("asan-initialization-order", |
303 | | cl::desc("Handle C++ initializer order"), |
304 | | cl::Hidden, cl::init(true)); |
305 | | |
306 | | static cl::opt<bool> ClInvalidPointerPairs( |
307 | | "asan-detect-invalid-pointer-pair", |
308 | | cl::desc("Instrument <, <=, >, >=, - with pointer operands"), cl::Hidden, |
309 | | cl::init(false)); |
310 | | |
311 | | static cl::opt<bool> ClInvalidPointerCmp( |
312 | | "asan-detect-invalid-pointer-cmp", |
313 | | cl::desc("Instrument <, <=, >, >= with pointer operands"), cl::Hidden, |
314 | | cl::init(false)); |
315 | | |
316 | | static cl::opt<bool> ClInvalidPointerSub( |
317 | | "asan-detect-invalid-pointer-sub", |
318 | | cl::desc("Instrument - operations with pointer operands"), cl::Hidden, |
319 | | cl::init(false)); |
320 | | |
321 | | static cl::opt<unsigned> ClRealignStack( |
322 | | "asan-realign-stack", |
323 | | cl::desc("Realign stack to the value of this flag (power of two)"), |
324 | | cl::Hidden, cl::init(32)); |
325 | | |
326 | | static cl::opt<int> ClInstrumentationWithCallsThreshold( |
327 | | "asan-instrumentation-with-call-threshold", |
328 | | cl::desc("If the function being instrumented contains more than " |
329 | | "this number of memory accesses, use callbacks instead of " |
330 | | "inline checks (-1 means never use callbacks)."), |
331 | | cl::Hidden, cl::init(7000)); |
332 | | |
333 | | static cl::opt<std::string> ClMemoryAccessCallbackPrefix( |
334 | | "asan-memory-access-callback-prefix", |
335 | | cl::desc("Prefix for memory access callbacks"), cl::Hidden, |
336 | | cl::init("__asan_")); |
337 | | |
338 | | static cl::opt<bool> ClKasanMemIntrinCallbackPrefix( |
339 | | "asan-kernel-mem-intrinsic-prefix", |
340 | | cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, |
341 | | cl::init(false)); |
342 | | |
343 | | static cl::opt<bool> |
344 | | ClInstrumentDynamicAllocas("asan-instrument-dynamic-allocas", |
345 | | cl::desc("instrument dynamic allocas"), |
346 | | cl::Hidden, cl::init(true)); |
347 | | |
348 | | static cl::opt<bool> ClSkipPromotableAllocas( |
349 | | "asan-skip-promotable-allocas", |
350 | | cl::desc("Do not instrument promotable allocas"), cl::Hidden, |
351 | | cl::init(true)); |
352 | | |
353 | | static cl::opt<AsanCtorKind> ClConstructorKind( |
354 | | "asan-constructor-kind", |
355 | | cl::desc("Sets the ASan constructor kind"), |
356 | | cl::values(clEnumValN(AsanCtorKind::None, "none", "No constructors"), |
357 | | clEnumValN(AsanCtorKind::Global, "global", |
358 | | "Use global constructors")), |
359 | | cl::init(AsanCtorKind::Global), cl::Hidden); |
360 | | // These flags allow to change the shadow mapping. |
361 | | // The shadow mapping looks like |
362 | | // Shadow = (Mem >> scale) + offset |
363 | | |
364 | | static cl::opt<int> ClMappingScale("asan-mapping-scale", |
365 | | cl::desc("scale of asan shadow mapping"), |
366 | | cl::Hidden, cl::init(0)); |
367 | | |
368 | | static cl::opt<uint64_t> |
369 | | ClMappingOffset("asan-mapping-offset", |
370 | | cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"), |
371 | | cl::Hidden, cl::init(0)); |
372 | | |
373 | | // Optimization flags. Not user visible, used mostly for testing |
374 | | // and benchmarking the tool. |
375 | | |
376 | | static cl::opt<bool> ClOpt("asan-opt", cl::desc("Optimize instrumentation"), |
377 | | cl::Hidden, cl::init(true)); |
378 | | |
379 | | static cl::opt<bool> ClOptimizeCallbacks("asan-optimize-callbacks", |
380 | | cl::desc("Optimize callbacks"), |
381 | | cl::Hidden, cl::init(false)); |
382 | | |
383 | | static cl::opt<bool> ClOptSameTemp( |
384 | | "asan-opt-same-temp", cl::desc("Instrument the same temp just once"), |
385 | | cl::Hidden, cl::init(true)); |
386 | | |
387 | | static cl::opt<bool> ClOptGlobals("asan-opt-globals", |
388 | | cl::desc("Don't instrument scalar globals"), |
389 | | cl::Hidden, cl::init(true)); |
390 | | |
391 | | static cl::opt<bool> ClOptStack( |
392 | | "asan-opt-stack", cl::desc("Don't instrument scalar stack variables"), |
393 | | cl::Hidden, cl::init(false)); |
394 | | |
395 | | static cl::opt<bool> ClDynamicAllocaStack( |
396 | | "asan-stack-dynamic-alloca", |
397 | | cl::desc("Use dynamic alloca to represent stack variables"), cl::Hidden, |
398 | | cl::init(true)); |
399 | | |
400 | | static cl::opt<uint32_t> ClForceExperiment( |
401 | | "asan-force-experiment", |
402 | | cl::desc("Force optimization experiment (for testing)"), cl::Hidden, |
403 | | cl::init(0)); |
404 | | |
405 | | static cl::opt<bool> |
406 | | ClUsePrivateAlias("asan-use-private-alias", |
407 | | cl::desc("Use private aliases for global variables"), |
408 | | cl::Hidden, cl::init(true)); |
409 | | |
410 | | static cl::opt<bool> |
411 | | ClUseOdrIndicator("asan-use-odr-indicator", |
412 | | cl::desc("Use odr indicators to improve ODR reporting"), |
413 | | cl::Hidden, cl::init(true)); |
414 | | |
415 | | static cl::opt<bool> |
416 | | ClUseGlobalsGC("asan-globals-live-support", |
417 | | cl::desc("Use linker features to support dead " |
418 | | "code stripping of globals"), |
419 | | cl::Hidden, cl::init(true)); |
420 | | |
421 | | // This is on by default even though there is a bug in gold: |
422 | | // https://sourceware.org/bugzilla/show_bug.cgi?id=19002 |
423 | | static cl::opt<bool> |
424 | | ClWithComdat("asan-with-comdat", |
425 | | cl::desc("Place ASan constructors in comdat sections"), |
426 | | cl::Hidden, cl::init(true)); |
427 | | |
428 | | static cl::opt<AsanDtorKind> ClOverrideDestructorKind( |
429 | | "asan-destructor-kind", |
430 | | cl::desc("Sets the ASan destructor kind. The default is to use the value " |
431 | | "provided to the pass constructor"), |
432 | | cl::values(clEnumValN(AsanDtorKind::None, "none", "No destructors"), |
433 | | clEnumValN(AsanDtorKind::Global, "global", |
434 | | "Use global destructors")), |
435 | | cl::init(AsanDtorKind::Invalid), cl::Hidden); |
436 | | |
437 | | // Debug flags. |
438 | | |
439 | | static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden, |
440 | | cl::init(0)); |
441 | | |
442 | | static cl::opt<int> ClDebugStack("asan-debug-stack", cl::desc("debug stack"), |
443 | | cl::Hidden, cl::init(0)); |
444 | | |
445 | | static cl::opt<std::string> ClDebugFunc("asan-debug-func", cl::Hidden, |
446 | | cl::desc("Debug func")); |
447 | | |
448 | | static cl::opt<int> ClDebugMin("asan-debug-min", cl::desc("Debug min inst"), |
449 | | cl::Hidden, cl::init(-1)); |
450 | | |
451 | | static cl::opt<int> ClDebugMax("asan-debug-max", cl::desc("Debug max inst"), |
452 | | cl::Hidden, cl::init(-1)); |
453 | | |
454 | | STATISTIC(NumInstrumentedReads, "Number of instrumented reads"); |
455 | | STATISTIC(NumInstrumentedWrites, "Number of instrumented writes"); |
456 | | STATISTIC(NumOptimizedAccessesToGlobalVar, |
457 | | "Number of optimized accesses to global vars"); |
458 | | STATISTIC(NumOptimizedAccessesToStackVar, |
459 | | "Number of optimized accesses to stack vars"); |
460 | | |
461 | | namespace { |
462 | | |
463 | | /// This struct defines the shadow mapping using the rule: |
464 | | /// shadow = (mem >> Scale) ADD-or-OR Offset. |
465 | | /// If InGlobal is true, then |
466 | | /// extern char __asan_shadow[]; |
467 | | /// shadow = (mem >> Scale) + &__asan_shadow |
468 | | struct ShadowMapping { |
469 | | int Scale; |
470 | | uint64_t Offset; |
471 | | bool OrShadowOffset; |
472 | | bool InGlobal; |
473 | | }; |
474 | | |
475 | | } // end anonymous namespace |
476 | | |
477 | | static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize, |
478 | 0 | bool IsKasan) { |
479 | 0 | bool IsAndroid = TargetTriple.isAndroid(); |
480 | 0 | bool IsIOS = TargetTriple.isiOS() || TargetTriple.isWatchOS() || |
481 | 0 | TargetTriple.isDriverKit(); |
482 | 0 | bool IsMacOS = TargetTriple.isMacOSX(); |
483 | 0 | bool IsFreeBSD = TargetTriple.isOSFreeBSD(); |
484 | 0 | bool IsNetBSD = TargetTriple.isOSNetBSD(); |
485 | 0 | bool IsPS = TargetTriple.isPS(); |
486 | 0 | bool IsLinux = TargetTriple.isOSLinux(); |
487 | 0 | bool IsPPC64 = TargetTriple.getArch() == Triple::ppc64 || |
488 | 0 | TargetTriple.getArch() == Triple::ppc64le; |
489 | 0 | bool IsSystemZ = TargetTriple.getArch() == Triple::systemz; |
490 | 0 | bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64; |
491 | 0 | bool IsMIPSN32ABI = TargetTriple.getEnvironment() == Triple::GNUABIN32; |
492 | 0 | bool IsMIPS32 = TargetTriple.isMIPS32(); |
493 | 0 | bool IsMIPS64 = TargetTriple.isMIPS64(); |
494 | 0 | bool IsArmOrThumb = TargetTriple.isARM() || TargetTriple.isThumb(); |
495 | 0 | bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64 || |
496 | 0 | TargetTriple.getArch() == Triple::aarch64_be; |
497 | 0 | bool IsLoongArch64 = TargetTriple.isLoongArch64(); |
498 | 0 | bool IsRISCV64 = TargetTriple.getArch() == Triple::riscv64; |
499 | 0 | bool IsWindows = TargetTriple.isOSWindows(); |
500 | 0 | bool IsFuchsia = TargetTriple.isOSFuchsia(); |
501 | 0 | bool IsEmscripten = TargetTriple.isOSEmscripten(); |
502 | 0 | bool IsAMDGPU = TargetTriple.isAMDGPU(); |
503 | |
|
504 | 0 | ShadowMapping Mapping; |
505 | |
|
506 | 0 | Mapping.Scale = kDefaultShadowScale; |
507 | 0 | if (ClMappingScale.getNumOccurrences() > 0) { |
508 | 0 | Mapping.Scale = ClMappingScale; |
509 | 0 | } |
510 | |
|
511 | 0 | if (LongSize == 32) { |
512 | 0 | if (IsAndroid) |
513 | 0 | Mapping.Offset = kDynamicShadowSentinel; |
514 | 0 | else if (IsMIPSN32ABI) |
515 | 0 | Mapping.Offset = kMIPS_ShadowOffsetN32; |
516 | 0 | else if (IsMIPS32) |
517 | 0 | Mapping.Offset = kMIPS32_ShadowOffset32; |
518 | 0 | else if (IsFreeBSD) |
519 | 0 | Mapping.Offset = kFreeBSD_ShadowOffset32; |
520 | 0 | else if (IsNetBSD) |
521 | 0 | Mapping.Offset = kNetBSD_ShadowOffset32; |
522 | 0 | else if (IsIOS) |
523 | 0 | Mapping.Offset = kDynamicShadowSentinel; |
524 | 0 | else if (IsWindows) |
525 | 0 | Mapping.Offset = kWindowsShadowOffset32; |
526 | 0 | else if (IsEmscripten) |
527 | 0 | Mapping.Offset = kEmscriptenShadowOffset; |
528 | 0 | else |
529 | 0 | Mapping.Offset = kDefaultShadowOffset32; |
530 | 0 | } else { // LongSize == 64 |
531 | | // Fuchsia is always PIE, which means that the beginning of the address |
532 | | // space is always available. |
533 | 0 | if (IsFuchsia) |
534 | 0 | Mapping.Offset = 0; |
535 | 0 | else if (IsPPC64) |
536 | 0 | Mapping.Offset = kPPC64_ShadowOffset64; |
537 | 0 | else if (IsSystemZ) |
538 | 0 | Mapping.Offset = kSystemZ_ShadowOffset64; |
539 | 0 | else if (IsFreeBSD && IsAArch64) |
540 | 0 | Mapping.Offset = kFreeBSDAArch64_ShadowOffset64; |
541 | 0 | else if (IsFreeBSD && !IsMIPS64) { |
542 | 0 | if (IsKasan) |
543 | 0 | Mapping.Offset = kFreeBSDKasan_ShadowOffset64; |
544 | 0 | else |
545 | 0 | Mapping.Offset = kFreeBSD_ShadowOffset64; |
546 | 0 | } else if (IsNetBSD) { |
547 | 0 | if (IsKasan) |
548 | 0 | Mapping.Offset = kNetBSDKasan_ShadowOffset64; |
549 | 0 | else |
550 | 0 | Mapping.Offset = kNetBSD_ShadowOffset64; |
551 | 0 | } else if (IsPS) |
552 | 0 | Mapping.Offset = kPS_ShadowOffset64; |
553 | 0 | else if (IsLinux && IsX86_64) { |
554 | 0 | if (IsKasan) |
555 | 0 | Mapping.Offset = kLinuxKasan_ShadowOffset64; |
556 | 0 | else |
557 | 0 | Mapping.Offset = (kSmallX86_64ShadowOffsetBase & |
558 | 0 | (kSmallX86_64ShadowOffsetAlignMask << Mapping.Scale)); |
559 | 0 | } else if (IsWindows && IsX86_64) { |
560 | 0 | Mapping.Offset = kWindowsShadowOffset64; |
561 | 0 | } else if (IsMIPS64) |
562 | 0 | Mapping.Offset = kMIPS64_ShadowOffset64; |
563 | 0 | else if (IsIOS) |
564 | 0 | Mapping.Offset = kDynamicShadowSentinel; |
565 | 0 | else if (IsMacOS && IsAArch64) |
566 | 0 | Mapping.Offset = kDynamicShadowSentinel; |
567 | 0 | else if (IsAArch64) |
568 | 0 | Mapping.Offset = kAArch64_ShadowOffset64; |
569 | 0 | else if (IsLoongArch64) |
570 | 0 | Mapping.Offset = kLoongArch64_ShadowOffset64; |
571 | 0 | else if (IsRISCV64) |
572 | 0 | Mapping.Offset = kRISCV64_ShadowOffset64; |
573 | 0 | else if (IsAMDGPU) |
574 | 0 | Mapping.Offset = (kSmallX86_64ShadowOffsetBase & |
575 | 0 | (kSmallX86_64ShadowOffsetAlignMask << Mapping.Scale)); |
576 | 0 | else |
577 | 0 | Mapping.Offset = kDefaultShadowOffset64; |
578 | 0 | } |
579 | |
|
580 | 0 | if (ClForceDynamicShadow) { |
581 | 0 | Mapping.Offset = kDynamicShadowSentinel; |
582 | 0 | } |
583 | |
|
584 | 0 | if (ClMappingOffset.getNumOccurrences() > 0) { |
585 | 0 | Mapping.Offset = ClMappingOffset; |
586 | 0 | } |
587 | | |
588 | | // OR-ing shadow offset if more efficient (at least on x86) if the offset |
589 | | // is a power of two, but on ppc64 and loongarch64 we have to use add since |
590 | | // the shadow offset is not necessarily 1/8-th of the address space. On |
591 | | // SystemZ, we could OR the constant in a single instruction, but it's more |
592 | | // efficient to load it once and use indexed addressing. |
593 | 0 | Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS && |
594 | 0 | !IsRISCV64 && !IsLoongArch64 && |
595 | 0 | !(Mapping.Offset & (Mapping.Offset - 1)) && |
596 | 0 | Mapping.Offset != kDynamicShadowSentinel; |
597 | 0 | bool IsAndroidWithIfuncSupport = |
598 | 0 | IsAndroid && !TargetTriple.isAndroidVersionLT(21); |
599 | 0 | Mapping.InGlobal = ClWithIfunc && IsAndroidWithIfuncSupport && IsArmOrThumb; |
600 | |
|
601 | 0 | return Mapping; |
602 | 0 | } |
603 | | |
604 | | namespace llvm { |
605 | | void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize, |
606 | | bool IsKasan, uint64_t *ShadowBase, |
607 | 0 | int *MappingScale, bool *OrShadowOffset) { |
608 | 0 | auto Mapping = getShadowMapping(TargetTriple, LongSize, IsKasan); |
609 | 0 | *ShadowBase = Mapping.Offset; |
610 | 0 | *MappingScale = Mapping.Scale; |
611 | 0 | *OrShadowOffset = Mapping.OrShadowOffset; |
612 | 0 | } |
613 | | |
614 | | ASanAccessInfo::ASanAccessInfo(int32_t Packed) |
615 | | : Packed(Packed), |
616 | | AccessSizeIndex((Packed >> kAccessSizeIndexShift) & kAccessSizeIndexMask), |
617 | | IsWrite((Packed >> kIsWriteShift) & kIsWriteMask), |
618 | 0 | CompileKernel((Packed >> kCompileKernelShift) & kCompileKernelMask) {} |
619 | | |
620 | | ASanAccessInfo::ASanAccessInfo(bool IsWrite, bool CompileKernel, |
621 | | uint8_t AccessSizeIndex) |
622 | | : Packed((IsWrite << kIsWriteShift) + |
623 | | (CompileKernel << kCompileKernelShift) + |
624 | | (AccessSizeIndex << kAccessSizeIndexShift)), |
625 | | AccessSizeIndex(AccessSizeIndex), IsWrite(IsWrite), |
626 | 0 | CompileKernel(CompileKernel) {} |
627 | | |
628 | | } // namespace llvm |
629 | | |
630 | 0 | static uint64_t getRedzoneSizeForScale(int MappingScale) { |
631 | | // Redzone used for stack and globals is at least 32 bytes. |
632 | | // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively. |
633 | 0 | return std::max(32U, 1U << MappingScale); |
634 | 0 | } |
635 | | |
636 | 0 | static uint64_t GetCtorAndDtorPriority(Triple &TargetTriple) { |
637 | 0 | if (TargetTriple.isOSEmscripten()) { |
638 | 0 | return kAsanEmscriptenCtorAndDtorPriority; |
639 | 0 | } else { |
640 | 0 | return kAsanCtorAndDtorPriority; |
641 | 0 | } |
642 | 0 | } |
643 | | |
644 | | namespace { |
645 | | |
646 | | /// AddressSanitizer: instrument the code in module to find memory bugs. |
647 | | struct AddressSanitizer { |
648 | | AddressSanitizer(Module &M, const StackSafetyGlobalInfo *SSGI, |
649 | | int InstrumentationWithCallsThreshold, |
650 | | uint32_t MaxInlinePoisoningSize, bool CompileKernel = false, |
651 | | bool Recover = false, bool UseAfterScope = false, |
652 | | AsanDetectStackUseAfterReturnMode UseAfterReturn = |
653 | | AsanDetectStackUseAfterReturnMode::Runtime) |
654 | | : CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan |
655 | | : CompileKernel), |
656 | | Recover(ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover), |
657 | | UseAfterScope(UseAfterScope || ClUseAfterScope), |
658 | | UseAfterReturn(ClUseAfterReturn.getNumOccurrences() ? ClUseAfterReturn |
659 | | : UseAfterReturn), |
660 | | SSGI(SSGI), |
661 | | InstrumentationWithCallsThreshold( |
662 | | ClInstrumentationWithCallsThreshold.getNumOccurrences() > 0 |
663 | | ? ClInstrumentationWithCallsThreshold |
664 | | : InstrumentationWithCallsThreshold), |
665 | | MaxInlinePoisoningSize(ClMaxInlinePoisoningSize.getNumOccurrences() > 0 |
666 | | ? ClMaxInlinePoisoningSize |
667 | 0 | : MaxInlinePoisoningSize) { |
668 | 0 | C = &(M.getContext()); |
669 | 0 | DL = &M.getDataLayout(); |
670 | 0 | LongSize = M.getDataLayout().getPointerSizeInBits(); |
671 | 0 | IntptrTy = Type::getIntNTy(*C, LongSize); |
672 | 0 | PtrTy = PointerType::getUnqual(*C); |
673 | 0 | Int32Ty = Type::getInt32Ty(*C); |
674 | 0 | TargetTriple = Triple(M.getTargetTriple()); |
675 | |
|
676 | 0 | Mapping = getShadowMapping(TargetTriple, LongSize, this->CompileKernel); |
677 | |
|
678 | 0 | assert(this->UseAfterReturn != AsanDetectStackUseAfterReturnMode::Invalid); |
679 | 0 | } |
680 | | |
681 | 0 | TypeSize getAllocaSizeInBytes(const AllocaInst &AI) const { |
682 | 0 | return *AI.getAllocationSize(AI.getModule()->getDataLayout()); |
683 | 0 | } |
684 | | |
685 | | /// Check if we want (and can) handle this alloca. |
686 | | bool isInterestingAlloca(const AllocaInst &AI); |
687 | | |
688 | | bool ignoreAccess(Instruction *Inst, Value *Ptr); |
689 | | void getInterestingMemoryOperands( |
690 | | Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting); |
691 | | |
692 | | void instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis, |
693 | | InterestingMemoryOperand &O, bool UseCalls, |
694 | | const DataLayout &DL); |
695 | | void instrumentPointerComparisonOrSubtraction(Instruction *I); |
696 | | void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore, |
697 | | Value *Addr, MaybeAlign Alignment, |
698 | | uint32_t TypeStoreSize, bool IsWrite, |
699 | | Value *SizeArgument, bool UseCalls, uint32_t Exp); |
700 | | Instruction *instrumentAMDGPUAddress(Instruction *OrigIns, |
701 | | Instruction *InsertBefore, Value *Addr, |
702 | | uint32_t TypeStoreSize, bool IsWrite, |
703 | | Value *SizeArgument); |
704 | | Instruction *genAMDGPUReportBlock(IRBuilder<> &IRB, Value *Cond, |
705 | | bool Recover); |
706 | | void instrumentUnusualSizeOrAlignment(Instruction *I, |
707 | | Instruction *InsertBefore, Value *Addr, |
708 | | TypeSize TypeStoreSize, bool IsWrite, |
709 | | Value *SizeArgument, bool UseCalls, |
710 | | uint32_t Exp); |
711 | | void instrumentMaskedLoadOrStore(AddressSanitizer *Pass, const DataLayout &DL, |
712 | | Type *IntptrTy, Value *Mask, Value *EVL, |
713 | | Value *Stride, Instruction *I, Value *Addr, |
714 | | MaybeAlign Alignment, unsigned Granularity, |
715 | | Type *OpType, bool IsWrite, |
716 | | Value *SizeArgument, bool UseCalls, |
717 | | uint32_t Exp); |
718 | | Value *createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, |
719 | | Value *ShadowValue, uint32_t TypeStoreSize); |
720 | | Instruction *generateCrashCode(Instruction *InsertBefore, Value *Addr, |
721 | | bool IsWrite, size_t AccessSizeIndex, |
722 | | Value *SizeArgument, uint32_t Exp); |
723 | | void instrumentMemIntrinsic(MemIntrinsic *MI); |
724 | | Value *memToShadow(Value *Shadow, IRBuilder<> &IRB); |
725 | | bool suppressInstrumentationSiteForDebug(int &Instrumented); |
726 | | bool instrumentFunction(Function &F, const TargetLibraryInfo *TLI); |
727 | | bool maybeInsertAsanInitAtFunctionEntry(Function &F); |
728 | | bool maybeInsertDynamicShadowAtFunctionEntry(Function &F); |
729 | | void markEscapedLocalAllocas(Function &F); |
730 | | |
731 | | private: |
732 | | friend struct FunctionStackPoisoner; |
733 | | |
734 | | void initializeCallbacks(Module &M, const TargetLibraryInfo *TLI); |
735 | | |
736 | | bool LooksLikeCodeInBug11395(Instruction *I); |
737 | | bool GlobalIsLinkerInitialized(GlobalVariable *G); |
738 | | bool isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis, Value *Addr, |
739 | | TypeSize TypeStoreSize) const; |
740 | | |
741 | | /// Helper to cleanup per-function state. |
742 | | struct FunctionStateRAII { |
743 | | AddressSanitizer *Pass; |
744 | | |
745 | 0 | FunctionStateRAII(AddressSanitizer *Pass) : Pass(Pass) { |
746 | 0 | assert(Pass->ProcessedAllocas.empty() && |
747 | 0 | "last pass forgot to clear cache"); |
748 | 0 | assert(!Pass->LocalDynamicShadow); |
749 | 0 | } |
750 | | |
751 | 0 | ~FunctionStateRAII() { |
752 | 0 | Pass->LocalDynamicShadow = nullptr; |
753 | 0 | Pass->ProcessedAllocas.clear(); |
754 | 0 | } |
755 | | }; |
756 | | |
757 | | LLVMContext *C; |
758 | | const DataLayout *DL; |
759 | | Triple TargetTriple; |
760 | | int LongSize; |
761 | | bool CompileKernel; |
762 | | bool Recover; |
763 | | bool UseAfterScope; |
764 | | AsanDetectStackUseAfterReturnMode UseAfterReturn; |
765 | | Type *IntptrTy; |
766 | | Type *Int32Ty; |
767 | | PointerType *PtrTy; |
768 | | ShadowMapping Mapping; |
769 | | FunctionCallee AsanHandleNoReturnFunc; |
770 | | FunctionCallee AsanPtrCmpFunction, AsanPtrSubFunction; |
771 | | Constant *AsanShadowGlobal; |
772 | | |
773 | | // These arrays is indexed by AccessIsWrite, Experiment and log2(AccessSize). |
774 | | FunctionCallee AsanErrorCallback[2][2][kNumberOfAccessSizes]; |
775 | | FunctionCallee AsanMemoryAccessCallback[2][2][kNumberOfAccessSizes]; |
776 | | |
777 | | // These arrays is indexed by AccessIsWrite and Experiment. |
778 | | FunctionCallee AsanErrorCallbackSized[2][2]; |
779 | | FunctionCallee AsanMemoryAccessCallbackSized[2][2]; |
780 | | |
781 | | FunctionCallee AsanMemmove, AsanMemcpy, AsanMemset; |
782 | | Value *LocalDynamicShadow = nullptr; |
783 | | const StackSafetyGlobalInfo *SSGI; |
784 | | DenseMap<const AllocaInst *, bool> ProcessedAllocas; |
785 | | |
786 | | FunctionCallee AMDGPUAddressShared; |
787 | | FunctionCallee AMDGPUAddressPrivate; |
788 | | int InstrumentationWithCallsThreshold; |
789 | | uint32_t MaxInlinePoisoningSize; |
790 | | }; |
791 | | |
792 | | class ModuleAddressSanitizer { |
793 | | public: |
794 | | ModuleAddressSanitizer(Module &M, bool InsertVersionCheck, |
795 | | bool CompileKernel = false, bool Recover = false, |
796 | | bool UseGlobalsGC = true, bool UseOdrIndicator = true, |
797 | | AsanDtorKind DestructorKind = AsanDtorKind::Global, |
798 | | AsanCtorKind ConstructorKind = AsanCtorKind::Global) |
799 | | : CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan |
800 | | : CompileKernel), |
801 | | InsertVersionCheck(ClInsertVersionCheck.getNumOccurrences() > 0 |
802 | | ? ClInsertVersionCheck |
803 | | : InsertVersionCheck), |
804 | | Recover(ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover), |
805 | | UseGlobalsGC(UseGlobalsGC && ClUseGlobalsGC && !this->CompileKernel), |
806 | | // Enable aliases as they should have no downside with ODR indicators. |
807 | | UsePrivateAlias(ClUsePrivateAlias.getNumOccurrences() > 0 |
808 | | ? ClUsePrivateAlias |
809 | | : UseOdrIndicator), |
810 | | UseOdrIndicator(ClUseOdrIndicator.getNumOccurrences() > 0 |
811 | | ? ClUseOdrIndicator |
812 | | : UseOdrIndicator), |
813 | | // Not a typo: ClWithComdat is almost completely pointless without |
814 | | // ClUseGlobalsGC (because then it only works on modules without |
815 | | // globals, which are rare); it is a prerequisite for ClUseGlobalsGC; |
816 | | // and both suffer from gold PR19002 for which UseGlobalsGC constructor |
817 | | // argument is designed as workaround. Therefore, disable both |
818 | | // ClWithComdat and ClUseGlobalsGC unless the frontend says it's ok to |
819 | | // do globals-gc. |
820 | | UseCtorComdat(UseGlobalsGC && ClWithComdat && !this->CompileKernel), |
821 | | DestructorKind(DestructorKind), |
822 | | ConstructorKind(ClConstructorKind.getNumOccurrences() > 0 |
823 | | ? ClConstructorKind |
824 | 0 | : ConstructorKind) { |
825 | 0 | C = &(M.getContext()); |
826 | 0 | int LongSize = M.getDataLayout().getPointerSizeInBits(); |
827 | 0 | IntptrTy = Type::getIntNTy(*C, LongSize); |
828 | 0 | PtrTy = PointerType::getUnqual(*C); |
829 | 0 | TargetTriple = Triple(M.getTargetTriple()); |
830 | 0 | Mapping = getShadowMapping(TargetTriple, LongSize, this->CompileKernel); |
831 | |
|
832 | 0 | if (ClOverrideDestructorKind != AsanDtorKind::Invalid) |
833 | 0 | this->DestructorKind = ClOverrideDestructorKind; |
834 | 0 | assert(this->DestructorKind != AsanDtorKind::Invalid); |
835 | 0 | } |
836 | | |
837 | | bool instrumentModule(Module &); |
838 | | |
839 | | private: |
840 | | void initializeCallbacks(Module &M); |
841 | | |
842 | | void instrumentGlobals(IRBuilder<> &IRB, Module &M, bool *CtorComdat); |
843 | | void InstrumentGlobalsCOFF(IRBuilder<> &IRB, Module &M, |
844 | | ArrayRef<GlobalVariable *> ExtendedGlobals, |
845 | | ArrayRef<Constant *> MetadataInitializers); |
846 | | void instrumentGlobalsELF(IRBuilder<> &IRB, Module &M, |
847 | | ArrayRef<GlobalVariable *> ExtendedGlobals, |
848 | | ArrayRef<Constant *> MetadataInitializers, |
849 | | const std::string &UniqueModuleId); |
850 | | void InstrumentGlobalsMachO(IRBuilder<> &IRB, Module &M, |
851 | | ArrayRef<GlobalVariable *> ExtendedGlobals, |
852 | | ArrayRef<Constant *> MetadataInitializers); |
853 | | void |
854 | | InstrumentGlobalsWithMetadataArray(IRBuilder<> &IRB, Module &M, |
855 | | ArrayRef<GlobalVariable *> ExtendedGlobals, |
856 | | ArrayRef<Constant *> MetadataInitializers); |
857 | | |
858 | | GlobalVariable *CreateMetadataGlobal(Module &M, Constant *Initializer, |
859 | | StringRef OriginalName); |
860 | | void SetComdatForGlobalMetadata(GlobalVariable *G, GlobalVariable *Metadata, |
861 | | StringRef InternalSuffix); |
862 | | Instruction *CreateAsanModuleDtor(Module &M); |
863 | | |
864 | | const GlobalVariable *getExcludedAliasedGlobal(const GlobalAlias &GA) const; |
865 | | bool shouldInstrumentGlobal(GlobalVariable *G) const; |
866 | | bool ShouldUseMachOGlobalsSection() const; |
867 | | StringRef getGlobalMetadataSection() const; |
868 | | void poisonOneInitializer(Function &GlobalInit, GlobalValue *ModuleName); |
869 | | void createInitializerPoisonCalls(Module &M, GlobalValue *ModuleName); |
870 | 0 | uint64_t getMinRedzoneSizeForGlobal() const { |
871 | 0 | return getRedzoneSizeForScale(Mapping.Scale); |
872 | 0 | } |
873 | | uint64_t getRedzoneSizeForGlobal(uint64_t SizeInBytes) const; |
874 | | int GetAsanVersion(const Module &M) const; |
875 | | |
876 | | bool CompileKernel; |
877 | | bool InsertVersionCheck; |
878 | | bool Recover; |
879 | | bool UseGlobalsGC; |
880 | | bool UsePrivateAlias; |
881 | | bool UseOdrIndicator; |
882 | | bool UseCtorComdat; |
883 | | AsanDtorKind DestructorKind; |
884 | | AsanCtorKind ConstructorKind; |
885 | | Type *IntptrTy; |
886 | | PointerType *PtrTy; |
887 | | LLVMContext *C; |
888 | | Triple TargetTriple; |
889 | | ShadowMapping Mapping; |
890 | | FunctionCallee AsanPoisonGlobals; |
891 | | FunctionCallee AsanUnpoisonGlobals; |
892 | | FunctionCallee AsanRegisterGlobals; |
893 | | FunctionCallee AsanUnregisterGlobals; |
894 | | FunctionCallee AsanRegisterImageGlobals; |
895 | | FunctionCallee AsanUnregisterImageGlobals; |
896 | | FunctionCallee AsanRegisterElfGlobals; |
897 | | FunctionCallee AsanUnregisterElfGlobals; |
898 | | |
899 | | Function *AsanCtorFunction = nullptr; |
900 | | Function *AsanDtorFunction = nullptr; |
901 | | }; |
902 | | |
903 | | // Stack poisoning does not play well with exception handling. |
904 | | // When an exception is thrown, we essentially bypass the code |
905 | | // that unpoisones the stack. This is why the run-time library has |
906 | | // to intercept __cxa_throw (as well as longjmp, etc) and unpoison the entire |
907 | | // stack in the interceptor. This however does not work inside the |
908 | | // actual function which catches the exception. Most likely because the |
909 | | // compiler hoists the load of the shadow value somewhere too high. |
910 | | // This causes asan to report a non-existing bug on 453.povray. |
911 | | // It sounds like an LLVM bug. |
912 | | struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> { |
913 | | Function &F; |
914 | | AddressSanitizer &ASan; |
915 | | DIBuilder DIB; |
916 | | LLVMContext *C; |
917 | | Type *IntptrTy; |
918 | | Type *IntptrPtrTy; |
919 | | ShadowMapping Mapping; |
920 | | |
921 | | SmallVector<AllocaInst *, 16> AllocaVec; |
922 | | SmallVector<AllocaInst *, 16> StaticAllocasToMoveUp; |
923 | | SmallVector<Instruction *, 8> RetVec; |
924 | | |
925 | | FunctionCallee AsanStackMallocFunc[kMaxAsanStackMallocSizeClass + 1], |
926 | | AsanStackFreeFunc[kMaxAsanStackMallocSizeClass + 1]; |
927 | | FunctionCallee AsanSetShadowFunc[0x100] = {}; |
928 | | FunctionCallee AsanPoisonStackMemoryFunc, AsanUnpoisonStackMemoryFunc; |
929 | | FunctionCallee AsanAllocaPoisonFunc, AsanAllocasUnpoisonFunc; |
930 | | |
931 | | // Stores a place and arguments of poisoning/unpoisoning call for alloca. |
932 | | struct AllocaPoisonCall { |
933 | | IntrinsicInst *InsBefore; |
934 | | AllocaInst *AI; |
935 | | uint64_t Size; |
936 | | bool DoPoison; |
937 | | }; |
938 | | SmallVector<AllocaPoisonCall, 8> DynamicAllocaPoisonCallVec; |
939 | | SmallVector<AllocaPoisonCall, 8> StaticAllocaPoisonCallVec; |
940 | | bool HasUntracedLifetimeIntrinsic = false; |
941 | | |
942 | | SmallVector<AllocaInst *, 1> DynamicAllocaVec; |
943 | | SmallVector<IntrinsicInst *, 1> StackRestoreVec; |
944 | | AllocaInst *DynamicAllocaLayout = nullptr; |
945 | | IntrinsicInst *LocalEscapeCall = nullptr; |
946 | | |
947 | | bool HasInlineAsm = false; |
948 | | bool HasReturnsTwiceCall = false; |
949 | | bool PoisonStack; |
950 | | |
951 | | FunctionStackPoisoner(Function &F, AddressSanitizer &ASan) |
952 | | : F(F), ASan(ASan), DIB(*F.getParent(), /*AllowUnresolved*/ false), |
953 | | C(ASan.C), IntptrTy(ASan.IntptrTy), |
954 | | IntptrPtrTy(PointerType::get(IntptrTy, 0)), Mapping(ASan.Mapping), |
955 | | PoisonStack(ClStack && |
956 | 0 | !Triple(F.getParent()->getTargetTriple()).isAMDGPU()) {} |
957 | | |
958 | 0 | bool runOnFunction() { |
959 | 0 | if (!PoisonStack) |
960 | 0 | return false; |
961 | | |
962 | 0 | if (ClRedzoneByvalArgs) |
963 | 0 | copyArgsPassedByValToAllocas(); |
964 | | |
965 | | // Collect alloca, ret, lifetime instructions etc. |
966 | 0 | for (BasicBlock *BB : depth_first(&F.getEntryBlock())) visit(*BB); |
967 | |
|
968 | 0 | if (AllocaVec.empty() && DynamicAllocaVec.empty()) return false; |
969 | | |
970 | 0 | initializeCallbacks(*F.getParent()); |
971 | |
|
972 | 0 | if (HasUntracedLifetimeIntrinsic) { |
973 | | // If there are lifetime intrinsics which couldn't be traced back to an |
974 | | // alloca, we may not know exactly when a variable enters scope, and |
975 | | // therefore should "fail safe" by not poisoning them. |
976 | 0 | StaticAllocaPoisonCallVec.clear(); |
977 | 0 | DynamicAllocaPoisonCallVec.clear(); |
978 | 0 | } |
979 | |
|
980 | 0 | processDynamicAllocas(); |
981 | 0 | processStaticAllocas(); |
982 | |
|
983 | 0 | if (ClDebugStack) { |
984 | 0 | LLVM_DEBUG(dbgs() << F); |
985 | 0 | } |
986 | 0 | return true; |
987 | 0 | } |
988 | | |
989 | | // Arguments marked with the "byval" attribute are implicitly copied without |
990 | | // using an alloca instruction. To produce redzones for those arguments, we |
991 | | // copy them a second time into memory allocated with an alloca instruction. |
992 | | void copyArgsPassedByValToAllocas(); |
993 | | |
994 | | // Finds all Alloca instructions and puts |
995 | | // poisoned red zones around all of them. |
996 | | // Then unpoison everything back before the function returns. |
997 | | void processStaticAllocas(); |
998 | | void processDynamicAllocas(); |
999 | | |
1000 | | void createDynamicAllocasInitStorage(); |
1001 | | |
1002 | | // ----------------------- Visitors. |
1003 | | /// Collect all Ret instructions, or the musttail call instruction if it |
1004 | | /// precedes the return instruction. |
1005 | 0 | void visitReturnInst(ReturnInst &RI) { |
1006 | 0 | if (CallInst *CI = RI.getParent()->getTerminatingMustTailCall()) |
1007 | 0 | RetVec.push_back(CI); |
1008 | 0 | else |
1009 | 0 | RetVec.push_back(&RI); |
1010 | 0 | } |
1011 | | |
1012 | | /// Collect all Resume instructions. |
1013 | 0 | void visitResumeInst(ResumeInst &RI) { RetVec.push_back(&RI); } |
1014 | | |
1015 | | /// Collect all CatchReturnInst instructions. |
1016 | 0 | void visitCleanupReturnInst(CleanupReturnInst &CRI) { RetVec.push_back(&CRI); } |
1017 | | |
1018 | | void unpoisonDynamicAllocasBeforeInst(Instruction *InstBefore, |
1019 | 0 | Value *SavedStack) { |
1020 | 0 | IRBuilder<> IRB(InstBefore); |
1021 | 0 | Value *DynamicAreaPtr = IRB.CreatePtrToInt(SavedStack, IntptrTy); |
1022 | | // When we insert _asan_allocas_unpoison before @llvm.stackrestore, we |
1023 | | // need to adjust extracted SP to compute the address of the most recent |
1024 | | // alloca. We have a special @llvm.get.dynamic.area.offset intrinsic for |
1025 | | // this purpose. |
1026 | 0 | if (!isa<ReturnInst>(InstBefore)) { |
1027 | 0 | Function *DynamicAreaOffsetFunc = Intrinsic::getDeclaration( |
1028 | 0 | InstBefore->getModule(), Intrinsic::get_dynamic_area_offset, |
1029 | 0 | {IntptrTy}); |
1030 | |
|
1031 | 0 | Value *DynamicAreaOffset = IRB.CreateCall(DynamicAreaOffsetFunc, {}); |
1032 | |
|
1033 | 0 | DynamicAreaPtr = IRB.CreateAdd(IRB.CreatePtrToInt(SavedStack, IntptrTy), |
1034 | 0 | DynamicAreaOffset); |
1035 | 0 | } |
1036 | |
|
1037 | 0 | IRB.CreateCall( |
1038 | 0 | AsanAllocasUnpoisonFunc, |
1039 | 0 | {IRB.CreateLoad(IntptrTy, DynamicAllocaLayout), DynamicAreaPtr}); |
1040 | 0 | } |
1041 | | |
1042 | | // Unpoison dynamic allocas redzones. |
1043 | 0 | void unpoisonDynamicAllocas() { |
1044 | 0 | for (Instruction *Ret : RetVec) |
1045 | 0 | unpoisonDynamicAllocasBeforeInst(Ret, DynamicAllocaLayout); |
1046 | |
|
1047 | 0 | for (Instruction *StackRestoreInst : StackRestoreVec) |
1048 | 0 | unpoisonDynamicAllocasBeforeInst(StackRestoreInst, |
1049 | 0 | StackRestoreInst->getOperand(0)); |
1050 | 0 | } |
1051 | | |
1052 | | // Deploy and poison redzones around dynamic alloca call. To do this, we |
1053 | | // should replace this call with another one with changed parameters and |
1054 | | // replace all its uses with new address, so |
1055 | | // addr = alloca type, old_size, align |
1056 | | // is replaced by |
1057 | | // new_size = (old_size + additional_size) * sizeof(type) |
1058 | | // tmp = alloca i8, new_size, max(align, 32) |
1059 | | // addr = tmp + 32 (first 32 bytes are for the left redzone). |
1060 | | // Additional_size is added to make new memory allocation contain not only |
1061 | | // requested memory, but also left, partial and right redzones. |
1062 | | void handleDynamicAllocaCall(AllocaInst *AI); |
1063 | | |
1064 | | /// Collect Alloca instructions we want (and can) handle. |
1065 | 0 | void visitAllocaInst(AllocaInst &AI) { |
1066 | | // FIXME: Handle scalable vectors instead of ignoring them. |
1067 | 0 | if (!ASan.isInterestingAlloca(AI) || |
1068 | 0 | isa<ScalableVectorType>(AI.getAllocatedType())) { |
1069 | 0 | if (AI.isStaticAlloca()) { |
1070 | | // Skip over allocas that are present *before* the first instrumented |
1071 | | // alloca, we don't want to move those around. |
1072 | 0 | if (AllocaVec.empty()) |
1073 | 0 | return; |
1074 | | |
1075 | 0 | StaticAllocasToMoveUp.push_back(&AI); |
1076 | 0 | } |
1077 | 0 | return; |
1078 | 0 | } |
1079 | | |
1080 | 0 | if (!AI.isStaticAlloca()) |
1081 | 0 | DynamicAllocaVec.push_back(&AI); |
1082 | 0 | else |
1083 | 0 | AllocaVec.push_back(&AI); |
1084 | 0 | } |
1085 | | |
1086 | | /// Collect lifetime intrinsic calls to check for use-after-scope |
1087 | | /// errors. |
1088 | 0 | void visitIntrinsicInst(IntrinsicInst &II) { |
1089 | 0 | Intrinsic::ID ID = II.getIntrinsicID(); |
1090 | 0 | if (ID == Intrinsic::stackrestore) StackRestoreVec.push_back(&II); |
1091 | 0 | if (ID == Intrinsic::localescape) LocalEscapeCall = &II; |
1092 | 0 | if (!ASan.UseAfterScope) |
1093 | 0 | return; |
1094 | 0 | if (!II.isLifetimeStartOrEnd()) |
1095 | 0 | return; |
1096 | | // Found lifetime intrinsic, add ASan instrumentation if necessary. |
1097 | 0 | auto *Size = cast<ConstantInt>(II.getArgOperand(0)); |
1098 | | // If size argument is undefined, don't do anything. |
1099 | 0 | if (Size->isMinusOne()) return; |
1100 | | // Check that size doesn't saturate uint64_t and can |
1101 | | // be stored in IntptrTy. |
1102 | 0 | const uint64_t SizeValue = Size->getValue().getLimitedValue(); |
1103 | 0 | if (SizeValue == ~0ULL || |
1104 | 0 | !ConstantInt::isValueValidForType(IntptrTy, SizeValue)) |
1105 | 0 | return; |
1106 | | // Find alloca instruction that corresponds to llvm.lifetime argument. |
1107 | | // Currently we can only handle lifetime markers pointing to the |
1108 | | // beginning of the alloca. |
1109 | 0 | AllocaInst *AI = findAllocaForValue(II.getArgOperand(1), true); |
1110 | 0 | if (!AI) { |
1111 | 0 | HasUntracedLifetimeIntrinsic = true; |
1112 | 0 | return; |
1113 | 0 | } |
1114 | | // We're interested only in allocas we can handle. |
1115 | 0 | if (!ASan.isInterestingAlloca(*AI)) |
1116 | 0 | return; |
1117 | 0 | bool DoPoison = (ID == Intrinsic::lifetime_end); |
1118 | 0 | AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison}; |
1119 | 0 | if (AI->isStaticAlloca()) |
1120 | 0 | StaticAllocaPoisonCallVec.push_back(APC); |
1121 | 0 | else if (ClInstrumentDynamicAllocas) |
1122 | 0 | DynamicAllocaPoisonCallVec.push_back(APC); |
1123 | 0 | } |
1124 | | |
1125 | 0 | void visitCallBase(CallBase &CB) { |
1126 | 0 | if (CallInst *CI = dyn_cast<CallInst>(&CB)) { |
1127 | 0 | HasInlineAsm |= CI->isInlineAsm() && &CB != ASan.LocalDynamicShadow; |
1128 | 0 | HasReturnsTwiceCall |= CI->canReturnTwice(); |
1129 | 0 | } |
1130 | 0 | } |
1131 | | |
1132 | | // ---------------------- Helpers. |
1133 | | void initializeCallbacks(Module &M); |
1134 | | |
1135 | | // Copies bytes from ShadowBytes into shadow memory for indexes where |
1136 | | // ShadowMask is not zero. If ShadowMask[i] is zero, we assume that |
1137 | | // ShadowBytes[i] is constantly zero and doesn't need to be overwritten. |
1138 | | void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes, |
1139 | | IRBuilder<> &IRB, Value *ShadowBase); |
1140 | | void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes, |
1141 | | size_t Begin, size_t End, IRBuilder<> &IRB, |
1142 | | Value *ShadowBase); |
1143 | | void copyToShadowInline(ArrayRef<uint8_t> ShadowMask, |
1144 | | ArrayRef<uint8_t> ShadowBytes, size_t Begin, |
1145 | | size_t End, IRBuilder<> &IRB, Value *ShadowBase); |
1146 | | |
1147 | | void poisonAlloca(Value *V, uint64_t Size, IRBuilder<> &IRB, bool DoPoison); |
1148 | | |
1149 | | Value *createAllocaForLayout(IRBuilder<> &IRB, const ASanStackFrameLayout &L, |
1150 | | bool Dynamic); |
1151 | | PHINode *createPHI(IRBuilder<> &IRB, Value *Cond, Value *ValueIfTrue, |
1152 | | Instruction *ThenTerm, Value *ValueIfFalse); |
1153 | | }; |
1154 | | |
1155 | | } // end anonymous namespace |
1156 | | |
1157 | | void AddressSanitizerPass::printPipeline( |
1158 | 0 | raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { |
1159 | 0 | static_cast<PassInfoMixin<AddressSanitizerPass> *>(this)->printPipeline( |
1160 | 0 | OS, MapClassName2PassName); |
1161 | 0 | OS << '<'; |
1162 | 0 | if (Options.CompileKernel) |
1163 | 0 | OS << "kernel"; |
1164 | 0 | OS << '>'; |
1165 | 0 | } |
1166 | | |
1167 | | AddressSanitizerPass::AddressSanitizerPass( |
1168 | | const AddressSanitizerOptions &Options, bool UseGlobalGC, |
1169 | | bool UseOdrIndicator, AsanDtorKind DestructorKind, |
1170 | | AsanCtorKind ConstructorKind) |
1171 | | : Options(Options), UseGlobalGC(UseGlobalGC), |
1172 | | UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind), |
1173 | 0 | ConstructorKind(ConstructorKind) {} |
1174 | | |
1175 | | PreservedAnalyses AddressSanitizerPass::run(Module &M, |
1176 | 0 | ModuleAnalysisManager &MAM) { |
1177 | 0 | ModuleAddressSanitizer ModuleSanitizer( |
1178 | 0 | M, Options.InsertVersionCheck, Options.CompileKernel, Options.Recover, |
1179 | 0 | UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind); |
1180 | 0 | bool Modified = false; |
1181 | 0 | auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); |
1182 | 0 | const StackSafetyGlobalInfo *const SSGI = |
1183 | 0 | ClUseStackSafety ? &MAM.getResult<StackSafetyGlobalAnalysis>(M) : nullptr; |
1184 | 0 | for (Function &F : M) { |
1185 | 0 | AddressSanitizer FunctionSanitizer( |
1186 | 0 | M, SSGI, Options.InstrumentationWithCallsThreshold, |
1187 | 0 | Options.MaxInlinePoisoningSize, Options.CompileKernel, Options.Recover, |
1188 | 0 | Options.UseAfterScope, Options.UseAfterReturn); |
1189 | 0 | const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F); |
1190 | 0 | Modified |= FunctionSanitizer.instrumentFunction(F, &TLI); |
1191 | 0 | } |
1192 | 0 | Modified |= ModuleSanitizer.instrumentModule(M); |
1193 | 0 | if (!Modified) |
1194 | 0 | return PreservedAnalyses::all(); |
1195 | | |
1196 | 0 | PreservedAnalyses PA = PreservedAnalyses::none(); |
1197 | | // GlobalsAA is considered stateless and does not get invalidated unless |
1198 | | // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers |
1199 | | // make changes that require GlobalsAA to be invalidated. |
1200 | 0 | PA.abandon<GlobalsAA>(); |
1201 | 0 | return PA; |
1202 | 0 | } |
1203 | | |
1204 | 0 | static size_t TypeStoreSizeToSizeIndex(uint32_t TypeSize) { |
1205 | 0 | size_t Res = llvm::countr_zero(TypeSize / 8); |
1206 | 0 | assert(Res < kNumberOfAccessSizes); |
1207 | 0 | return Res; |
1208 | 0 | } |
1209 | | |
1210 | | /// Check if \p G has been created by a trusted compiler pass. |
1211 | 0 | static bool GlobalWasGeneratedByCompiler(GlobalVariable *G) { |
1212 | | // Do not instrument @llvm.global_ctors, @llvm.used, etc. |
1213 | 0 | if (G->getName().starts_with("llvm.") || |
1214 | | // Do not instrument gcov counter arrays. |
1215 | 0 | G->getName().starts_with("__llvm_gcov_ctr") || |
1216 | | // Do not instrument rtti proxy symbols for function sanitizer. |
1217 | 0 | G->getName().starts_with("__llvm_rtti_proxy")) |
1218 | 0 | return true; |
1219 | | |
1220 | | // Do not instrument asan globals. |
1221 | 0 | if (G->getName().starts_with(kAsanGenPrefix) || |
1222 | 0 | G->getName().starts_with(kSanCovGenPrefix) || |
1223 | 0 | G->getName().starts_with(kODRGenPrefix)) |
1224 | 0 | return true; |
1225 | | |
1226 | 0 | return false; |
1227 | 0 | } |
1228 | | |
1229 | 0 | static bool isUnsupportedAMDGPUAddrspace(Value *Addr) { |
1230 | 0 | Type *PtrTy = cast<PointerType>(Addr->getType()->getScalarType()); |
1231 | 0 | unsigned int AddrSpace = PtrTy->getPointerAddressSpace(); |
1232 | 0 | if (AddrSpace == 3 || AddrSpace == 5) |
1233 | 0 | return true; |
1234 | 0 | return false; |
1235 | 0 | } |
1236 | | |
1237 | 0 | Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) { |
1238 | | // Shadow >> scale |
1239 | 0 | Shadow = IRB.CreateLShr(Shadow, Mapping.Scale); |
1240 | 0 | if (Mapping.Offset == 0) return Shadow; |
1241 | | // (Shadow >> scale) | offset |
1242 | 0 | Value *ShadowBase; |
1243 | 0 | if (LocalDynamicShadow) |
1244 | 0 | ShadowBase = LocalDynamicShadow; |
1245 | 0 | else |
1246 | 0 | ShadowBase = ConstantInt::get(IntptrTy, Mapping.Offset); |
1247 | 0 | if (Mapping.OrShadowOffset) |
1248 | 0 | return IRB.CreateOr(Shadow, ShadowBase); |
1249 | 0 | else |
1250 | 0 | return IRB.CreateAdd(Shadow, ShadowBase); |
1251 | 0 | } |
1252 | | |
1253 | | // Instrument memset/memmove/memcpy |
1254 | 0 | void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) { |
1255 | 0 | InstrumentationIRBuilder IRB(MI); |
1256 | 0 | if (isa<MemTransferInst>(MI)) { |
1257 | 0 | IRB.CreateCall(isa<MemMoveInst>(MI) ? AsanMemmove : AsanMemcpy, |
1258 | 0 | {MI->getOperand(0), MI->getOperand(1), |
1259 | 0 | IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); |
1260 | 0 | } else if (isa<MemSetInst>(MI)) { |
1261 | 0 | IRB.CreateCall( |
1262 | 0 | AsanMemset, |
1263 | 0 | {MI->getOperand(0), |
1264 | 0 | IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false), |
1265 | 0 | IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); |
1266 | 0 | } |
1267 | 0 | MI->eraseFromParent(); |
1268 | 0 | } |
1269 | | |
1270 | | /// Check if we want (and can) handle this alloca. |
1271 | 0 | bool AddressSanitizer::isInterestingAlloca(const AllocaInst &AI) { |
1272 | 0 | auto PreviouslySeenAllocaInfo = ProcessedAllocas.find(&AI); |
1273 | |
|
1274 | 0 | if (PreviouslySeenAllocaInfo != ProcessedAllocas.end()) |
1275 | 0 | return PreviouslySeenAllocaInfo->getSecond(); |
1276 | | |
1277 | 0 | bool IsInteresting = |
1278 | 0 | (AI.getAllocatedType()->isSized() && |
1279 | | // alloca() may be called with 0 size, ignore it. |
1280 | 0 | ((!AI.isStaticAlloca()) || !getAllocaSizeInBytes(AI).isZero()) && |
1281 | | // We are only interested in allocas not promotable to registers. |
1282 | | // Promotable allocas are common under -O0. |
1283 | 0 | (!ClSkipPromotableAllocas || !isAllocaPromotable(&AI)) && |
1284 | | // inalloca allocas are not treated as static, and we don't want |
1285 | | // dynamic alloca instrumentation for them as well. |
1286 | 0 | !AI.isUsedWithInAlloca() && |
1287 | | // swifterror allocas are register promoted by ISel |
1288 | 0 | !AI.isSwiftError() && |
1289 | | // safe allocas are not interesting |
1290 | 0 | !(SSGI && SSGI->isSafe(AI))); |
1291 | |
|
1292 | 0 | ProcessedAllocas[&AI] = IsInteresting; |
1293 | 0 | return IsInteresting; |
1294 | 0 | } |
1295 | | |
1296 | 0 | bool AddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) { |
1297 | | // Instrument accesses from different address spaces only for AMDGPU. |
1298 | 0 | Type *PtrTy = cast<PointerType>(Ptr->getType()->getScalarType()); |
1299 | 0 | if (PtrTy->getPointerAddressSpace() != 0 && |
1300 | 0 | !(TargetTriple.isAMDGPU() && !isUnsupportedAMDGPUAddrspace(Ptr))) |
1301 | 0 | return true; |
1302 | | |
1303 | | // Ignore swifterror addresses. |
1304 | | // swifterror memory addresses are mem2reg promoted by instruction |
1305 | | // selection. As such they cannot have regular uses like an instrumentation |
1306 | | // function and it makes no sense to track them as memory. |
1307 | 0 | if (Ptr->isSwiftError()) |
1308 | 0 | return true; |
1309 | | |
1310 | | // Treat memory accesses to promotable allocas as non-interesting since they |
1311 | | // will not cause memory violations. This greatly speeds up the instrumented |
1312 | | // executable at -O0. |
1313 | 0 | if (auto AI = dyn_cast_or_null<AllocaInst>(Ptr)) |
1314 | 0 | if (ClSkipPromotableAllocas && !isInterestingAlloca(*AI)) |
1315 | 0 | return true; |
1316 | | |
1317 | 0 | if (SSGI != nullptr && SSGI->stackAccessIsSafe(*Inst) && |
1318 | 0 | findAllocaForValue(Ptr)) |
1319 | 0 | return true; |
1320 | | |
1321 | 0 | return false; |
1322 | 0 | } |
1323 | | |
1324 | | void AddressSanitizer::getInterestingMemoryOperands( |
1325 | 0 | Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting) { |
1326 | | // Do not instrument the load fetching the dynamic shadow address. |
1327 | 0 | if (LocalDynamicShadow == I) |
1328 | 0 | return; |
1329 | | |
1330 | 0 | if (LoadInst *LI = dyn_cast<LoadInst>(I)) { |
1331 | 0 | if (!ClInstrumentReads || ignoreAccess(I, LI->getPointerOperand())) |
1332 | 0 | return; |
1333 | 0 | Interesting.emplace_back(I, LI->getPointerOperandIndex(), false, |
1334 | 0 | LI->getType(), LI->getAlign()); |
1335 | 0 | } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { |
1336 | 0 | if (!ClInstrumentWrites || ignoreAccess(I, SI->getPointerOperand())) |
1337 | 0 | return; |
1338 | 0 | Interesting.emplace_back(I, SI->getPointerOperandIndex(), true, |
1339 | 0 | SI->getValueOperand()->getType(), SI->getAlign()); |
1340 | 0 | } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { |
1341 | 0 | if (!ClInstrumentAtomics || ignoreAccess(I, RMW->getPointerOperand())) |
1342 | 0 | return; |
1343 | 0 | Interesting.emplace_back(I, RMW->getPointerOperandIndex(), true, |
1344 | 0 | RMW->getValOperand()->getType(), std::nullopt); |
1345 | 0 | } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { |
1346 | 0 | if (!ClInstrumentAtomics || ignoreAccess(I, XCHG->getPointerOperand())) |
1347 | 0 | return; |
1348 | 0 | Interesting.emplace_back(I, XCHG->getPointerOperandIndex(), true, |
1349 | 0 | XCHG->getCompareOperand()->getType(), |
1350 | 0 | std::nullopt); |
1351 | 0 | } else if (auto CI = dyn_cast<CallInst>(I)) { |
1352 | 0 | switch (CI->getIntrinsicID()) { |
1353 | 0 | case Intrinsic::masked_load: |
1354 | 0 | case Intrinsic::masked_store: |
1355 | 0 | case Intrinsic::masked_gather: |
1356 | 0 | case Intrinsic::masked_scatter: { |
1357 | 0 | bool IsWrite = CI->getType()->isVoidTy(); |
1358 | | // Masked store has an initial operand for the value. |
1359 | 0 | unsigned OpOffset = IsWrite ? 1 : 0; |
1360 | 0 | if (IsWrite ? !ClInstrumentWrites : !ClInstrumentReads) |
1361 | 0 | return; |
1362 | | |
1363 | 0 | auto BasePtr = CI->getOperand(OpOffset); |
1364 | 0 | if (ignoreAccess(I, BasePtr)) |
1365 | 0 | return; |
1366 | 0 | Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType(); |
1367 | 0 | MaybeAlign Alignment = Align(1); |
1368 | | // Otherwise no alignment guarantees. We probably got Undef. |
1369 | 0 | if (auto *Op = dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset))) |
1370 | 0 | Alignment = Op->getMaybeAlignValue(); |
1371 | 0 | Value *Mask = CI->getOperand(2 + OpOffset); |
1372 | 0 | Interesting.emplace_back(I, OpOffset, IsWrite, Ty, Alignment, Mask); |
1373 | 0 | break; |
1374 | 0 | } |
1375 | 0 | case Intrinsic::masked_expandload: |
1376 | 0 | case Intrinsic::masked_compressstore: { |
1377 | 0 | bool IsWrite = CI->getIntrinsicID() == Intrinsic::masked_compressstore; |
1378 | 0 | unsigned OpOffset = IsWrite ? 1 : 0; |
1379 | 0 | if (IsWrite ? !ClInstrumentWrites : !ClInstrumentReads) |
1380 | 0 | return; |
1381 | 0 | auto BasePtr = CI->getOperand(OpOffset); |
1382 | 0 | if (ignoreAccess(I, BasePtr)) |
1383 | 0 | return; |
1384 | 0 | MaybeAlign Alignment = BasePtr->getPointerAlignment(*DL); |
1385 | 0 | Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType(); |
1386 | |
|
1387 | 0 | IRBuilder IB(I); |
1388 | 0 | Value *Mask = CI->getOperand(1 + OpOffset); |
1389 | | // Use the popcount of Mask as the effective vector length. |
1390 | 0 | Type *ExtTy = VectorType::get(IntptrTy, cast<VectorType>(Ty)); |
1391 | 0 | Value *ExtMask = IB.CreateZExt(Mask, ExtTy); |
1392 | 0 | Value *EVL = IB.CreateAddReduce(ExtMask); |
1393 | 0 | Value *TrueMask = ConstantInt::get(Mask->getType(), 1); |
1394 | 0 | Interesting.emplace_back(I, OpOffset, IsWrite, Ty, Alignment, TrueMask, |
1395 | 0 | EVL); |
1396 | 0 | break; |
1397 | 0 | } |
1398 | 0 | case Intrinsic::vp_load: |
1399 | 0 | case Intrinsic::vp_store: |
1400 | 0 | case Intrinsic::experimental_vp_strided_load: |
1401 | 0 | case Intrinsic::experimental_vp_strided_store: { |
1402 | 0 | auto *VPI = cast<VPIntrinsic>(CI); |
1403 | 0 | unsigned IID = CI->getIntrinsicID(); |
1404 | 0 | bool IsWrite = CI->getType()->isVoidTy(); |
1405 | 0 | if (IsWrite ? !ClInstrumentWrites : !ClInstrumentReads) |
1406 | 0 | return; |
1407 | 0 | unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID); |
1408 | 0 | Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType(); |
1409 | 0 | MaybeAlign Alignment = VPI->getOperand(PtrOpNo)->getPointerAlignment(*DL); |
1410 | 0 | Value *Stride = nullptr; |
1411 | 0 | if (IID == Intrinsic::experimental_vp_strided_store || |
1412 | 0 | IID == Intrinsic::experimental_vp_strided_load) { |
1413 | 0 | Stride = VPI->getOperand(PtrOpNo + 1); |
1414 | | // Use the pointer alignment as the element alignment if the stride is a |
1415 | | // mutiple of the pointer alignment. Otherwise, the element alignment |
1416 | | // should be Align(1). |
1417 | 0 | unsigned PointerAlign = Alignment.valueOrOne().value(); |
1418 | 0 | if (!isa<ConstantInt>(Stride) || |
1419 | 0 | cast<ConstantInt>(Stride)->getZExtValue() % PointerAlign != 0) |
1420 | 0 | Alignment = Align(1); |
1421 | 0 | } |
1422 | 0 | Interesting.emplace_back(I, PtrOpNo, IsWrite, Ty, Alignment, |
1423 | 0 | VPI->getMaskParam(), VPI->getVectorLengthParam(), |
1424 | 0 | Stride); |
1425 | 0 | break; |
1426 | 0 | } |
1427 | 0 | case Intrinsic::vp_gather: |
1428 | 0 | case Intrinsic::vp_scatter: { |
1429 | 0 | auto *VPI = cast<VPIntrinsic>(CI); |
1430 | 0 | unsigned IID = CI->getIntrinsicID(); |
1431 | 0 | bool IsWrite = IID == Intrinsic::vp_scatter; |
1432 | 0 | if (IsWrite ? !ClInstrumentWrites : !ClInstrumentReads) |
1433 | 0 | return; |
1434 | 0 | unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID); |
1435 | 0 | Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType(); |
1436 | 0 | MaybeAlign Alignment = VPI->getPointerAlignment(); |
1437 | 0 | Interesting.emplace_back(I, PtrOpNo, IsWrite, Ty, Alignment, |
1438 | 0 | VPI->getMaskParam(), |
1439 | 0 | VPI->getVectorLengthParam()); |
1440 | 0 | break; |
1441 | 0 | } |
1442 | 0 | default: |
1443 | 0 | for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) { |
1444 | 0 | if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) || |
1445 | 0 | ignoreAccess(I, CI->getArgOperand(ArgNo))) |
1446 | 0 | continue; |
1447 | 0 | Type *Ty = CI->getParamByValType(ArgNo); |
1448 | 0 | Interesting.emplace_back(I, ArgNo, false, Ty, Align(1)); |
1449 | 0 | } |
1450 | 0 | } |
1451 | 0 | } |
1452 | 0 | } |
1453 | | |
1454 | 0 | static bool isPointerOperand(Value *V) { |
1455 | 0 | return V->getType()->isPointerTy() || isa<PtrToIntInst>(V); |
1456 | 0 | } |
1457 | | |
1458 | | // This is a rough heuristic; it may cause both false positives and |
1459 | | // false negatives. The proper implementation requires cooperation with |
1460 | | // the frontend. |
1461 | 0 | static bool isInterestingPointerComparison(Instruction *I) { |
1462 | 0 | if (ICmpInst *Cmp = dyn_cast<ICmpInst>(I)) { |
1463 | 0 | if (!Cmp->isRelational()) |
1464 | 0 | return false; |
1465 | 0 | } else { |
1466 | 0 | return false; |
1467 | 0 | } |
1468 | 0 | return isPointerOperand(I->getOperand(0)) && |
1469 | 0 | isPointerOperand(I->getOperand(1)); |
1470 | 0 | } |
1471 | | |
1472 | | // This is a rough heuristic; it may cause both false positives and |
1473 | | // false negatives. The proper implementation requires cooperation with |
1474 | | // the frontend. |
1475 | 0 | static bool isInterestingPointerSubtraction(Instruction *I) { |
1476 | 0 | if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I)) { |
1477 | 0 | if (BO->getOpcode() != Instruction::Sub) |
1478 | 0 | return false; |
1479 | 0 | } else { |
1480 | 0 | return false; |
1481 | 0 | } |
1482 | 0 | return isPointerOperand(I->getOperand(0)) && |
1483 | 0 | isPointerOperand(I->getOperand(1)); |
1484 | 0 | } |
1485 | | |
1486 | 0 | bool AddressSanitizer::GlobalIsLinkerInitialized(GlobalVariable *G) { |
1487 | | // If a global variable does not have dynamic initialization we don't |
1488 | | // have to instrument it. However, if a global does not have initializer |
1489 | | // at all, we assume it has dynamic initializer (in other TU). |
1490 | 0 | if (!G->hasInitializer()) |
1491 | 0 | return false; |
1492 | | |
1493 | 0 | if (G->hasSanitizerMetadata() && G->getSanitizerMetadata().IsDynInit) |
1494 | 0 | return false; |
1495 | | |
1496 | 0 | return true; |
1497 | 0 | } |
1498 | | |
1499 | | void AddressSanitizer::instrumentPointerComparisonOrSubtraction( |
1500 | 0 | Instruction *I) { |
1501 | 0 | IRBuilder<> IRB(I); |
1502 | 0 | FunctionCallee F = isa<ICmpInst>(I) ? AsanPtrCmpFunction : AsanPtrSubFunction; |
1503 | 0 | Value *Param[2] = {I->getOperand(0), I->getOperand(1)}; |
1504 | 0 | for (Value *&i : Param) { |
1505 | 0 | if (i->getType()->isPointerTy()) |
1506 | 0 | i = IRB.CreatePointerCast(i, IntptrTy); |
1507 | 0 | } |
1508 | 0 | IRB.CreateCall(F, Param); |
1509 | 0 | } |
1510 | | |
1511 | | static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I, |
1512 | | Instruction *InsertBefore, Value *Addr, |
1513 | | MaybeAlign Alignment, unsigned Granularity, |
1514 | | TypeSize TypeStoreSize, bool IsWrite, |
1515 | | Value *SizeArgument, bool UseCalls, |
1516 | 0 | uint32_t Exp) { |
1517 | | // Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check |
1518 | | // if the data is properly aligned. |
1519 | 0 | if (!TypeStoreSize.isScalable()) { |
1520 | 0 | const auto FixedSize = TypeStoreSize.getFixedValue(); |
1521 | 0 | switch (FixedSize) { |
1522 | 0 | case 8: |
1523 | 0 | case 16: |
1524 | 0 | case 32: |
1525 | 0 | case 64: |
1526 | 0 | case 128: |
1527 | 0 | if (!Alignment || *Alignment >= Granularity || |
1528 | 0 | *Alignment >= FixedSize / 8) |
1529 | 0 | return Pass->instrumentAddress(I, InsertBefore, Addr, Alignment, |
1530 | 0 | FixedSize, IsWrite, nullptr, UseCalls, |
1531 | 0 | Exp); |
1532 | 0 | } |
1533 | 0 | } |
1534 | 0 | Pass->instrumentUnusualSizeOrAlignment(I, InsertBefore, Addr, TypeStoreSize, |
1535 | 0 | IsWrite, nullptr, UseCalls, Exp); |
1536 | 0 | } |
1537 | | |
1538 | | void AddressSanitizer::instrumentMaskedLoadOrStore( |
1539 | | AddressSanitizer *Pass, const DataLayout &DL, Type *IntptrTy, Value *Mask, |
1540 | | Value *EVL, Value *Stride, Instruction *I, Value *Addr, |
1541 | | MaybeAlign Alignment, unsigned Granularity, Type *OpType, bool IsWrite, |
1542 | 0 | Value *SizeArgument, bool UseCalls, uint32_t Exp) { |
1543 | 0 | auto *VTy = cast<VectorType>(OpType); |
1544 | 0 | TypeSize ElemTypeSize = DL.getTypeStoreSizeInBits(VTy->getScalarType()); |
1545 | 0 | auto Zero = ConstantInt::get(IntptrTy, 0); |
1546 | |
|
1547 | 0 | IRBuilder IB(I); |
1548 | 0 | Instruction *LoopInsertBefore = I; |
1549 | 0 | if (EVL) { |
1550 | | // The end argument of SplitBlockAndInsertForLane is assumed bigger |
1551 | | // than zero, so we should check whether EVL is zero here. |
1552 | 0 | Type *EVLType = EVL->getType(); |
1553 | 0 | Value *IsEVLZero = IB.CreateICmpNE(EVL, ConstantInt::get(EVLType, 0)); |
1554 | 0 | LoopInsertBefore = SplitBlockAndInsertIfThen(IsEVLZero, I, false); |
1555 | 0 | IB.SetInsertPoint(LoopInsertBefore); |
1556 | | // Cast EVL to IntptrTy. |
1557 | 0 | EVL = IB.CreateZExtOrTrunc(EVL, IntptrTy); |
1558 | | // To avoid undefined behavior for extracting with out of range index, use |
1559 | | // the minimum of evl and element count as trip count. |
1560 | 0 | Value *EC = IB.CreateElementCount(IntptrTy, VTy->getElementCount()); |
1561 | 0 | EVL = IB.CreateBinaryIntrinsic(Intrinsic::umin, EVL, EC); |
1562 | 0 | } else { |
1563 | 0 | EVL = IB.CreateElementCount(IntptrTy, VTy->getElementCount()); |
1564 | 0 | } |
1565 | | |
1566 | | // Cast Stride to IntptrTy. |
1567 | 0 | if (Stride) |
1568 | 0 | Stride = IB.CreateZExtOrTrunc(Stride, IntptrTy); |
1569 | |
|
1570 | 0 | SplitBlockAndInsertForEachLane(EVL, LoopInsertBefore, |
1571 | 0 | [&](IRBuilderBase &IRB, Value *Index) { |
1572 | 0 | Value *MaskElem = IRB.CreateExtractElement(Mask, Index); |
1573 | 0 | if (auto *MaskElemC = dyn_cast<ConstantInt>(MaskElem)) { |
1574 | 0 | if (MaskElemC->isZero()) |
1575 | | // No check |
1576 | 0 | return; |
1577 | | // Unconditional check |
1578 | 0 | } else { |
1579 | | // Conditional check |
1580 | 0 | Instruction *ThenTerm = SplitBlockAndInsertIfThen( |
1581 | 0 | MaskElem, &*IRB.GetInsertPoint(), false); |
1582 | 0 | IRB.SetInsertPoint(ThenTerm); |
1583 | 0 | } |
1584 | | |
1585 | 0 | Value *InstrumentedAddress; |
1586 | 0 | if (isa<VectorType>(Addr->getType())) { |
1587 | 0 | assert( |
1588 | 0 | cast<VectorType>(Addr->getType())->getElementType()->isPointerTy() && |
1589 | 0 | "Expected vector of pointer."); |
1590 | 0 | InstrumentedAddress = IRB.CreateExtractElement(Addr, Index); |
1591 | 0 | } else if (Stride) { |
1592 | 0 | Index = IRB.CreateMul(Index, Stride); |
1593 | 0 | InstrumentedAddress = IRB.CreatePtrAdd(Addr, Index); |
1594 | 0 | } else { |
1595 | 0 | InstrumentedAddress = IRB.CreateGEP(VTy, Addr, {Zero, Index}); |
1596 | 0 | } |
1597 | 0 | doInstrumentAddress(Pass, I, &*IRB.GetInsertPoint(), |
1598 | 0 | InstrumentedAddress, Alignment, Granularity, |
1599 | 0 | ElemTypeSize, IsWrite, SizeArgument, UseCalls, Exp); |
1600 | 0 | }); |
1601 | 0 | } |
1602 | | |
1603 | | void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis, |
1604 | | InterestingMemoryOperand &O, bool UseCalls, |
1605 | 0 | const DataLayout &DL) { |
1606 | 0 | Value *Addr = O.getPtr(); |
1607 | | |
1608 | | // Optimization experiments. |
1609 | | // The experiments can be used to evaluate potential optimizations that remove |
1610 | | // instrumentation (assess false negatives). Instead of completely removing |
1611 | | // some instrumentation, you set Exp to a non-zero value (mask of optimization |
1612 | | // experiments that want to remove instrumentation of this instruction). |
1613 | | // If Exp is non-zero, this pass will emit special calls into runtime |
1614 | | // (e.g. __asan_report_exp_load1 instead of __asan_report_load1). These calls |
1615 | | // make runtime terminate the program in a special way (with a different |
1616 | | // exit status). Then you run the new compiler on a buggy corpus, collect |
1617 | | // the special terminations (ideally, you don't see them at all -- no false |
1618 | | // negatives) and make the decision on the optimization. |
1619 | 0 | uint32_t Exp = ClForceExperiment; |
1620 | |
|
1621 | 0 | if (ClOpt && ClOptGlobals) { |
1622 | | // If initialization order checking is disabled, a simple access to a |
1623 | | // dynamically initialized global is always valid. |
1624 | 0 | GlobalVariable *G = dyn_cast<GlobalVariable>(getUnderlyingObject(Addr)); |
1625 | 0 | if (G && (!ClInitializers || GlobalIsLinkerInitialized(G)) && |
1626 | 0 | isSafeAccess(ObjSizeVis, Addr, O.TypeStoreSize)) { |
1627 | 0 | NumOptimizedAccessesToGlobalVar++; |
1628 | 0 | return; |
1629 | 0 | } |
1630 | 0 | } |
1631 | | |
1632 | 0 | if (ClOpt && ClOptStack) { |
1633 | | // A direct inbounds access to a stack variable is always valid. |
1634 | 0 | if (isa<AllocaInst>(getUnderlyingObject(Addr)) && |
1635 | 0 | isSafeAccess(ObjSizeVis, Addr, O.TypeStoreSize)) { |
1636 | 0 | NumOptimizedAccessesToStackVar++; |
1637 | 0 | return; |
1638 | 0 | } |
1639 | 0 | } |
1640 | | |
1641 | 0 | if (O.IsWrite) |
1642 | 0 | NumInstrumentedWrites++; |
1643 | 0 | else |
1644 | 0 | NumInstrumentedReads++; |
1645 | |
|
1646 | 0 | unsigned Granularity = 1 << Mapping.Scale; |
1647 | 0 | if (O.MaybeMask) { |
1648 | 0 | instrumentMaskedLoadOrStore(this, DL, IntptrTy, O.MaybeMask, O.MaybeEVL, |
1649 | 0 | O.MaybeStride, O.getInsn(), Addr, O.Alignment, |
1650 | 0 | Granularity, O.OpType, O.IsWrite, nullptr, |
1651 | 0 | UseCalls, Exp); |
1652 | 0 | } else { |
1653 | 0 | doInstrumentAddress(this, O.getInsn(), O.getInsn(), Addr, O.Alignment, |
1654 | 0 | Granularity, O.TypeStoreSize, O.IsWrite, nullptr, UseCalls, |
1655 | 0 | Exp); |
1656 | 0 | } |
1657 | 0 | } |
1658 | | |
1659 | | Instruction *AddressSanitizer::generateCrashCode(Instruction *InsertBefore, |
1660 | | Value *Addr, bool IsWrite, |
1661 | | size_t AccessSizeIndex, |
1662 | | Value *SizeArgument, |
1663 | 0 | uint32_t Exp) { |
1664 | 0 | InstrumentationIRBuilder IRB(InsertBefore); |
1665 | 0 | Value *ExpVal = Exp == 0 ? nullptr : ConstantInt::get(IRB.getInt32Ty(), Exp); |
1666 | 0 | CallInst *Call = nullptr; |
1667 | 0 | if (SizeArgument) { |
1668 | 0 | if (Exp == 0) |
1669 | 0 | Call = IRB.CreateCall(AsanErrorCallbackSized[IsWrite][0], |
1670 | 0 | {Addr, SizeArgument}); |
1671 | 0 | else |
1672 | 0 | Call = IRB.CreateCall(AsanErrorCallbackSized[IsWrite][1], |
1673 | 0 | {Addr, SizeArgument, ExpVal}); |
1674 | 0 | } else { |
1675 | 0 | if (Exp == 0) |
1676 | 0 | Call = |
1677 | 0 | IRB.CreateCall(AsanErrorCallback[IsWrite][0][AccessSizeIndex], Addr); |
1678 | 0 | else |
1679 | 0 | Call = IRB.CreateCall(AsanErrorCallback[IsWrite][1][AccessSizeIndex], |
1680 | 0 | {Addr, ExpVal}); |
1681 | 0 | } |
1682 | |
|
1683 | 0 | Call->setCannotMerge(); |
1684 | 0 | return Call; |
1685 | 0 | } |
1686 | | |
1687 | | Value *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, |
1688 | | Value *ShadowValue, |
1689 | 0 | uint32_t TypeStoreSize) { |
1690 | 0 | size_t Granularity = static_cast<size_t>(1) << Mapping.Scale; |
1691 | | // Addr & (Granularity - 1) |
1692 | 0 | Value *LastAccessedByte = |
1693 | 0 | IRB.CreateAnd(AddrLong, ConstantInt::get(IntptrTy, Granularity - 1)); |
1694 | | // (Addr & (Granularity - 1)) + size - 1 |
1695 | 0 | if (TypeStoreSize / 8 > 1) |
1696 | 0 | LastAccessedByte = IRB.CreateAdd( |
1697 | 0 | LastAccessedByte, ConstantInt::get(IntptrTy, TypeStoreSize / 8 - 1)); |
1698 | | // (uint8_t) ((Addr & (Granularity-1)) + size - 1) |
1699 | 0 | LastAccessedByte = |
1700 | 0 | IRB.CreateIntCast(LastAccessedByte, ShadowValue->getType(), false); |
1701 | | // ((uint8_t) ((Addr & (Granularity-1)) + size - 1)) >= ShadowValue |
1702 | 0 | return IRB.CreateICmpSGE(LastAccessedByte, ShadowValue); |
1703 | 0 | } |
1704 | | |
1705 | | Instruction *AddressSanitizer::instrumentAMDGPUAddress( |
1706 | | Instruction *OrigIns, Instruction *InsertBefore, Value *Addr, |
1707 | 0 | uint32_t TypeStoreSize, bool IsWrite, Value *SizeArgument) { |
1708 | | // Do not instrument unsupported addrspaces. |
1709 | 0 | if (isUnsupportedAMDGPUAddrspace(Addr)) |
1710 | 0 | return nullptr; |
1711 | 0 | Type *PtrTy = cast<PointerType>(Addr->getType()->getScalarType()); |
1712 | | // Follow host instrumentation for global and constant addresses. |
1713 | 0 | if (PtrTy->getPointerAddressSpace() != 0) |
1714 | 0 | return InsertBefore; |
1715 | | // Instrument generic addresses in supported addressspaces. |
1716 | 0 | IRBuilder<> IRB(InsertBefore); |
1717 | 0 | Value *IsShared = IRB.CreateCall(AMDGPUAddressShared, {Addr}); |
1718 | 0 | Value *IsPrivate = IRB.CreateCall(AMDGPUAddressPrivate, {Addr}); |
1719 | 0 | Value *IsSharedOrPrivate = IRB.CreateOr(IsShared, IsPrivate); |
1720 | 0 | Value *Cmp = IRB.CreateNot(IsSharedOrPrivate); |
1721 | 0 | Value *AddrSpaceZeroLanding = |
1722 | 0 | SplitBlockAndInsertIfThen(Cmp, InsertBefore, false); |
1723 | 0 | InsertBefore = cast<Instruction>(AddrSpaceZeroLanding); |
1724 | 0 | return InsertBefore; |
1725 | 0 | } |
1726 | | |
1727 | | Instruction *AddressSanitizer::genAMDGPUReportBlock(IRBuilder<> &IRB, |
1728 | 0 | Value *Cond, bool Recover) { |
1729 | 0 | Module &M = *IRB.GetInsertBlock()->getModule(); |
1730 | 0 | Value *ReportCond = Cond; |
1731 | 0 | if (!Recover) { |
1732 | 0 | auto Ballot = M.getOrInsertFunction(kAMDGPUBallotName, IRB.getInt64Ty(), |
1733 | 0 | IRB.getInt1Ty()); |
1734 | 0 | ReportCond = IRB.CreateIsNotNull(IRB.CreateCall(Ballot, {Cond})); |
1735 | 0 | } |
1736 | |
|
1737 | 0 | auto *Trm = |
1738 | 0 | SplitBlockAndInsertIfThen(ReportCond, &*IRB.GetInsertPoint(), false, |
1739 | 0 | MDBuilder(*C).createBranchWeights(1, 100000)); |
1740 | 0 | Trm->getParent()->setName("asan.report"); |
1741 | |
|
1742 | 0 | if (Recover) |
1743 | 0 | return Trm; |
1744 | | |
1745 | 0 | Trm = SplitBlockAndInsertIfThen(Cond, Trm, false); |
1746 | 0 | IRB.SetInsertPoint(Trm); |
1747 | 0 | return IRB.CreateCall( |
1748 | 0 | M.getOrInsertFunction(kAMDGPUUnreachableName, IRB.getVoidTy()), {}); |
1749 | 0 | } |
1750 | | |
1751 | | void AddressSanitizer::instrumentAddress(Instruction *OrigIns, |
1752 | | Instruction *InsertBefore, Value *Addr, |
1753 | | MaybeAlign Alignment, |
1754 | | uint32_t TypeStoreSize, bool IsWrite, |
1755 | | Value *SizeArgument, bool UseCalls, |
1756 | 0 | uint32_t Exp) { |
1757 | 0 | if (TargetTriple.isAMDGPU()) { |
1758 | 0 | InsertBefore = instrumentAMDGPUAddress(OrigIns, InsertBefore, Addr, |
1759 | 0 | TypeStoreSize, IsWrite, SizeArgument); |
1760 | 0 | if (!InsertBefore) |
1761 | 0 | return; |
1762 | 0 | } |
1763 | | |
1764 | 0 | InstrumentationIRBuilder IRB(InsertBefore); |
1765 | 0 | size_t AccessSizeIndex = TypeStoreSizeToSizeIndex(TypeStoreSize); |
1766 | 0 | const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex); |
1767 | |
|
1768 | 0 | if (UseCalls && ClOptimizeCallbacks) { |
1769 | 0 | const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex); |
1770 | 0 | Module *M = IRB.GetInsertBlock()->getParent()->getParent(); |
1771 | 0 | IRB.CreateCall( |
1772 | 0 | Intrinsic::getDeclaration(M, Intrinsic::asan_check_memaccess), |
1773 | 0 | {IRB.CreatePointerCast(Addr, PtrTy), |
1774 | 0 | ConstantInt::get(Int32Ty, AccessInfo.Packed)}); |
1775 | 0 | return; |
1776 | 0 | } |
1777 | | |
1778 | 0 | Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); |
1779 | 0 | if (UseCalls) { |
1780 | 0 | if (Exp == 0) |
1781 | 0 | IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], |
1782 | 0 | AddrLong); |
1783 | 0 | else |
1784 | 0 | IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex], |
1785 | 0 | {AddrLong, ConstantInt::get(IRB.getInt32Ty(), Exp)}); |
1786 | 0 | return; |
1787 | 0 | } |
1788 | | |
1789 | 0 | Type *ShadowTy = |
1790 | 0 | IntegerType::get(*C, std::max(8U, TypeStoreSize >> Mapping.Scale)); |
1791 | 0 | Type *ShadowPtrTy = PointerType::get(ShadowTy, 0); |
1792 | 0 | Value *ShadowPtr = memToShadow(AddrLong, IRB); |
1793 | 0 | const uint64_t ShadowAlign = |
1794 | 0 | std::max<uint64_t>(Alignment.valueOrOne().value() >> Mapping.Scale, 1); |
1795 | 0 | Value *ShadowValue = IRB.CreateAlignedLoad( |
1796 | 0 | ShadowTy, IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy), Align(ShadowAlign)); |
1797 | |
|
1798 | 0 | Value *Cmp = IRB.CreateIsNotNull(ShadowValue); |
1799 | 0 | size_t Granularity = 1ULL << Mapping.Scale; |
1800 | 0 | Instruction *CrashTerm = nullptr; |
1801 | |
|
1802 | 0 | bool GenSlowPath = (ClAlwaysSlowPath || (TypeStoreSize < 8 * Granularity)); |
1803 | |
|
1804 | 0 | if (TargetTriple.isAMDGCN()) { |
1805 | 0 | if (GenSlowPath) { |
1806 | 0 | auto *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize); |
1807 | 0 | Cmp = IRB.CreateAnd(Cmp, Cmp2); |
1808 | 0 | } |
1809 | 0 | CrashTerm = genAMDGPUReportBlock(IRB, Cmp, Recover); |
1810 | 0 | } else if (GenSlowPath) { |
1811 | | // We use branch weights for the slow path check, to indicate that the slow |
1812 | | // path is rarely taken. This seems to be the case for SPEC benchmarks. |
1813 | 0 | Instruction *CheckTerm = SplitBlockAndInsertIfThen( |
1814 | 0 | Cmp, InsertBefore, false, MDBuilder(*C).createBranchWeights(1, 100000)); |
1815 | 0 | assert(cast<BranchInst>(CheckTerm)->isUnconditional()); |
1816 | 0 | BasicBlock *NextBB = CheckTerm->getSuccessor(0); |
1817 | 0 | IRB.SetInsertPoint(CheckTerm); |
1818 | 0 | Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize); |
1819 | 0 | if (Recover) { |
1820 | 0 | CrashTerm = SplitBlockAndInsertIfThen(Cmp2, CheckTerm, false); |
1821 | 0 | } else { |
1822 | 0 | BasicBlock *CrashBlock = |
1823 | 0 | BasicBlock::Create(*C, "", NextBB->getParent(), NextBB); |
1824 | 0 | CrashTerm = new UnreachableInst(*C, CrashBlock); |
1825 | 0 | BranchInst *NewTerm = BranchInst::Create(CrashBlock, NextBB, Cmp2); |
1826 | 0 | ReplaceInstWithInst(CheckTerm, NewTerm); |
1827 | 0 | } |
1828 | 0 | } else { |
1829 | 0 | CrashTerm = SplitBlockAndInsertIfThen(Cmp, InsertBefore, !Recover); |
1830 | 0 | } |
1831 | | |
1832 | 0 | Instruction *Crash = generateCrashCode(CrashTerm, AddrLong, IsWrite, |
1833 | 0 | AccessSizeIndex, SizeArgument, Exp); |
1834 | 0 | if (OrigIns->getDebugLoc()) |
1835 | 0 | Crash->setDebugLoc(OrigIns->getDebugLoc()); |
1836 | 0 | } |
1837 | | |
1838 | | // Instrument unusual size or unusual alignment. |
1839 | | // We can not do it with a single check, so we do 1-byte check for the first |
1840 | | // and the last bytes. We call __asan_report_*_n(addr, real_size) to be able |
1841 | | // to report the actual access size. |
1842 | | void AddressSanitizer::instrumentUnusualSizeOrAlignment( |
1843 | | Instruction *I, Instruction *InsertBefore, Value *Addr, TypeSize TypeStoreSize, |
1844 | 0 | bool IsWrite, Value *SizeArgument, bool UseCalls, uint32_t Exp) { |
1845 | 0 | InstrumentationIRBuilder IRB(InsertBefore); |
1846 | 0 | Value *NumBits = IRB.CreateTypeSize(IntptrTy, TypeStoreSize); |
1847 | 0 | Value *Size = IRB.CreateLShr(NumBits, ConstantInt::get(IntptrTy, 3)); |
1848 | |
|
1849 | 0 | Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); |
1850 | 0 | if (UseCalls) { |
1851 | 0 | if (Exp == 0) |
1852 | 0 | IRB.CreateCall(AsanMemoryAccessCallbackSized[IsWrite][0], |
1853 | 0 | {AddrLong, Size}); |
1854 | 0 | else |
1855 | 0 | IRB.CreateCall(AsanMemoryAccessCallbackSized[IsWrite][1], |
1856 | 0 | {AddrLong, Size, ConstantInt::get(IRB.getInt32Ty(), Exp)}); |
1857 | 0 | } else { |
1858 | 0 | Value *SizeMinusOne = IRB.CreateSub(Size, ConstantInt::get(IntptrTy, 1)); |
1859 | 0 | Value *LastByte = IRB.CreateIntToPtr( |
1860 | 0 | IRB.CreateAdd(AddrLong, SizeMinusOne), |
1861 | 0 | Addr->getType()); |
1862 | 0 | instrumentAddress(I, InsertBefore, Addr, {}, 8, IsWrite, Size, false, Exp); |
1863 | 0 | instrumentAddress(I, InsertBefore, LastByte, {}, 8, IsWrite, Size, false, |
1864 | 0 | Exp); |
1865 | 0 | } |
1866 | 0 | } |
1867 | | |
1868 | | void ModuleAddressSanitizer::poisonOneInitializer(Function &GlobalInit, |
1869 | 0 | GlobalValue *ModuleName) { |
1870 | | // Set up the arguments to our poison/unpoison functions. |
1871 | 0 | IRBuilder<> IRB(&GlobalInit.front(), |
1872 | 0 | GlobalInit.front().getFirstInsertionPt()); |
1873 | | |
1874 | | // Add a call to poison all external globals before the given function starts. |
1875 | 0 | Value *ModuleNameAddr = ConstantExpr::getPointerCast(ModuleName, IntptrTy); |
1876 | 0 | IRB.CreateCall(AsanPoisonGlobals, ModuleNameAddr); |
1877 | | |
1878 | | // Add calls to unpoison all globals before each return instruction. |
1879 | 0 | for (auto &BB : GlobalInit) |
1880 | 0 | if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) |
1881 | 0 | CallInst::Create(AsanUnpoisonGlobals, "", RI); |
1882 | 0 | } |
1883 | | |
1884 | | void ModuleAddressSanitizer::createInitializerPoisonCalls( |
1885 | 0 | Module &M, GlobalValue *ModuleName) { |
1886 | 0 | GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); |
1887 | 0 | if (!GV) |
1888 | 0 | return; |
1889 | | |
1890 | 0 | ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer()); |
1891 | 0 | if (!CA) |
1892 | 0 | return; |
1893 | | |
1894 | 0 | for (Use &OP : CA->operands()) { |
1895 | 0 | if (isa<ConstantAggregateZero>(OP)) continue; |
1896 | 0 | ConstantStruct *CS = cast<ConstantStruct>(OP); |
1897 | | |
1898 | | // Must have a function or null ptr. |
1899 | 0 | if (Function *F = dyn_cast<Function>(CS->getOperand(1))) { |
1900 | 0 | if (F->getName() == kAsanModuleCtorName) continue; |
1901 | 0 | auto *Priority = cast<ConstantInt>(CS->getOperand(0)); |
1902 | | // Don't instrument CTORs that will run before asan.module_ctor. |
1903 | 0 | if (Priority->getLimitedValue() <= GetCtorAndDtorPriority(TargetTriple)) |
1904 | 0 | continue; |
1905 | 0 | poisonOneInitializer(*F, ModuleName); |
1906 | 0 | } |
1907 | 0 | } |
1908 | 0 | } |
1909 | | |
1910 | | const GlobalVariable * |
1911 | 0 | ModuleAddressSanitizer::getExcludedAliasedGlobal(const GlobalAlias &GA) const { |
1912 | | // In case this function should be expanded to include rules that do not just |
1913 | | // apply when CompileKernel is true, either guard all existing rules with an |
1914 | | // 'if (CompileKernel) { ... }' or be absolutely sure that all these rules |
1915 | | // should also apply to user space. |
1916 | 0 | assert(CompileKernel && "Only expecting to be called when compiling kernel"); |
1917 | | |
1918 | 0 | const Constant *C = GA.getAliasee(); |
1919 | | |
1920 | | // When compiling the kernel, globals that are aliased by symbols prefixed |
1921 | | // by "__" are special and cannot be padded with a redzone. |
1922 | 0 | if (GA.getName().starts_with("__")) |
1923 | 0 | return dyn_cast<GlobalVariable>(C->stripPointerCastsAndAliases()); |
1924 | | |
1925 | 0 | return nullptr; |
1926 | 0 | } |
1927 | | |
1928 | 0 | bool ModuleAddressSanitizer::shouldInstrumentGlobal(GlobalVariable *G) const { |
1929 | 0 | Type *Ty = G->getValueType(); |
1930 | 0 | LLVM_DEBUG(dbgs() << "GLOBAL: " << *G << "\n"); |
1931 | |
|
1932 | 0 | if (G->hasSanitizerMetadata() && G->getSanitizerMetadata().NoAddress) |
1933 | 0 | return false; |
1934 | 0 | if (!Ty->isSized()) return false; |
1935 | 0 | if (!G->hasInitializer()) return false; |
1936 | | // Globals in address space 1 and 4 are supported for AMDGPU. |
1937 | 0 | if (G->getAddressSpace() && |
1938 | 0 | !(TargetTriple.isAMDGPU() && !isUnsupportedAMDGPUAddrspace(G))) |
1939 | 0 | return false; |
1940 | 0 | if (GlobalWasGeneratedByCompiler(G)) return false; // Our own globals. |
1941 | | // Two problems with thread-locals: |
1942 | | // - The address of the main thread's copy can't be computed at link-time. |
1943 | | // - Need to poison all copies, not just the main thread's one. |
1944 | 0 | if (G->isThreadLocal()) return false; |
1945 | | // For now, just ignore this Global if the alignment is large. |
1946 | 0 | if (G->getAlign() && *G->getAlign() > getMinRedzoneSizeForGlobal()) return false; |
1947 | | |
1948 | | // For non-COFF targets, only instrument globals known to be defined by this |
1949 | | // TU. |
1950 | | // FIXME: We can instrument comdat globals on ELF if we are using the |
1951 | | // GC-friendly metadata scheme. |
1952 | 0 | if (!TargetTriple.isOSBinFormatCOFF()) { |
1953 | 0 | if (!G->hasExactDefinition() || G->hasComdat()) |
1954 | 0 | return false; |
1955 | 0 | } else { |
1956 | | // On COFF, don't instrument non-ODR linkages. |
1957 | 0 | if (G->isInterposable()) |
1958 | 0 | return false; |
1959 | 0 | } |
1960 | | |
1961 | | // If a comdat is present, it must have a selection kind that implies ODR |
1962 | | // semantics: no duplicates, any, or exact match. |
1963 | 0 | if (Comdat *C = G->getComdat()) { |
1964 | 0 | switch (C->getSelectionKind()) { |
1965 | 0 | case Comdat::Any: |
1966 | 0 | case Comdat::ExactMatch: |
1967 | 0 | case Comdat::NoDeduplicate: |
1968 | 0 | break; |
1969 | 0 | case Comdat::Largest: |
1970 | 0 | case Comdat::SameSize: |
1971 | 0 | return false; |
1972 | 0 | } |
1973 | 0 | } |
1974 | | |
1975 | 0 | if (G->hasSection()) { |
1976 | | // The kernel uses explicit sections for mostly special global variables |
1977 | | // that we should not instrument. E.g. the kernel may rely on their layout |
1978 | | // without redzones, or remove them at link time ("discard.*"), etc. |
1979 | 0 | if (CompileKernel) |
1980 | 0 | return false; |
1981 | | |
1982 | 0 | StringRef Section = G->getSection(); |
1983 | | |
1984 | | // Globals from llvm.metadata aren't emitted, do not instrument them. |
1985 | 0 | if (Section == "llvm.metadata") return false; |
1986 | | // Do not instrument globals from special LLVM sections. |
1987 | 0 | if (Section.contains("__llvm") || Section.contains("__LLVM")) |
1988 | 0 | return false; |
1989 | | |
1990 | | // Do not instrument function pointers to initialization and termination |
1991 | | // routines: dynamic linker will not properly handle redzones. |
1992 | 0 | if (Section.starts_with(".preinit_array") || |
1993 | 0 | Section.starts_with(".init_array") || |
1994 | 0 | Section.starts_with(".fini_array")) { |
1995 | 0 | return false; |
1996 | 0 | } |
1997 | | |
1998 | | // Do not instrument user-defined sections (with names resembling |
1999 | | // valid C identifiers) |
2000 | 0 | if (TargetTriple.isOSBinFormatELF()) { |
2001 | 0 | if (llvm::all_of(Section, |
2002 | 0 | [](char c) { return llvm::isAlnum(c) || c == '_'; })) |
2003 | 0 | return false; |
2004 | 0 | } |
2005 | | |
2006 | | // On COFF, if the section name contains '$', it is highly likely that the |
2007 | | // user is using section sorting to create an array of globals similar to |
2008 | | // the way initialization callbacks are registered in .init_array and |
2009 | | // .CRT$XCU. The ATL also registers things in .ATL$__[azm]. Adding redzones |
2010 | | // to such globals is counterproductive, because the intent is that they |
2011 | | // will form an array, and out-of-bounds accesses are expected. |
2012 | | // See https://github.com/google/sanitizers/issues/305 |
2013 | | // and http://msdn.microsoft.com/en-US/en-en/library/bb918180(v=vs.120).aspx |
2014 | 0 | if (TargetTriple.isOSBinFormatCOFF() && Section.contains('$')) { |
2015 | 0 | LLVM_DEBUG(dbgs() << "Ignoring global in sorted section (contains '$'): " |
2016 | 0 | << *G << "\n"); |
2017 | 0 | return false; |
2018 | 0 | } |
2019 | | |
2020 | 0 | if (TargetTriple.isOSBinFormatMachO()) { |
2021 | 0 | StringRef ParsedSegment, ParsedSection; |
2022 | 0 | unsigned TAA = 0, StubSize = 0; |
2023 | 0 | bool TAAParsed; |
2024 | 0 | cantFail(MCSectionMachO::ParseSectionSpecifier( |
2025 | 0 | Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize)); |
2026 | | |
2027 | | // Ignore the globals from the __OBJC section. The ObjC runtime assumes |
2028 | | // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to |
2029 | | // them. |
2030 | 0 | if (ParsedSegment == "__OBJC" || |
2031 | 0 | (ParsedSegment == "__DATA" && ParsedSection.starts_with("__objc_"))) { |
2032 | 0 | LLVM_DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G << "\n"); |
2033 | 0 | return false; |
2034 | 0 | } |
2035 | | // See https://github.com/google/sanitizers/issues/32 |
2036 | | // Constant CFString instances are compiled in the following way: |
2037 | | // -- the string buffer is emitted into |
2038 | | // __TEXT,__cstring,cstring_literals |
2039 | | // -- the constant NSConstantString structure referencing that buffer |
2040 | | // is placed into __DATA,__cfstring |
2041 | | // Therefore there's no point in placing redzones into __DATA,__cfstring. |
2042 | | // Moreover, it causes the linker to crash on OS X 10.7 |
2043 | 0 | if (ParsedSegment == "__DATA" && ParsedSection == "__cfstring") { |
2044 | 0 | LLVM_DEBUG(dbgs() << "Ignoring CFString: " << *G << "\n"); |
2045 | 0 | return false; |
2046 | 0 | } |
2047 | | // The linker merges the contents of cstring_literals and removes the |
2048 | | // trailing zeroes. |
2049 | 0 | if (ParsedSegment == "__TEXT" && (TAA & MachO::S_CSTRING_LITERALS)) { |
2050 | 0 | LLVM_DEBUG(dbgs() << "Ignoring a cstring literal: " << *G << "\n"); |
2051 | 0 | return false; |
2052 | 0 | } |
2053 | 0 | } |
2054 | 0 | } |
2055 | | |
2056 | 0 | if (CompileKernel) { |
2057 | | // Globals that prefixed by "__" are special and cannot be padded with a |
2058 | | // redzone. |
2059 | 0 | if (G->getName().starts_with("__")) |
2060 | 0 | return false; |
2061 | 0 | } |
2062 | | |
2063 | 0 | return true; |
2064 | 0 | } |
2065 | | |
2066 | | // On Mach-O platforms, we emit global metadata in a separate section of the |
2067 | | // binary in order to allow the linker to properly dead strip. This is only |
2068 | | // supported on recent versions of ld64. |
2069 | 0 | bool ModuleAddressSanitizer::ShouldUseMachOGlobalsSection() const { |
2070 | 0 | if (!TargetTriple.isOSBinFormatMachO()) |
2071 | 0 | return false; |
2072 | | |
2073 | 0 | if (TargetTriple.isMacOSX() && !TargetTriple.isMacOSXVersionLT(10, 11)) |
2074 | 0 | return true; |
2075 | 0 | if (TargetTriple.isiOS() /* or tvOS */ && !TargetTriple.isOSVersionLT(9)) |
2076 | 0 | return true; |
2077 | 0 | if (TargetTriple.isWatchOS() && !TargetTriple.isOSVersionLT(2)) |
2078 | 0 | return true; |
2079 | 0 | if (TargetTriple.isDriverKit()) |
2080 | 0 | return true; |
2081 | | |
2082 | 0 | return false; |
2083 | 0 | } |
2084 | | |
2085 | 0 | StringRef ModuleAddressSanitizer::getGlobalMetadataSection() const { |
2086 | 0 | switch (TargetTriple.getObjectFormat()) { |
2087 | 0 | case Triple::COFF: return ".ASAN$GL"; |
2088 | 0 | case Triple::ELF: return "asan_globals"; |
2089 | 0 | case Triple::MachO: return "__DATA,__asan_globals,regular"; |
2090 | 0 | case Triple::Wasm: |
2091 | 0 | case Triple::GOFF: |
2092 | 0 | case Triple::SPIRV: |
2093 | 0 | case Triple::XCOFF: |
2094 | 0 | case Triple::DXContainer: |
2095 | 0 | report_fatal_error( |
2096 | 0 | "ModuleAddressSanitizer not implemented for object file format"); |
2097 | 0 | case Triple::UnknownObjectFormat: |
2098 | 0 | break; |
2099 | 0 | } |
2100 | 0 | llvm_unreachable("unsupported object format"); |
2101 | 0 | } |
2102 | | |
2103 | 0 | void ModuleAddressSanitizer::initializeCallbacks(Module &M) { |
2104 | 0 | IRBuilder<> IRB(*C); |
2105 | | |
2106 | | // Declare our poisoning and unpoisoning functions. |
2107 | 0 | AsanPoisonGlobals = |
2108 | 0 | M.getOrInsertFunction(kAsanPoisonGlobalsName, IRB.getVoidTy(), IntptrTy); |
2109 | 0 | AsanUnpoisonGlobals = |
2110 | 0 | M.getOrInsertFunction(kAsanUnpoisonGlobalsName, IRB.getVoidTy()); |
2111 | | |
2112 | | // Declare functions that register/unregister globals. |
2113 | 0 | AsanRegisterGlobals = M.getOrInsertFunction( |
2114 | 0 | kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy); |
2115 | 0 | AsanUnregisterGlobals = M.getOrInsertFunction( |
2116 | 0 | kAsanUnregisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy); |
2117 | | |
2118 | | // Declare the functions that find globals in a shared object and then invoke |
2119 | | // the (un)register function on them. |
2120 | 0 | AsanRegisterImageGlobals = M.getOrInsertFunction( |
2121 | 0 | kAsanRegisterImageGlobalsName, IRB.getVoidTy(), IntptrTy); |
2122 | 0 | AsanUnregisterImageGlobals = M.getOrInsertFunction( |
2123 | 0 | kAsanUnregisterImageGlobalsName, IRB.getVoidTy(), IntptrTy); |
2124 | |
|
2125 | 0 | AsanRegisterElfGlobals = |
2126 | 0 | M.getOrInsertFunction(kAsanRegisterElfGlobalsName, IRB.getVoidTy(), |
2127 | 0 | IntptrTy, IntptrTy, IntptrTy); |
2128 | 0 | AsanUnregisterElfGlobals = |
2129 | 0 | M.getOrInsertFunction(kAsanUnregisterElfGlobalsName, IRB.getVoidTy(), |
2130 | 0 | IntptrTy, IntptrTy, IntptrTy); |
2131 | 0 | } |
2132 | | |
2133 | | // Put the metadata and the instrumented global in the same group. This ensures |
2134 | | // that the metadata is discarded if the instrumented global is discarded. |
2135 | | void ModuleAddressSanitizer::SetComdatForGlobalMetadata( |
2136 | 0 | GlobalVariable *G, GlobalVariable *Metadata, StringRef InternalSuffix) { |
2137 | 0 | Module &M = *G->getParent(); |
2138 | 0 | Comdat *C = G->getComdat(); |
2139 | 0 | if (!C) { |
2140 | 0 | if (!G->hasName()) { |
2141 | | // If G is unnamed, it must be internal. Give it an artificial name |
2142 | | // so we can put it in a comdat. |
2143 | 0 | assert(G->hasLocalLinkage()); |
2144 | 0 | G->setName(Twine(kAsanGenPrefix) + "_anon_global"); |
2145 | 0 | } |
2146 | | |
2147 | 0 | if (!InternalSuffix.empty() && G->hasLocalLinkage()) { |
2148 | 0 | std::string Name = std::string(G->getName()); |
2149 | 0 | Name += InternalSuffix; |
2150 | 0 | C = M.getOrInsertComdat(Name); |
2151 | 0 | } else { |
2152 | 0 | C = M.getOrInsertComdat(G->getName()); |
2153 | 0 | } |
2154 | | |
2155 | | // Make this IMAGE_COMDAT_SELECT_NODUPLICATES on COFF. Also upgrade private |
2156 | | // linkage to internal linkage so that a symbol table entry is emitted. This |
2157 | | // is necessary in order to create the comdat group. |
2158 | 0 | if (TargetTriple.isOSBinFormatCOFF()) { |
2159 | 0 | C->setSelectionKind(Comdat::NoDeduplicate); |
2160 | 0 | if (G->hasPrivateLinkage()) |
2161 | 0 | G->setLinkage(GlobalValue::InternalLinkage); |
2162 | 0 | } |
2163 | 0 | G->setComdat(C); |
2164 | 0 | } |
2165 | | |
2166 | 0 | assert(G->hasComdat()); |
2167 | 0 | Metadata->setComdat(G->getComdat()); |
2168 | 0 | } |
2169 | | |
2170 | | // Create a separate metadata global and put it in the appropriate ASan |
2171 | | // global registration section. |
2172 | | GlobalVariable * |
2173 | | ModuleAddressSanitizer::CreateMetadataGlobal(Module &M, Constant *Initializer, |
2174 | 0 | StringRef OriginalName) { |
2175 | 0 | auto Linkage = TargetTriple.isOSBinFormatMachO() |
2176 | 0 | ? GlobalVariable::InternalLinkage |
2177 | 0 | : GlobalVariable::PrivateLinkage; |
2178 | 0 | GlobalVariable *Metadata = new GlobalVariable( |
2179 | 0 | M, Initializer->getType(), false, Linkage, Initializer, |
2180 | 0 | Twine("__asan_global_") + GlobalValue::dropLLVMManglingEscape(OriginalName)); |
2181 | 0 | Metadata->setSection(getGlobalMetadataSection()); |
2182 | | // Place metadata in a large section for x86-64 ELF binaries to mitigate |
2183 | | // relocation pressure. |
2184 | 0 | setGlobalVariableLargeSection(TargetTriple, *Metadata); |
2185 | 0 | return Metadata; |
2186 | 0 | } |
2187 | | |
2188 | 0 | Instruction *ModuleAddressSanitizer::CreateAsanModuleDtor(Module &M) { |
2189 | 0 | AsanDtorFunction = Function::createWithDefaultAttr( |
2190 | 0 | FunctionType::get(Type::getVoidTy(*C), false), |
2191 | 0 | GlobalValue::InternalLinkage, 0, kAsanModuleDtorName, &M); |
2192 | 0 | AsanDtorFunction->addFnAttr(Attribute::NoUnwind); |
2193 | | // Ensure Dtor cannot be discarded, even if in a comdat. |
2194 | 0 | appendToUsed(M, {AsanDtorFunction}); |
2195 | 0 | BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); |
2196 | |
|
2197 | 0 | return ReturnInst::Create(*C, AsanDtorBB); |
2198 | 0 | } |
2199 | | |
2200 | | void ModuleAddressSanitizer::InstrumentGlobalsCOFF( |
2201 | | IRBuilder<> &IRB, Module &M, ArrayRef<GlobalVariable *> ExtendedGlobals, |
2202 | 0 | ArrayRef<Constant *> MetadataInitializers) { |
2203 | 0 | assert(ExtendedGlobals.size() == MetadataInitializers.size()); |
2204 | 0 | auto &DL = M.getDataLayout(); |
2205 | |
|
2206 | 0 | SmallVector<GlobalValue *, 16> MetadataGlobals(ExtendedGlobals.size()); |
2207 | 0 | for (size_t i = 0; i < ExtendedGlobals.size(); i++) { |
2208 | 0 | Constant *Initializer = MetadataInitializers[i]; |
2209 | 0 | GlobalVariable *G = ExtendedGlobals[i]; |
2210 | 0 | GlobalVariable *Metadata = |
2211 | 0 | CreateMetadataGlobal(M, Initializer, G->getName()); |
2212 | 0 | MDNode *MD = MDNode::get(M.getContext(), ValueAsMetadata::get(G)); |
2213 | 0 | Metadata->setMetadata(LLVMContext::MD_associated, MD); |
2214 | 0 | MetadataGlobals[i] = Metadata; |
2215 | | |
2216 | | // The MSVC linker always inserts padding when linking incrementally. We |
2217 | | // cope with that by aligning each struct to its size, which must be a power |
2218 | | // of two. |
2219 | 0 | unsigned SizeOfGlobalStruct = DL.getTypeAllocSize(Initializer->getType()); |
2220 | 0 | assert(isPowerOf2_32(SizeOfGlobalStruct) && |
2221 | 0 | "global metadata will not be padded appropriately"); |
2222 | 0 | Metadata->setAlignment(assumeAligned(SizeOfGlobalStruct)); |
2223 | |
|
2224 | 0 | SetComdatForGlobalMetadata(G, Metadata, ""); |
2225 | 0 | } |
2226 | | |
2227 | | // Update llvm.compiler.used, adding the new metadata globals. This is |
2228 | | // needed so that during LTO these variables stay alive. |
2229 | 0 | if (!MetadataGlobals.empty()) |
2230 | 0 | appendToCompilerUsed(M, MetadataGlobals); |
2231 | 0 | } |
2232 | | |
2233 | | void ModuleAddressSanitizer::instrumentGlobalsELF( |
2234 | | IRBuilder<> &IRB, Module &M, ArrayRef<GlobalVariable *> ExtendedGlobals, |
2235 | | ArrayRef<Constant *> MetadataInitializers, |
2236 | 0 | const std::string &UniqueModuleId) { |
2237 | 0 | assert(ExtendedGlobals.size() == MetadataInitializers.size()); |
2238 | | |
2239 | | // Putting globals in a comdat changes the semantic and potentially cause |
2240 | | // false negative odr violations at link time. If odr indicators are used, we |
2241 | | // keep the comdat sections, as link time odr violations will be dectected on |
2242 | | // the odr indicator symbols. |
2243 | 0 | bool UseComdatForGlobalsGC = UseOdrIndicator && !UniqueModuleId.empty(); |
2244 | |
|
2245 | 0 | SmallVector<GlobalValue *, 16> MetadataGlobals(ExtendedGlobals.size()); |
2246 | 0 | for (size_t i = 0; i < ExtendedGlobals.size(); i++) { |
2247 | 0 | GlobalVariable *G = ExtendedGlobals[i]; |
2248 | 0 | GlobalVariable *Metadata = |
2249 | 0 | CreateMetadataGlobal(M, MetadataInitializers[i], G->getName()); |
2250 | 0 | MDNode *MD = MDNode::get(M.getContext(), ValueAsMetadata::get(G)); |
2251 | 0 | Metadata->setMetadata(LLVMContext::MD_associated, MD); |
2252 | 0 | MetadataGlobals[i] = Metadata; |
2253 | |
|
2254 | 0 | if (UseComdatForGlobalsGC) |
2255 | 0 | SetComdatForGlobalMetadata(G, Metadata, UniqueModuleId); |
2256 | 0 | } |
2257 | | |
2258 | | // Update llvm.compiler.used, adding the new metadata globals. This is |
2259 | | // needed so that during LTO these variables stay alive. |
2260 | 0 | if (!MetadataGlobals.empty()) |
2261 | 0 | appendToCompilerUsed(M, MetadataGlobals); |
2262 | | |
2263 | | // RegisteredFlag serves two purposes. First, we can pass it to dladdr() |
2264 | | // to look up the loaded image that contains it. Second, we can store in it |
2265 | | // whether registration has already occurred, to prevent duplicate |
2266 | | // registration. |
2267 | | // |
2268 | | // Common linkage ensures that there is only one global per shared library. |
2269 | 0 | GlobalVariable *RegisteredFlag = new GlobalVariable( |
2270 | 0 | M, IntptrTy, false, GlobalVariable::CommonLinkage, |
2271 | 0 | ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName); |
2272 | 0 | RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility); |
2273 | | |
2274 | | // Create start and stop symbols. |
2275 | 0 | GlobalVariable *StartELFMetadata = new GlobalVariable( |
2276 | 0 | M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr, |
2277 | 0 | "__start_" + getGlobalMetadataSection()); |
2278 | 0 | StartELFMetadata->setVisibility(GlobalVariable::HiddenVisibility); |
2279 | 0 | GlobalVariable *StopELFMetadata = new GlobalVariable( |
2280 | 0 | M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr, |
2281 | 0 | "__stop_" + getGlobalMetadataSection()); |
2282 | 0 | StopELFMetadata->setVisibility(GlobalVariable::HiddenVisibility); |
2283 | | |
2284 | | // Create a call to register the globals with the runtime. |
2285 | 0 | if (ConstructorKind == AsanCtorKind::Global) |
2286 | 0 | IRB.CreateCall(AsanRegisterElfGlobals, |
2287 | 0 | {IRB.CreatePointerCast(RegisteredFlag, IntptrTy), |
2288 | 0 | IRB.CreatePointerCast(StartELFMetadata, IntptrTy), |
2289 | 0 | IRB.CreatePointerCast(StopELFMetadata, IntptrTy)}); |
2290 | | |
2291 | | // We also need to unregister globals at the end, e.g., when a shared library |
2292 | | // gets closed. |
2293 | 0 | if (DestructorKind != AsanDtorKind::None && !MetadataGlobals.empty()) { |
2294 | 0 | IRBuilder<> IrbDtor(CreateAsanModuleDtor(M)); |
2295 | 0 | IrbDtor.CreateCall(AsanUnregisterElfGlobals, |
2296 | 0 | {IRB.CreatePointerCast(RegisteredFlag, IntptrTy), |
2297 | 0 | IRB.CreatePointerCast(StartELFMetadata, IntptrTy), |
2298 | 0 | IRB.CreatePointerCast(StopELFMetadata, IntptrTy)}); |
2299 | 0 | } |
2300 | 0 | } |
2301 | | |
2302 | | void ModuleAddressSanitizer::InstrumentGlobalsMachO( |
2303 | | IRBuilder<> &IRB, Module &M, ArrayRef<GlobalVariable *> ExtendedGlobals, |
2304 | 0 | ArrayRef<Constant *> MetadataInitializers) { |
2305 | 0 | assert(ExtendedGlobals.size() == MetadataInitializers.size()); |
2306 | | |
2307 | | // On recent Mach-O platforms, use a structure which binds the liveness of |
2308 | | // the global variable to the metadata struct. Keep the list of "Liveness" GV |
2309 | | // created to be added to llvm.compiler.used |
2310 | 0 | StructType *LivenessTy = StructType::get(IntptrTy, IntptrTy); |
2311 | 0 | SmallVector<GlobalValue *, 16> LivenessGlobals(ExtendedGlobals.size()); |
2312 | |
|
2313 | 0 | for (size_t i = 0; i < ExtendedGlobals.size(); i++) { |
2314 | 0 | Constant *Initializer = MetadataInitializers[i]; |
2315 | 0 | GlobalVariable *G = ExtendedGlobals[i]; |
2316 | 0 | GlobalVariable *Metadata = |
2317 | 0 | CreateMetadataGlobal(M, Initializer, G->getName()); |
2318 | | |
2319 | | // On recent Mach-O platforms, we emit the global metadata in a way that |
2320 | | // allows the linker to properly strip dead globals. |
2321 | 0 | auto LivenessBinder = |
2322 | 0 | ConstantStruct::get(LivenessTy, Initializer->getAggregateElement(0u), |
2323 | 0 | ConstantExpr::getPointerCast(Metadata, IntptrTy)); |
2324 | 0 | GlobalVariable *Liveness = new GlobalVariable( |
2325 | 0 | M, LivenessTy, false, GlobalVariable::InternalLinkage, LivenessBinder, |
2326 | 0 | Twine("__asan_binder_") + G->getName()); |
2327 | 0 | Liveness->setSection("__DATA,__asan_liveness,regular,live_support"); |
2328 | 0 | LivenessGlobals[i] = Liveness; |
2329 | 0 | } |
2330 | | |
2331 | | // Update llvm.compiler.used, adding the new liveness globals. This is |
2332 | | // needed so that during LTO these variables stay alive. The alternative |
2333 | | // would be to have the linker handling the LTO symbols, but libLTO |
2334 | | // current API does not expose access to the section for each symbol. |
2335 | 0 | if (!LivenessGlobals.empty()) |
2336 | 0 | appendToCompilerUsed(M, LivenessGlobals); |
2337 | | |
2338 | | // RegisteredFlag serves two purposes. First, we can pass it to dladdr() |
2339 | | // to look up the loaded image that contains it. Second, we can store in it |
2340 | | // whether registration has already occurred, to prevent duplicate |
2341 | | // registration. |
2342 | | // |
2343 | | // common linkage ensures that there is only one global per shared library. |
2344 | 0 | GlobalVariable *RegisteredFlag = new GlobalVariable( |
2345 | 0 | M, IntptrTy, false, GlobalVariable::CommonLinkage, |
2346 | 0 | ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName); |
2347 | 0 | RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility); |
2348 | |
|
2349 | 0 | if (ConstructorKind == AsanCtorKind::Global) |
2350 | 0 | IRB.CreateCall(AsanRegisterImageGlobals, |
2351 | 0 | {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); |
2352 | | |
2353 | | // We also need to unregister globals at the end, e.g., when a shared library |
2354 | | // gets closed. |
2355 | 0 | if (DestructorKind != AsanDtorKind::None) { |
2356 | 0 | IRBuilder<> IrbDtor(CreateAsanModuleDtor(M)); |
2357 | 0 | IrbDtor.CreateCall(AsanUnregisterImageGlobals, |
2358 | 0 | {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); |
2359 | 0 | } |
2360 | 0 | } |
2361 | | |
2362 | | void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray( |
2363 | | IRBuilder<> &IRB, Module &M, ArrayRef<GlobalVariable *> ExtendedGlobals, |
2364 | 0 | ArrayRef<Constant *> MetadataInitializers) { |
2365 | 0 | assert(ExtendedGlobals.size() == MetadataInitializers.size()); |
2366 | 0 | unsigned N = ExtendedGlobals.size(); |
2367 | 0 | assert(N > 0); |
2368 | | |
2369 | | // On platforms that don't have a custom metadata section, we emit an array |
2370 | | // of global metadata structures. |
2371 | 0 | ArrayType *ArrayOfGlobalStructTy = |
2372 | 0 | ArrayType::get(MetadataInitializers[0]->getType(), N); |
2373 | 0 | auto AllGlobals = new GlobalVariable( |
2374 | 0 | M, ArrayOfGlobalStructTy, false, GlobalVariable::InternalLinkage, |
2375 | 0 | ConstantArray::get(ArrayOfGlobalStructTy, MetadataInitializers), ""); |
2376 | 0 | if (Mapping.Scale > 3) |
2377 | 0 | AllGlobals->setAlignment(Align(1ULL << Mapping.Scale)); |
2378 | |
|
2379 | 0 | if (ConstructorKind == AsanCtorKind::Global) |
2380 | 0 | IRB.CreateCall(AsanRegisterGlobals, |
2381 | 0 | {IRB.CreatePointerCast(AllGlobals, IntptrTy), |
2382 | 0 | ConstantInt::get(IntptrTy, N)}); |
2383 | | |
2384 | | // We also need to unregister globals at the end, e.g., when a shared library |
2385 | | // gets closed. |
2386 | 0 | if (DestructorKind != AsanDtorKind::None) { |
2387 | 0 | IRBuilder<> IrbDtor(CreateAsanModuleDtor(M)); |
2388 | 0 | IrbDtor.CreateCall(AsanUnregisterGlobals, |
2389 | 0 | {IRB.CreatePointerCast(AllGlobals, IntptrTy), |
2390 | 0 | ConstantInt::get(IntptrTy, N)}); |
2391 | 0 | } |
2392 | 0 | } |
2393 | | |
2394 | | // This function replaces all global variables with new variables that have |
2395 | | // trailing redzones. It also creates a function that poisons |
2396 | | // redzones and inserts this function into llvm.global_ctors. |
2397 | | // Sets *CtorComdat to true if the global registration code emitted into the |
2398 | | // asan constructor is comdat-compatible. |
2399 | | void ModuleAddressSanitizer::instrumentGlobals(IRBuilder<> &IRB, Module &M, |
2400 | 0 | bool *CtorComdat) { |
2401 | | // Build set of globals that are aliased by some GA, where |
2402 | | // getExcludedAliasedGlobal(GA) returns the relevant GlobalVariable. |
2403 | 0 | SmallPtrSet<const GlobalVariable *, 16> AliasedGlobalExclusions; |
2404 | 0 | if (CompileKernel) { |
2405 | 0 | for (auto &GA : M.aliases()) { |
2406 | 0 | if (const GlobalVariable *GV = getExcludedAliasedGlobal(GA)) |
2407 | 0 | AliasedGlobalExclusions.insert(GV); |
2408 | 0 | } |
2409 | 0 | } |
2410 | |
|
2411 | 0 | SmallVector<GlobalVariable *, 16> GlobalsToChange; |
2412 | 0 | for (auto &G : M.globals()) { |
2413 | 0 | if (!AliasedGlobalExclusions.count(&G) && shouldInstrumentGlobal(&G)) |
2414 | 0 | GlobalsToChange.push_back(&G); |
2415 | 0 | } |
2416 | |
|
2417 | 0 | size_t n = GlobalsToChange.size(); |
2418 | 0 | auto &DL = M.getDataLayout(); |
2419 | | |
2420 | | // A global is described by a structure |
2421 | | // size_t beg; |
2422 | | // size_t size; |
2423 | | // size_t size_with_redzone; |
2424 | | // const char *name; |
2425 | | // const char *module_name; |
2426 | | // size_t has_dynamic_init; |
2427 | | // size_t padding_for_windows_msvc_incremental_link; |
2428 | | // size_t odr_indicator; |
2429 | | // We initialize an array of such structures and pass it to a run-time call. |
2430 | 0 | StructType *GlobalStructTy = |
2431 | 0 | StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, |
2432 | 0 | IntptrTy, IntptrTy, IntptrTy); |
2433 | 0 | SmallVector<GlobalVariable *, 16> NewGlobals(n); |
2434 | 0 | SmallVector<Constant *, 16> Initializers(n); |
2435 | |
|
2436 | 0 | bool HasDynamicallyInitializedGlobals = false; |
2437 | | |
2438 | | // We shouldn't merge same module names, as this string serves as unique |
2439 | | // module ID in runtime. |
2440 | 0 | GlobalVariable *ModuleName = |
2441 | 0 | n != 0 |
2442 | 0 | ? createPrivateGlobalForString(M, M.getModuleIdentifier(), |
2443 | 0 | /*AllowMerging*/ false, kAsanGenPrefix) |
2444 | 0 | : nullptr; |
2445 | |
|
2446 | 0 | for (size_t i = 0; i < n; i++) { |
2447 | 0 | GlobalVariable *G = GlobalsToChange[i]; |
2448 | |
|
2449 | 0 | GlobalValue::SanitizerMetadata MD; |
2450 | 0 | if (G->hasSanitizerMetadata()) |
2451 | 0 | MD = G->getSanitizerMetadata(); |
2452 | | |
2453 | | // The runtime library tries demangling symbol names in the descriptor but |
2454 | | // functionality like __cxa_demangle may be unavailable (e.g. |
2455 | | // -static-libstdc++). So we demangle the symbol names here. |
2456 | 0 | std::string NameForGlobal = G->getName().str(); |
2457 | 0 | GlobalVariable *Name = |
2458 | 0 | createPrivateGlobalForString(M, llvm::demangle(NameForGlobal), |
2459 | 0 | /*AllowMerging*/ true, kAsanGenPrefix); |
2460 | |
|
2461 | 0 | Type *Ty = G->getValueType(); |
2462 | 0 | const uint64_t SizeInBytes = DL.getTypeAllocSize(Ty); |
2463 | 0 | const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal(SizeInBytes); |
2464 | 0 | Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); |
2465 | |
|
2466 | 0 | StructType *NewTy = StructType::get(Ty, RightRedZoneTy); |
2467 | 0 | Constant *NewInitializer = ConstantStruct::get( |
2468 | 0 | NewTy, G->getInitializer(), Constant::getNullValue(RightRedZoneTy)); |
2469 | | |
2470 | | // Create a new global variable with enough space for a redzone. |
2471 | 0 | GlobalValue::LinkageTypes Linkage = G->getLinkage(); |
2472 | 0 | if (G->isConstant() && Linkage == GlobalValue::PrivateLinkage) |
2473 | 0 | Linkage = GlobalValue::InternalLinkage; |
2474 | 0 | GlobalVariable *NewGlobal = new GlobalVariable( |
2475 | 0 | M, NewTy, G->isConstant(), Linkage, NewInitializer, "", G, |
2476 | 0 | G->getThreadLocalMode(), G->getAddressSpace()); |
2477 | 0 | NewGlobal->copyAttributesFrom(G); |
2478 | 0 | NewGlobal->setComdat(G->getComdat()); |
2479 | 0 | NewGlobal->setAlignment(Align(getMinRedzoneSizeForGlobal())); |
2480 | | // Don't fold globals with redzones. ODR violation detector and redzone |
2481 | | // poisoning implicitly creates a dependence on the global's address, so it |
2482 | | // is no longer valid for it to be marked unnamed_addr. |
2483 | 0 | NewGlobal->setUnnamedAddr(GlobalValue::UnnamedAddr::None); |
2484 | | |
2485 | | // Move null-terminated C strings to "__asan_cstring" section on Darwin. |
2486 | 0 | if (TargetTriple.isOSBinFormatMachO() && !G->hasSection() && |
2487 | 0 | G->isConstant()) { |
2488 | 0 | auto Seq = dyn_cast<ConstantDataSequential>(G->getInitializer()); |
2489 | 0 | if (Seq && Seq->isCString()) |
2490 | 0 | NewGlobal->setSection("__TEXT,__asan_cstring,regular"); |
2491 | 0 | } |
2492 | | |
2493 | | // Transfer the debug info and type metadata. The payload starts at offset |
2494 | | // zero so we can copy the metadata over as is. |
2495 | 0 | NewGlobal->copyMetadata(G, 0); |
2496 | |
|
2497 | 0 | Value *Indices2[2]; |
2498 | 0 | Indices2[0] = IRB.getInt32(0); |
2499 | 0 | Indices2[1] = IRB.getInt32(0); |
2500 | |
|
2501 | 0 | G->replaceAllUsesWith( |
2502 | 0 | ConstantExpr::getGetElementPtr(NewTy, NewGlobal, Indices2, true)); |
2503 | 0 | NewGlobal->takeName(G); |
2504 | 0 | G->eraseFromParent(); |
2505 | 0 | NewGlobals[i] = NewGlobal; |
2506 | |
|
2507 | 0 | Constant *ODRIndicator = ConstantPointerNull::get(PtrTy); |
2508 | 0 | GlobalValue *InstrumentedGlobal = NewGlobal; |
2509 | |
|
2510 | 0 | bool CanUsePrivateAliases = |
2511 | 0 | TargetTriple.isOSBinFormatELF() || TargetTriple.isOSBinFormatMachO() || |
2512 | 0 | TargetTriple.isOSBinFormatWasm(); |
2513 | 0 | if (CanUsePrivateAliases && UsePrivateAlias) { |
2514 | | // Create local alias for NewGlobal to avoid crash on ODR between |
2515 | | // instrumented and non-instrumented libraries. |
2516 | 0 | InstrumentedGlobal = |
2517 | 0 | GlobalAlias::create(GlobalValue::PrivateLinkage, "", NewGlobal); |
2518 | 0 | } |
2519 | | |
2520 | | // ODR should not happen for local linkage. |
2521 | 0 | if (NewGlobal->hasLocalLinkage()) { |
2522 | 0 | ODRIndicator = |
2523 | 0 | ConstantExpr::getIntToPtr(ConstantInt::get(IntptrTy, -1), PtrTy); |
2524 | 0 | } else if (UseOdrIndicator) { |
2525 | | // With local aliases, we need to provide another externally visible |
2526 | | // symbol __odr_asan_XXX to detect ODR violation. |
2527 | 0 | auto *ODRIndicatorSym = |
2528 | 0 | new GlobalVariable(M, IRB.getInt8Ty(), false, Linkage, |
2529 | 0 | Constant::getNullValue(IRB.getInt8Ty()), |
2530 | 0 | kODRGenPrefix + NameForGlobal, nullptr, |
2531 | 0 | NewGlobal->getThreadLocalMode()); |
2532 | | |
2533 | | // Set meaningful attributes for indicator symbol. |
2534 | 0 | ODRIndicatorSym->setVisibility(NewGlobal->getVisibility()); |
2535 | 0 | ODRIndicatorSym->setDLLStorageClass(NewGlobal->getDLLStorageClass()); |
2536 | 0 | ODRIndicatorSym->setAlignment(Align(1)); |
2537 | 0 | ODRIndicator = ODRIndicatorSym; |
2538 | 0 | } |
2539 | |
|
2540 | 0 | Constant *Initializer = ConstantStruct::get( |
2541 | 0 | GlobalStructTy, |
2542 | 0 | ConstantExpr::getPointerCast(InstrumentedGlobal, IntptrTy), |
2543 | 0 | ConstantInt::get(IntptrTy, SizeInBytes), |
2544 | 0 | ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), |
2545 | 0 | ConstantExpr::getPointerCast(Name, IntptrTy), |
2546 | 0 | ConstantExpr::getPointerCast(ModuleName, IntptrTy), |
2547 | 0 | ConstantInt::get(IntptrTy, MD.IsDynInit), |
2548 | 0 | Constant::getNullValue(IntptrTy), |
2549 | 0 | ConstantExpr::getPointerCast(ODRIndicator, IntptrTy)); |
2550 | |
|
2551 | 0 | if (ClInitializers && MD.IsDynInit) |
2552 | 0 | HasDynamicallyInitializedGlobals = true; |
2553 | |
|
2554 | 0 | LLVM_DEBUG(dbgs() << "NEW GLOBAL: " << *NewGlobal << "\n"); |
2555 | |
|
2556 | 0 | Initializers[i] = Initializer; |
2557 | 0 | } |
2558 | | |
2559 | | // Add instrumented globals to llvm.compiler.used list to avoid LTO from |
2560 | | // ConstantMerge'ing them. |
2561 | 0 | SmallVector<GlobalValue *, 16> GlobalsToAddToUsedList; |
2562 | 0 | for (size_t i = 0; i < n; i++) { |
2563 | 0 | GlobalVariable *G = NewGlobals[i]; |
2564 | 0 | if (G->getName().empty()) continue; |
2565 | 0 | GlobalsToAddToUsedList.push_back(G); |
2566 | 0 | } |
2567 | 0 | appendToCompilerUsed(M, ArrayRef<GlobalValue *>(GlobalsToAddToUsedList)); |
2568 | |
|
2569 | 0 | if (UseGlobalsGC && TargetTriple.isOSBinFormatELF()) { |
2570 | | // Use COMDAT and register globals even if n == 0 to ensure that (a) the |
2571 | | // linkage unit will only have one module constructor, and (b) the register |
2572 | | // function will be called. The module destructor is not created when n == |
2573 | | // 0. |
2574 | 0 | *CtorComdat = true; |
2575 | 0 | instrumentGlobalsELF(IRB, M, NewGlobals, Initializers, |
2576 | 0 | getUniqueModuleId(&M)); |
2577 | 0 | } else if (n == 0) { |
2578 | | // When UseGlobalsGC is false, COMDAT can still be used if n == 0, because |
2579 | | // all compile units will have identical module constructor/destructor. |
2580 | 0 | *CtorComdat = TargetTriple.isOSBinFormatELF(); |
2581 | 0 | } else { |
2582 | 0 | *CtorComdat = false; |
2583 | 0 | if (UseGlobalsGC && TargetTriple.isOSBinFormatCOFF()) { |
2584 | 0 | InstrumentGlobalsCOFF(IRB, M, NewGlobals, Initializers); |
2585 | 0 | } else if (UseGlobalsGC && ShouldUseMachOGlobalsSection()) { |
2586 | 0 | InstrumentGlobalsMachO(IRB, M, NewGlobals, Initializers); |
2587 | 0 | } else { |
2588 | 0 | InstrumentGlobalsWithMetadataArray(IRB, M, NewGlobals, Initializers); |
2589 | 0 | } |
2590 | 0 | } |
2591 | | |
2592 | | // Create calls for poisoning before initializers run and unpoisoning after. |
2593 | 0 | if (HasDynamicallyInitializedGlobals) |
2594 | 0 | createInitializerPoisonCalls(M, ModuleName); |
2595 | |
|
2596 | 0 | LLVM_DEBUG(dbgs() << M); |
2597 | 0 | } |
2598 | | |
2599 | | uint64_t |
2600 | 0 | ModuleAddressSanitizer::getRedzoneSizeForGlobal(uint64_t SizeInBytes) const { |
2601 | 0 | constexpr uint64_t kMaxRZ = 1 << 18; |
2602 | 0 | const uint64_t MinRZ = getMinRedzoneSizeForGlobal(); |
2603 | |
|
2604 | 0 | uint64_t RZ = 0; |
2605 | 0 | if (SizeInBytes <= MinRZ / 2) { |
2606 | | // Reduce redzone size for small size objects, e.g. int, char[1]. MinRZ is |
2607 | | // at least 32 bytes, optimize when SizeInBytes is less than or equal to |
2608 | | // half of MinRZ. |
2609 | 0 | RZ = MinRZ - SizeInBytes; |
2610 | 0 | } else { |
2611 | | // Calculate RZ, where MinRZ <= RZ <= MaxRZ, and RZ ~ 1/4 * SizeInBytes. |
2612 | 0 | RZ = std::clamp((SizeInBytes / MinRZ / 4) * MinRZ, MinRZ, kMaxRZ); |
2613 | | |
2614 | | // Round up to multiple of MinRZ. |
2615 | 0 | if (SizeInBytes % MinRZ) |
2616 | 0 | RZ += MinRZ - (SizeInBytes % MinRZ); |
2617 | 0 | } |
2618 | |
|
2619 | 0 | assert((RZ + SizeInBytes) % MinRZ == 0); |
2620 | | |
2621 | 0 | return RZ; |
2622 | 0 | } |
2623 | | |
2624 | 0 | int ModuleAddressSanitizer::GetAsanVersion(const Module &M) const { |
2625 | 0 | int LongSize = M.getDataLayout().getPointerSizeInBits(); |
2626 | 0 | bool isAndroid = Triple(M.getTargetTriple()).isAndroid(); |
2627 | 0 | int Version = 8; |
2628 | | // 32-bit Android is one version ahead because of the switch to dynamic |
2629 | | // shadow. |
2630 | 0 | Version += (LongSize == 32 && isAndroid); |
2631 | 0 | return Version; |
2632 | 0 | } |
2633 | | |
2634 | 0 | bool ModuleAddressSanitizer::instrumentModule(Module &M) { |
2635 | 0 | initializeCallbacks(M); |
2636 | | |
2637 | | // Create a module constructor. A destructor is created lazily because not all |
2638 | | // platforms, and not all modules need it. |
2639 | 0 | if (ConstructorKind == AsanCtorKind::Global) { |
2640 | 0 | if (CompileKernel) { |
2641 | | // The kernel always builds with its own runtime, and therefore does not |
2642 | | // need the init and version check calls. |
2643 | 0 | AsanCtorFunction = createSanitizerCtor(M, kAsanModuleCtorName); |
2644 | 0 | } else { |
2645 | 0 | std::string AsanVersion = std::to_string(GetAsanVersion(M)); |
2646 | 0 | std::string VersionCheckName = |
2647 | 0 | InsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : ""; |
2648 | 0 | std::tie(AsanCtorFunction, std::ignore) = |
2649 | 0 | createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName, |
2650 | 0 | kAsanInitName, /*InitArgTypes=*/{}, |
2651 | 0 | /*InitArgs=*/{}, VersionCheckName); |
2652 | 0 | } |
2653 | 0 | } |
2654 | |
|
2655 | 0 | bool CtorComdat = true; |
2656 | 0 | if (ClGlobals) { |
2657 | 0 | assert(AsanCtorFunction || ConstructorKind == AsanCtorKind::None); |
2658 | 0 | if (AsanCtorFunction) { |
2659 | 0 | IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator()); |
2660 | 0 | instrumentGlobals(IRB, M, &CtorComdat); |
2661 | 0 | } else { |
2662 | 0 | IRBuilder<> IRB(*C); |
2663 | 0 | instrumentGlobals(IRB, M, &CtorComdat); |
2664 | 0 | } |
2665 | 0 | } |
2666 | | |
2667 | 0 | const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple); |
2668 | | |
2669 | | // Put the constructor and destructor in comdat if both |
2670 | | // (1) global instrumentation is not TU-specific |
2671 | | // (2) target is ELF. |
2672 | 0 | if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) { |
2673 | 0 | if (AsanCtorFunction) { |
2674 | 0 | AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName)); |
2675 | 0 | appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction); |
2676 | 0 | } |
2677 | 0 | if (AsanDtorFunction) { |
2678 | 0 | AsanDtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleDtorName)); |
2679 | 0 | appendToGlobalDtors(M, AsanDtorFunction, Priority, AsanDtorFunction); |
2680 | 0 | } |
2681 | 0 | } else { |
2682 | 0 | if (AsanCtorFunction) |
2683 | 0 | appendToGlobalCtors(M, AsanCtorFunction, Priority); |
2684 | 0 | if (AsanDtorFunction) |
2685 | 0 | appendToGlobalDtors(M, AsanDtorFunction, Priority); |
2686 | 0 | } |
2687 | |
|
2688 | 0 | return true; |
2689 | 0 | } |
2690 | | |
2691 | 0 | void AddressSanitizer::initializeCallbacks(Module &M, const TargetLibraryInfo *TLI) { |
2692 | 0 | IRBuilder<> IRB(*C); |
2693 | | // Create __asan_report* callbacks. |
2694 | | // IsWrite, TypeSize and Exp are encoded in the function name. |
2695 | 0 | for (int Exp = 0; Exp < 2; Exp++) { |
2696 | 0 | for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) { |
2697 | 0 | const std::string TypeStr = AccessIsWrite ? "store" : "load"; |
2698 | 0 | const std::string ExpStr = Exp ? "exp_" : ""; |
2699 | 0 | const std::string EndingStr = Recover ? "_noabort" : ""; |
2700 | |
|
2701 | 0 | SmallVector<Type *, 3> Args2 = {IntptrTy, IntptrTy}; |
2702 | 0 | SmallVector<Type *, 2> Args1{1, IntptrTy}; |
2703 | 0 | AttributeList AL2; |
2704 | 0 | AttributeList AL1; |
2705 | 0 | if (Exp) { |
2706 | 0 | Type *ExpType = Type::getInt32Ty(*C); |
2707 | 0 | Args2.push_back(ExpType); |
2708 | 0 | Args1.push_back(ExpType); |
2709 | 0 | if (auto AK = TLI->getExtAttrForI32Param(false)) { |
2710 | 0 | AL2 = AL2.addParamAttribute(*C, 2, AK); |
2711 | 0 | AL1 = AL1.addParamAttribute(*C, 1, AK); |
2712 | 0 | } |
2713 | 0 | } |
2714 | 0 | AsanErrorCallbackSized[AccessIsWrite][Exp] = M.getOrInsertFunction( |
2715 | 0 | kAsanReportErrorTemplate + ExpStr + TypeStr + "_n" + EndingStr, |
2716 | 0 | FunctionType::get(IRB.getVoidTy(), Args2, false), AL2); |
2717 | |
|
2718 | 0 | AsanMemoryAccessCallbackSized[AccessIsWrite][Exp] = M.getOrInsertFunction( |
2719 | 0 | ClMemoryAccessCallbackPrefix + ExpStr + TypeStr + "N" + EndingStr, |
2720 | 0 | FunctionType::get(IRB.getVoidTy(), Args2, false), AL2); |
2721 | |
|
2722 | 0 | for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; |
2723 | 0 | AccessSizeIndex++) { |
2724 | 0 | const std::string Suffix = TypeStr + itostr(1ULL << AccessSizeIndex); |
2725 | 0 | AsanErrorCallback[AccessIsWrite][Exp][AccessSizeIndex] = |
2726 | 0 | M.getOrInsertFunction( |
2727 | 0 | kAsanReportErrorTemplate + ExpStr + Suffix + EndingStr, |
2728 | 0 | FunctionType::get(IRB.getVoidTy(), Args1, false), AL1); |
2729 | |
|
2730 | 0 | AsanMemoryAccessCallback[AccessIsWrite][Exp][AccessSizeIndex] = |
2731 | 0 | M.getOrInsertFunction( |
2732 | 0 | ClMemoryAccessCallbackPrefix + ExpStr + Suffix + EndingStr, |
2733 | 0 | FunctionType::get(IRB.getVoidTy(), Args1, false), AL1); |
2734 | 0 | } |
2735 | 0 | } |
2736 | 0 | } |
2737 | |
|
2738 | 0 | const std::string MemIntrinCallbackPrefix = |
2739 | 0 | (CompileKernel && !ClKasanMemIntrinCallbackPrefix) |
2740 | 0 | ? std::string("") |
2741 | 0 | : ClMemoryAccessCallbackPrefix; |
2742 | 0 | AsanMemmove = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memmove", |
2743 | 0 | PtrTy, PtrTy, PtrTy, IntptrTy); |
2744 | 0 | AsanMemcpy = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memcpy", PtrTy, |
2745 | 0 | PtrTy, PtrTy, IntptrTy); |
2746 | 0 | AsanMemset = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memset", |
2747 | 0 | TLI->getAttrList(C, {1}, /*Signed=*/false), |
2748 | 0 | PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy); |
2749 | |
|
2750 | 0 | AsanHandleNoReturnFunc = |
2751 | 0 | M.getOrInsertFunction(kAsanHandleNoReturnName, IRB.getVoidTy()); |
2752 | |
|
2753 | 0 | AsanPtrCmpFunction = |
2754 | 0 | M.getOrInsertFunction(kAsanPtrCmp, IRB.getVoidTy(), IntptrTy, IntptrTy); |
2755 | 0 | AsanPtrSubFunction = |
2756 | 0 | M.getOrInsertFunction(kAsanPtrSub, IRB.getVoidTy(), IntptrTy, IntptrTy); |
2757 | 0 | if (Mapping.InGlobal) |
2758 | 0 | AsanShadowGlobal = M.getOrInsertGlobal("__asan_shadow", |
2759 | 0 | ArrayType::get(IRB.getInt8Ty(), 0)); |
2760 | |
|
2761 | 0 | AMDGPUAddressShared = |
2762 | 0 | M.getOrInsertFunction(kAMDGPUAddressSharedName, IRB.getInt1Ty(), PtrTy); |
2763 | 0 | AMDGPUAddressPrivate = |
2764 | 0 | M.getOrInsertFunction(kAMDGPUAddressPrivateName, IRB.getInt1Ty(), PtrTy); |
2765 | 0 | } |
2766 | | |
2767 | 0 | bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) { |
2768 | | // For each NSObject descendant having a +load method, this method is invoked |
2769 | | // by the ObjC runtime before any of the static constructors is called. |
2770 | | // Therefore we need to instrument such methods with a call to __asan_init |
2771 | | // at the beginning in order to initialize our runtime before any access to |
2772 | | // the shadow memory. |
2773 | | // We cannot just ignore these methods, because they may call other |
2774 | | // instrumented functions. |
2775 | 0 | if (F.getName().contains(" load]")) { |
2776 | 0 | FunctionCallee AsanInitFunction = |
2777 | 0 | declareSanitizerInitFunction(*F.getParent(), kAsanInitName, {}); |
2778 | 0 | IRBuilder<> IRB(&F.front(), F.front().begin()); |
2779 | 0 | IRB.CreateCall(AsanInitFunction, {}); |
2780 | 0 | return true; |
2781 | 0 | } |
2782 | 0 | return false; |
2783 | 0 | } |
2784 | | |
2785 | 0 | bool AddressSanitizer::maybeInsertDynamicShadowAtFunctionEntry(Function &F) { |
2786 | | // Generate code only when dynamic addressing is needed. |
2787 | 0 | if (Mapping.Offset != kDynamicShadowSentinel) |
2788 | 0 | return false; |
2789 | | |
2790 | 0 | IRBuilder<> IRB(&F.front().front()); |
2791 | 0 | if (Mapping.InGlobal) { |
2792 | 0 | if (ClWithIfuncSuppressRemat) { |
2793 | | // An empty inline asm with input reg == output reg. |
2794 | | // An opaque pointer-to-int cast, basically. |
2795 | 0 | InlineAsm *Asm = InlineAsm::get( |
2796 | 0 | FunctionType::get(IntptrTy, {AsanShadowGlobal->getType()}, false), |
2797 | 0 | StringRef(""), StringRef("=r,0"), |
2798 | 0 | /*hasSideEffects=*/false); |
2799 | 0 | LocalDynamicShadow = |
2800 | 0 | IRB.CreateCall(Asm, {AsanShadowGlobal}, ".asan.shadow"); |
2801 | 0 | } else { |
2802 | 0 | LocalDynamicShadow = |
2803 | 0 | IRB.CreatePointerCast(AsanShadowGlobal, IntptrTy, ".asan.shadow"); |
2804 | 0 | } |
2805 | 0 | } else { |
2806 | 0 | Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal( |
2807 | 0 | kAsanShadowMemoryDynamicAddress, IntptrTy); |
2808 | 0 | LocalDynamicShadow = IRB.CreateLoad(IntptrTy, GlobalDynamicAddress); |
2809 | 0 | } |
2810 | 0 | return true; |
2811 | 0 | } |
2812 | | |
2813 | 0 | void AddressSanitizer::markEscapedLocalAllocas(Function &F) { |
2814 | | // Find the one possible call to llvm.localescape and pre-mark allocas passed |
2815 | | // to it as uninteresting. This assumes we haven't started processing allocas |
2816 | | // yet. This check is done up front because iterating the use list in |
2817 | | // isInterestingAlloca would be algorithmically slower. |
2818 | 0 | assert(ProcessedAllocas.empty() && "must process localescape before allocas"); |
2819 | | |
2820 | | // Try to get the declaration of llvm.localescape. If it's not in the module, |
2821 | | // we can exit early. |
2822 | 0 | if (!F.getParent()->getFunction("llvm.localescape")) return; |
2823 | | |
2824 | | // Look for a call to llvm.localescape call in the entry block. It can't be in |
2825 | | // any other block. |
2826 | 0 | for (Instruction &I : F.getEntryBlock()) { |
2827 | 0 | IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I); |
2828 | 0 | if (II && II->getIntrinsicID() == Intrinsic::localescape) { |
2829 | | // We found a call. Mark all the allocas passed in as uninteresting. |
2830 | 0 | for (Value *Arg : II->args()) { |
2831 | 0 | AllocaInst *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts()); |
2832 | 0 | assert(AI && AI->isStaticAlloca() && |
2833 | 0 | "non-static alloca arg to localescape"); |
2834 | 0 | ProcessedAllocas[AI] = false; |
2835 | 0 | } |
2836 | 0 | break; |
2837 | 0 | } |
2838 | 0 | } |
2839 | 0 | } |
2840 | | |
2841 | 0 | bool AddressSanitizer::suppressInstrumentationSiteForDebug(int &Instrumented) { |
2842 | 0 | bool ShouldInstrument = |
2843 | 0 | ClDebugMin < 0 || ClDebugMax < 0 || |
2844 | 0 | (Instrumented >= ClDebugMin && Instrumented <= ClDebugMax); |
2845 | 0 | Instrumented++; |
2846 | 0 | return !ShouldInstrument; |
2847 | 0 | } |
2848 | | |
2849 | | bool AddressSanitizer::instrumentFunction(Function &F, |
2850 | 0 | const TargetLibraryInfo *TLI) { |
2851 | 0 | if (F.empty()) |
2852 | 0 | return false; |
2853 | 0 | if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return false; |
2854 | 0 | if (!ClDebugFunc.empty() && ClDebugFunc == F.getName()) return false; |
2855 | 0 | if (F.getName().starts_with("__asan_")) return false; |
2856 | | |
2857 | 0 | bool FunctionModified = false; |
2858 | | |
2859 | | // If needed, insert __asan_init before checking for SanitizeAddress attr. |
2860 | | // This function needs to be called even if the function body is not |
2861 | | // instrumented. |
2862 | 0 | if (maybeInsertAsanInitAtFunctionEntry(F)) |
2863 | 0 | FunctionModified = true; |
2864 | | |
2865 | | // Leave if the function doesn't need instrumentation. |
2866 | 0 | if (!F.hasFnAttribute(Attribute::SanitizeAddress)) return FunctionModified; |
2867 | | |
2868 | 0 | if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) |
2869 | 0 | return FunctionModified; |
2870 | | |
2871 | 0 | LLVM_DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n"); |
2872 | |
|
2873 | 0 | initializeCallbacks(*F.getParent(), TLI); |
2874 | |
|
2875 | 0 | FunctionStateRAII CleanupObj(this); |
2876 | |
|
2877 | 0 | FunctionModified |= maybeInsertDynamicShadowAtFunctionEntry(F); |
2878 | | |
2879 | | // We can't instrument allocas used with llvm.localescape. Only static allocas |
2880 | | // can be passed to that intrinsic. |
2881 | 0 | markEscapedLocalAllocas(F); |
2882 | | |
2883 | | // We want to instrument every address only once per basic block (unless there |
2884 | | // are calls between uses). |
2885 | 0 | SmallPtrSet<Value *, 16> TempsToInstrument; |
2886 | 0 | SmallVector<InterestingMemoryOperand, 16> OperandsToInstrument; |
2887 | 0 | SmallVector<MemIntrinsic *, 16> IntrinToInstrument; |
2888 | 0 | SmallVector<Instruction *, 8> NoReturnCalls; |
2889 | 0 | SmallVector<BasicBlock *, 16> AllBlocks; |
2890 | 0 | SmallVector<Instruction *, 16> PointerComparisonsOrSubtracts; |
2891 | | |
2892 | | // Fill the set of memory operations to instrument. |
2893 | 0 | for (auto &BB : F) { |
2894 | 0 | AllBlocks.push_back(&BB); |
2895 | 0 | TempsToInstrument.clear(); |
2896 | 0 | int NumInsnsPerBB = 0; |
2897 | 0 | for (auto &Inst : BB) { |
2898 | 0 | if (LooksLikeCodeInBug11395(&Inst)) return false; |
2899 | | // Skip instructions inserted by another instrumentation. |
2900 | 0 | if (Inst.hasMetadata(LLVMContext::MD_nosanitize)) |
2901 | 0 | continue; |
2902 | 0 | SmallVector<InterestingMemoryOperand, 1> InterestingOperands; |
2903 | 0 | getInterestingMemoryOperands(&Inst, InterestingOperands); |
2904 | |
|
2905 | 0 | if (!InterestingOperands.empty()) { |
2906 | 0 | for (auto &Operand : InterestingOperands) { |
2907 | 0 | if (ClOpt && ClOptSameTemp) { |
2908 | 0 | Value *Ptr = Operand.getPtr(); |
2909 | | // If we have a mask, skip instrumentation if we've already |
2910 | | // instrumented the full object. But don't add to TempsToInstrument |
2911 | | // because we might get another load/store with a different mask. |
2912 | 0 | if (Operand.MaybeMask) { |
2913 | 0 | if (TempsToInstrument.count(Ptr)) |
2914 | 0 | continue; // We've seen this (whole) temp in the current BB. |
2915 | 0 | } else { |
2916 | 0 | if (!TempsToInstrument.insert(Ptr).second) |
2917 | 0 | continue; // We've seen this temp in the current BB. |
2918 | 0 | } |
2919 | 0 | } |
2920 | 0 | OperandsToInstrument.push_back(Operand); |
2921 | 0 | NumInsnsPerBB++; |
2922 | 0 | } |
2923 | 0 | } else if (((ClInvalidPointerPairs || ClInvalidPointerCmp) && |
2924 | 0 | isInterestingPointerComparison(&Inst)) || |
2925 | 0 | ((ClInvalidPointerPairs || ClInvalidPointerSub) && |
2926 | 0 | isInterestingPointerSubtraction(&Inst))) { |
2927 | 0 | PointerComparisonsOrSubtracts.push_back(&Inst); |
2928 | 0 | } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&Inst)) { |
2929 | | // ok, take it. |
2930 | 0 | IntrinToInstrument.push_back(MI); |
2931 | 0 | NumInsnsPerBB++; |
2932 | 0 | } else { |
2933 | 0 | if (auto *CB = dyn_cast<CallBase>(&Inst)) { |
2934 | | // A call inside BB. |
2935 | 0 | TempsToInstrument.clear(); |
2936 | 0 | if (CB->doesNotReturn()) |
2937 | 0 | NoReturnCalls.push_back(CB); |
2938 | 0 | } |
2939 | 0 | if (CallInst *CI = dyn_cast<CallInst>(&Inst)) |
2940 | 0 | maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI); |
2941 | 0 | } |
2942 | 0 | if (NumInsnsPerBB >= ClMaxInsnsToInstrumentPerBB) break; |
2943 | 0 | } |
2944 | 0 | } |
2945 | | |
2946 | 0 | bool UseCalls = (InstrumentationWithCallsThreshold >= 0 && |
2947 | 0 | OperandsToInstrument.size() + IntrinToInstrument.size() > |
2948 | 0 | (unsigned)InstrumentationWithCallsThreshold); |
2949 | 0 | const DataLayout &DL = F.getParent()->getDataLayout(); |
2950 | 0 | ObjectSizeOpts ObjSizeOpts; |
2951 | 0 | ObjSizeOpts.RoundToAlign = true; |
2952 | 0 | ObjectSizeOffsetVisitor ObjSizeVis(DL, TLI, F.getContext(), ObjSizeOpts); |
2953 | | |
2954 | | // Instrument. |
2955 | 0 | int NumInstrumented = 0; |
2956 | 0 | for (auto &Operand : OperandsToInstrument) { |
2957 | 0 | if (!suppressInstrumentationSiteForDebug(NumInstrumented)) |
2958 | 0 | instrumentMop(ObjSizeVis, Operand, UseCalls, |
2959 | 0 | F.getParent()->getDataLayout()); |
2960 | 0 | FunctionModified = true; |
2961 | 0 | } |
2962 | 0 | for (auto *Inst : IntrinToInstrument) { |
2963 | 0 | if (!suppressInstrumentationSiteForDebug(NumInstrumented)) |
2964 | 0 | instrumentMemIntrinsic(Inst); |
2965 | 0 | FunctionModified = true; |
2966 | 0 | } |
2967 | |
|
2968 | 0 | FunctionStackPoisoner FSP(F, *this); |
2969 | 0 | bool ChangedStack = FSP.runOnFunction(); |
2970 | | |
2971 | | // We must unpoison the stack before NoReturn calls (throw, _exit, etc). |
2972 | | // See e.g. https://github.com/google/sanitizers/issues/37 |
2973 | 0 | for (auto *CI : NoReturnCalls) { |
2974 | 0 | IRBuilder<> IRB(CI); |
2975 | 0 | IRB.CreateCall(AsanHandleNoReturnFunc, {}); |
2976 | 0 | } |
2977 | |
|
2978 | 0 | for (auto *Inst : PointerComparisonsOrSubtracts) { |
2979 | 0 | instrumentPointerComparisonOrSubtraction(Inst); |
2980 | 0 | FunctionModified = true; |
2981 | 0 | } |
2982 | |
|
2983 | 0 | if (ChangedStack || !NoReturnCalls.empty()) |
2984 | 0 | FunctionModified = true; |
2985 | |
|
2986 | 0 | LLVM_DEBUG(dbgs() << "ASAN done instrumenting: " << FunctionModified << " " |
2987 | 0 | << F << "\n"); |
2988 | |
|
2989 | 0 | return FunctionModified; |
2990 | 0 | } |
2991 | | |
2992 | | // Workaround for bug 11395: we don't want to instrument stack in functions |
2993 | | // with large assembly blobs (32-bit only), otherwise reg alloc may crash. |
2994 | | // FIXME: remove once the bug 11395 is fixed. |
2995 | 0 | bool AddressSanitizer::LooksLikeCodeInBug11395(Instruction *I) { |
2996 | 0 | if (LongSize != 32) return false; |
2997 | 0 | CallInst *CI = dyn_cast<CallInst>(I); |
2998 | 0 | if (!CI || !CI->isInlineAsm()) return false; |
2999 | 0 | if (CI->arg_size() <= 5) |
3000 | 0 | return false; |
3001 | | // We have inline assembly with quite a few arguments. |
3002 | 0 | return true; |
3003 | 0 | } |
3004 | | |
3005 | 0 | void FunctionStackPoisoner::initializeCallbacks(Module &M) { |
3006 | 0 | IRBuilder<> IRB(*C); |
3007 | 0 | if (ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Always || |
3008 | 0 | ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Runtime) { |
3009 | 0 | const char *MallocNameTemplate = |
3010 | 0 | ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Always |
3011 | 0 | ? kAsanStackMallocAlwaysNameTemplate |
3012 | 0 | : kAsanStackMallocNameTemplate; |
3013 | 0 | for (int Index = 0; Index <= kMaxAsanStackMallocSizeClass; Index++) { |
3014 | 0 | std::string Suffix = itostr(Index); |
3015 | 0 | AsanStackMallocFunc[Index] = M.getOrInsertFunction( |
3016 | 0 | MallocNameTemplate + Suffix, IntptrTy, IntptrTy); |
3017 | 0 | AsanStackFreeFunc[Index] = |
3018 | 0 | M.getOrInsertFunction(kAsanStackFreeNameTemplate + Suffix, |
3019 | 0 | IRB.getVoidTy(), IntptrTy, IntptrTy); |
3020 | 0 | } |
3021 | 0 | } |
3022 | 0 | if (ASan.UseAfterScope) { |
3023 | 0 | AsanPoisonStackMemoryFunc = M.getOrInsertFunction( |
3024 | 0 | kAsanPoisonStackMemoryName, IRB.getVoidTy(), IntptrTy, IntptrTy); |
3025 | 0 | AsanUnpoisonStackMemoryFunc = M.getOrInsertFunction( |
3026 | 0 | kAsanUnpoisonStackMemoryName, IRB.getVoidTy(), IntptrTy, IntptrTy); |
3027 | 0 | } |
3028 | |
|
3029 | 0 | for (size_t Val : {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf1, 0xf2, |
3030 | 0 | 0xf3, 0xf5, 0xf8}) { |
3031 | 0 | std::ostringstream Name; |
3032 | 0 | Name << kAsanSetShadowPrefix; |
3033 | 0 | Name << std::setw(2) << std::setfill('0') << std::hex << Val; |
3034 | 0 | AsanSetShadowFunc[Val] = |
3035 | 0 | M.getOrInsertFunction(Name.str(), IRB.getVoidTy(), IntptrTy, IntptrTy); |
3036 | 0 | } |
3037 | |
|
3038 | 0 | AsanAllocaPoisonFunc = M.getOrInsertFunction( |
3039 | 0 | kAsanAllocaPoison, IRB.getVoidTy(), IntptrTy, IntptrTy); |
3040 | 0 | AsanAllocasUnpoisonFunc = M.getOrInsertFunction( |
3041 | 0 | kAsanAllocasUnpoison, IRB.getVoidTy(), IntptrTy, IntptrTy); |
3042 | 0 | } |
3043 | | |
3044 | | void FunctionStackPoisoner::copyToShadowInline(ArrayRef<uint8_t> ShadowMask, |
3045 | | ArrayRef<uint8_t> ShadowBytes, |
3046 | | size_t Begin, size_t End, |
3047 | | IRBuilder<> &IRB, |
3048 | 0 | Value *ShadowBase) { |
3049 | 0 | if (Begin >= End) |
3050 | 0 | return; |
3051 | | |
3052 | 0 | const size_t LargestStoreSizeInBytes = |
3053 | 0 | std::min<size_t>(sizeof(uint64_t), ASan.LongSize / 8); |
3054 | |
|
3055 | 0 | const bool IsLittleEndian = F.getParent()->getDataLayout().isLittleEndian(); |
3056 | | |
3057 | | // Poison given range in shadow using larges store size with out leading and |
3058 | | // trailing zeros in ShadowMask. Zeros never change, so they need neither |
3059 | | // poisoning nor up-poisoning. Still we don't mind if some of them get into a |
3060 | | // middle of a store. |
3061 | 0 | for (size_t i = Begin; i < End;) { |
3062 | 0 | if (!ShadowMask[i]) { |
3063 | 0 | assert(!ShadowBytes[i]); |
3064 | 0 | ++i; |
3065 | 0 | continue; |
3066 | 0 | } |
3067 | | |
3068 | 0 | size_t StoreSizeInBytes = LargestStoreSizeInBytes; |
3069 | | // Fit store size into the range. |
3070 | 0 | while (StoreSizeInBytes > End - i) |
3071 | 0 | StoreSizeInBytes /= 2; |
3072 | | |
3073 | | // Minimize store size by trimming trailing zeros. |
3074 | 0 | for (size_t j = StoreSizeInBytes - 1; j && !ShadowMask[i + j]; --j) { |
3075 | 0 | while (j <= StoreSizeInBytes / 2) |
3076 | 0 | StoreSizeInBytes /= 2; |
3077 | 0 | } |
3078 | |
|
3079 | 0 | uint64_t Val = 0; |
3080 | 0 | for (size_t j = 0; j < StoreSizeInBytes; j++) { |
3081 | 0 | if (IsLittleEndian) |
3082 | 0 | Val |= (uint64_t)ShadowBytes[i + j] << (8 * j); |
3083 | 0 | else |
3084 | 0 | Val = (Val << 8) | ShadowBytes[i + j]; |
3085 | 0 | } |
3086 | |
|
3087 | 0 | Value *Ptr = IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)); |
3088 | 0 | Value *Poison = IRB.getIntN(StoreSizeInBytes * 8, Val); |
3089 | 0 | IRB.CreateAlignedStore( |
3090 | 0 | Poison, IRB.CreateIntToPtr(Ptr, PointerType::getUnqual(Poison->getContext())), |
3091 | 0 | Align(1)); |
3092 | |
|
3093 | 0 | i += StoreSizeInBytes; |
3094 | 0 | } |
3095 | 0 | } |
3096 | | |
3097 | | void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask, |
3098 | | ArrayRef<uint8_t> ShadowBytes, |
3099 | 0 | IRBuilder<> &IRB, Value *ShadowBase) { |
3100 | 0 | copyToShadow(ShadowMask, ShadowBytes, 0, ShadowMask.size(), IRB, ShadowBase); |
3101 | 0 | } |
3102 | | |
3103 | | void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask, |
3104 | | ArrayRef<uint8_t> ShadowBytes, |
3105 | | size_t Begin, size_t End, |
3106 | 0 | IRBuilder<> &IRB, Value *ShadowBase) { |
3107 | 0 | assert(ShadowMask.size() == ShadowBytes.size()); |
3108 | 0 | size_t Done = Begin; |
3109 | 0 | for (size_t i = Begin, j = Begin + 1; i < End; i = j++) { |
3110 | 0 | if (!ShadowMask[i]) { |
3111 | 0 | assert(!ShadowBytes[i]); |
3112 | 0 | continue; |
3113 | 0 | } |
3114 | 0 | uint8_t Val = ShadowBytes[i]; |
3115 | 0 | if (!AsanSetShadowFunc[Val]) |
3116 | 0 | continue; |
3117 | | |
3118 | | // Skip same values. |
3119 | 0 | for (; j < End && ShadowMask[j] && Val == ShadowBytes[j]; ++j) { |
3120 | 0 | } |
3121 | |
|
3122 | 0 | if (j - i >= ASan.MaxInlinePoisoningSize) { |
3123 | 0 | copyToShadowInline(ShadowMask, ShadowBytes, Done, i, IRB, ShadowBase); |
3124 | 0 | IRB.CreateCall(AsanSetShadowFunc[Val], |
3125 | 0 | {IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)), |
3126 | 0 | ConstantInt::get(IntptrTy, j - i)}); |
3127 | 0 | Done = j; |
3128 | 0 | } |
3129 | 0 | } |
3130 | |
|
3131 | 0 | copyToShadowInline(ShadowMask, ShadowBytes, Done, End, IRB, ShadowBase); |
3132 | 0 | } |
3133 | | |
3134 | | // Fake stack allocator (asan_fake_stack.h) has 11 size classes |
3135 | | // for every power of 2 from kMinStackMallocSize to kMaxAsanStackMallocSizeClass |
3136 | 0 | static int StackMallocSizeClass(uint64_t LocalStackSize) { |
3137 | 0 | assert(LocalStackSize <= kMaxStackMallocSize); |
3138 | 0 | uint64_t MaxSize = kMinStackMallocSize; |
3139 | 0 | for (int i = 0;; i++, MaxSize *= 2) |
3140 | 0 | if (LocalStackSize <= MaxSize) return i; |
3141 | 0 | llvm_unreachable("impossible LocalStackSize"); |
3142 | 0 | } |
3143 | | |
3144 | 0 | void FunctionStackPoisoner::copyArgsPassedByValToAllocas() { |
3145 | 0 | Instruction *CopyInsertPoint = &F.front().front(); |
3146 | 0 | if (CopyInsertPoint == ASan.LocalDynamicShadow) { |
3147 | | // Insert after the dynamic shadow location is determined |
3148 | 0 | CopyInsertPoint = CopyInsertPoint->getNextNode(); |
3149 | 0 | assert(CopyInsertPoint); |
3150 | 0 | } |
3151 | 0 | IRBuilder<> IRB(CopyInsertPoint); |
3152 | 0 | const DataLayout &DL = F.getParent()->getDataLayout(); |
3153 | 0 | for (Argument &Arg : F.args()) { |
3154 | 0 | if (Arg.hasByValAttr()) { |
3155 | 0 | Type *Ty = Arg.getParamByValType(); |
3156 | 0 | const Align Alignment = |
3157 | 0 | DL.getValueOrABITypeAlignment(Arg.getParamAlign(), Ty); |
3158 | |
|
3159 | 0 | AllocaInst *AI = IRB.CreateAlloca( |
3160 | 0 | Ty, nullptr, |
3161 | 0 | (Arg.hasName() ? Arg.getName() : "Arg" + Twine(Arg.getArgNo())) + |
3162 | 0 | ".byval"); |
3163 | 0 | AI->setAlignment(Alignment); |
3164 | 0 | Arg.replaceAllUsesWith(AI); |
3165 | |
|
3166 | 0 | uint64_t AllocSize = DL.getTypeAllocSize(Ty); |
3167 | 0 | IRB.CreateMemCpy(AI, Alignment, &Arg, Alignment, AllocSize); |
3168 | 0 | } |
3169 | 0 | } |
3170 | 0 | } |
3171 | | |
3172 | | PHINode *FunctionStackPoisoner::createPHI(IRBuilder<> &IRB, Value *Cond, |
3173 | | Value *ValueIfTrue, |
3174 | | Instruction *ThenTerm, |
3175 | 0 | Value *ValueIfFalse) { |
3176 | 0 | PHINode *PHI = IRB.CreatePHI(IntptrTy, 2); |
3177 | 0 | BasicBlock *CondBlock = cast<Instruction>(Cond)->getParent(); |
3178 | 0 | PHI->addIncoming(ValueIfFalse, CondBlock); |
3179 | 0 | BasicBlock *ThenBlock = ThenTerm->getParent(); |
3180 | 0 | PHI->addIncoming(ValueIfTrue, ThenBlock); |
3181 | 0 | return PHI; |
3182 | 0 | } |
3183 | | |
3184 | | Value *FunctionStackPoisoner::createAllocaForLayout( |
3185 | 0 | IRBuilder<> &IRB, const ASanStackFrameLayout &L, bool Dynamic) { |
3186 | 0 | AllocaInst *Alloca; |
3187 | 0 | if (Dynamic) { |
3188 | 0 | Alloca = IRB.CreateAlloca(IRB.getInt8Ty(), |
3189 | 0 | ConstantInt::get(IRB.getInt64Ty(), L.FrameSize), |
3190 | 0 | "MyAlloca"); |
3191 | 0 | } else { |
3192 | 0 | Alloca = IRB.CreateAlloca(ArrayType::get(IRB.getInt8Ty(), L.FrameSize), |
3193 | 0 | nullptr, "MyAlloca"); |
3194 | 0 | assert(Alloca->isStaticAlloca()); |
3195 | 0 | } |
3196 | 0 | assert((ClRealignStack & (ClRealignStack - 1)) == 0); |
3197 | 0 | uint64_t FrameAlignment = std::max(L.FrameAlignment, uint64_t(ClRealignStack)); |
3198 | 0 | Alloca->setAlignment(Align(FrameAlignment)); |
3199 | 0 | return IRB.CreatePointerCast(Alloca, IntptrTy); |
3200 | 0 | } |
3201 | | |
3202 | 0 | void FunctionStackPoisoner::createDynamicAllocasInitStorage() { |
3203 | 0 | BasicBlock &FirstBB = *F.begin(); |
3204 | 0 | IRBuilder<> IRB(dyn_cast<Instruction>(FirstBB.begin())); |
3205 | 0 | DynamicAllocaLayout = IRB.CreateAlloca(IntptrTy, nullptr); |
3206 | 0 | IRB.CreateStore(Constant::getNullValue(IntptrTy), DynamicAllocaLayout); |
3207 | 0 | DynamicAllocaLayout->setAlignment(Align(32)); |
3208 | 0 | } |
3209 | | |
3210 | 0 | void FunctionStackPoisoner::processDynamicAllocas() { |
3211 | 0 | if (!ClInstrumentDynamicAllocas || DynamicAllocaVec.empty()) { |
3212 | 0 | assert(DynamicAllocaPoisonCallVec.empty()); |
3213 | 0 | return; |
3214 | 0 | } |
3215 | | |
3216 | | // Insert poison calls for lifetime intrinsics for dynamic allocas. |
3217 | 0 | for (const auto &APC : DynamicAllocaPoisonCallVec) { |
3218 | 0 | assert(APC.InsBefore); |
3219 | 0 | assert(APC.AI); |
3220 | 0 | assert(ASan.isInterestingAlloca(*APC.AI)); |
3221 | 0 | assert(!APC.AI->isStaticAlloca()); |
3222 | | |
3223 | 0 | IRBuilder<> IRB(APC.InsBefore); |
3224 | 0 | poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison); |
3225 | | // Dynamic allocas will be unpoisoned unconditionally below in |
3226 | | // unpoisonDynamicAllocas. |
3227 | | // Flag that we need unpoison static allocas. |
3228 | 0 | } |
3229 | | |
3230 | | // Handle dynamic allocas. |
3231 | 0 | createDynamicAllocasInitStorage(); |
3232 | 0 | for (auto &AI : DynamicAllocaVec) |
3233 | 0 | handleDynamicAllocaCall(AI); |
3234 | 0 | unpoisonDynamicAllocas(); |
3235 | 0 | } |
3236 | | |
3237 | | /// Collect instructions in the entry block after \p InsBefore which initialize |
3238 | | /// permanent storage for a function argument. These instructions must remain in |
3239 | | /// the entry block so that uninitialized values do not appear in backtraces. An |
3240 | | /// added benefit is that this conserves spill slots. This does not move stores |
3241 | | /// before instrumented / "interesting" allocas. |
3242 | | static void findStoresToUninstrumentedArgAllocas( |
3243 | | AddressSanitizer &ASan, Instruction &InsBefore, |
3244 | 0 | SmallVectorImpl<Instruction *> &InitInsts) { |
3245 | 0 | Instruction *Start = InsBefore.getNextNonDebugInstruction(); |
3246 | 0 | for (Instruction *It = Start; It; It = It->getNextNonDebugInstruction()) { |
3247 | | // Argument initialization looks like: |
3248 | | // 1) store <Argument>, <Alloca> OR |
3249 | | // 2) <CastArgument> = cast <Argument> to ... |
3250 | | // store <CastArgument> to <Alloca> |
3251 | | // Do not consider any other kind of instruction. |
3252 | | // |
3253 | | // Note: This covers all known cases, but may not be exhaustive. An |
3254 | | // alternative to pattern-matching stores is to DFS over all Argument uses: |
3255 | | // this might be more general, but is probably much more complicated. |
3256 | 0 | if (isa<AllocaInst>(It) || isa<CastInst>(It)) |
3257 | 0 | continue; |
3258 | 0 | if (auto *Store = dyn_cast<StoreInst>(It)) { |
3259 | | // The store destination must be an alloca that isn't interesting for |
3260 | | // ASan to instrument. These are moved up before InsBefore, and they're |
3261 | | // not interesting because allocas for arguments can be mem2reg'd. |
3262 | 0 | auto *Alloca = dyn_cast<AllocaInst>(Store->getPointerOperand()); |
3263 | 0 | if (!Alloca || ASan.isInterestingAlloca(*Alloca)) |
3264 | 0 | continue; |
3265 | | |
3266 | 0 | Value *Val = Store->getValueOperand(); |
3267 | 0 | bool IsDirectArgInit = isa<Argument>(Val); |
3268 | 0 | bool IsArgInitViaCast = |
3269 | 0 | isa<CastInst>(Val) && |
3270 | 0 | isa<Argument>(cast<CastInst>(Val)->getOperand(0)) && |
3271 | | // Check that the cast appears directly before the store. Otherwise |
3272 | | // moving the cast before InsBefore may break the IR. |
3273 | 0 | Val == It->getPrevNonDebugInstruction(); |
3274 | 0 | bool IsArgInit = IsDirectArgInit || IsArgInitViaCast; |
3275 | 0 | if (!IsArgInit) |
3276 | 0 | continue; |
3277 | | |
3278 | 0 | if (IsArgInitViaCast) |
3279 | 0 | InitInsts.push_back(cast<Instruction>(Val)); |
3280 | 0 | InitInsts.push_back(Store); |
3281 | 0 | continue; |
3282 | 0 | } |
3283 | | |
3284 | | // Do not reorder past unknown instructions: argument initialization should |
3285 | | // only involve casts and stores. |
3286 | 0 | return; |
3287 | 0 | } |
3288 | 0 | } |
3289 | | |
3290 | 0 | void FunctionStackPoisoner::processStaticAllocas() { |
3291 | 0 | if (AllocaVec.empty()) { |
3292 | 0 | assert(StaticAllocaPoisonCallVec.empty()); |
3293 | 0 | return; |
3294 | 0 | } |
3295 | | |
3296 | 0 | int StackMallocIdx = -1; |
3297 | 0 | DebugLoc EntryDebugLocation; |
3298 | 0 | if (auto SP = F.getSubprogram()) |
3299 | 0 | EntryDebugLocation = |
3300 | 0 | DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP); |
3301 | |
|
3302 | 0 | Instruction *InsBefore = AllocaVec[0]; |
3303 | 0 | IRBuilder<> IRB(InsBefore); |
3304 | | |
3305 | | // Make sure non-instrumented allocas stay in the entry block. Otherwise, |
3306 | | // debug info is broken, because only entry-block allocas are treated as |
3307 | | // regular stack slots. |
3308 | 0 | auto InsBeforeB = InsBefore->getParent(); |
3309 | 0 | assert(InsBeforeB == &F.getEntryBlock()); |
3310 | 0 | for (auto *AI : StaticAllocasToMoveUp) |
3311 | 0 | if (AI->getParent() == InsBeforeB) |
3312 | 0 | AI->moveBefore(InsBefore); |
3313 | | |
3314 | | // Move stores of arguments into entry-block allocas as well. This prevents |
3315 | | // extra stack slots from being generated (to house the argument values until |
3316 | | // they can be stored into the allocas). This also prevents uninitialized |
3317 | | // values from being shown in backtraces. |
3318 | 0 | SmallVector<Instruction *, 8> ArgInitInsts; |
3319 | 0 | findStoresToUninstrumentedArgAllocas(ASan, *InsBefore, ArgInitInsts); |
3320 | 0 | for (Instruction *ArgInitInst : ArgInitInsts) |
3321 | 0 | ArgInitInst->moveBefore(InsBefore); |
3322 | | |
3323 | | // If we have a call to llvm.localescape, keep it in the entry block. |
3324 | 0 | if (LocalEscapeCall) LocalEscapeCall->moveBefore(InsBefore); |
3325 | |
|
3326 | 0 | SmallVector<ASanStackVariableDescription, 16> SVD; |
3327 | 0 | SVD.reserve(AllocaVec.size()); |
3328 | 0 | for (AllocaInst *AI : AllocaVec) { |
3329 | 0 | ASanStackVariableDescription D = {AI->getName().data(), |
3330 | 0 | ASan.getAllocaSizeInBytes(*AI), |
3331 | 0 | 0, |
3332 | 0 | AI->getAlign().value(), |
3333 | 0 | AI, |
3334 | 0 | 0, |
3335 | 0 | 0}; |
3336 | 0 | SVD.push_back(D); |
3337 | 0 | } |
3338 | | |
3339 | | // Minimal header size (left redzone) is 4 pointers, |
3340 | | // i.e. 32 bytes on 64-bit platforms and 16 bytes in 32-bit platforms. |
3341 | 0 | uint64_t Granularity = 1ULL << Mapping.Scale; |
3342 | 0 | uint64_t MinHeaderSize = std::max((uint64_t)ASan.LongSize / 2, Granularity); |
3343 | 0 | const ASanStackFrameLayout &L = |
3344 | 0 | ComputeASanStackFrameLayout(SVD, Granularity, MinHeaderSize); |
3345 | | |
3346 | | // Build AllocaToSVDMap for ASanStackVariableDescription lookup. |
3347 | 0 | DenseMap<const AllocaInst *, ASanStackVariableDescription *> AllocaToSVDMap; |
3348 | 0 | for (auto &Desc : SVD) |
3349 | 0 | AllocaToSVDMap[Desc.AI] = &Desc; |
3350 | | |
3351 | | // Update SVD with information from lifetime intrinsics. |
3352 | 0 | for (const auto &APC : StaticAllocaPoisonCallVec) { |
3353 | 0 | assert(APC.InsBefore); |
3354 | 0 | assert(APC.AI); |
3355 | 0 | assert(ASan.isInterestingAlloca(*APC.AI)); |
3356 | 0 | assert(APC.AI->isStaticAlloca()); |
3357 | | |
3358 | 0 | ASanStackVariableDescription &Desc = *AllocaToSVDMap[APC.AI]; |
3359 | 0 | Desc.LifetimeSize = Desc.Size; |
3360 | 0 | if (const DILocation *FnLoc = EntryDebugLocation.get()) { |
3361 | 0 | if (const DILocation *LifetimeLoc = APC.InsBefore->getDebugLoc().get()) { |
3362 | 0 | if (LifetimeLoc->getFile() == FnLoc->getFile()) |
3363 | 0 | if (unsigned Line = LifetimeLoc->getLine()) |
3364 | 0 | Desc.Line = std::min(Desc.Line ? Desc.Line : Line, Line); |
3365 | 0 | } |
3366 | 0 | } |
3367 | 0 | } |
3368 | |
|
3369 | 0 | auto DescriptionString = ComputeASanStackFrameDescription(SVD); |
3370 | 0 | LLVM_DEBUG(dbgs() << DescriptionString << " --- " << L.FrameSize << "\n"); |
3371 | 0 | uint64_t LocalStackSize = L.FrameSize; |
3372 | 0 | bool DoStackMalloc = |
3373 | 0 | ASan.UseAfterReturn != AsanDetectStackUseAfterReturnMode::Never && |
3374 | 0 | !ASan.CompileKernel && LocalStackSize <= kMaxStackMallocSize; |
3375 | 0 | bool DoDynamicAlloca = ClDynamicAllocaStack; |
3376 | | // Don't do dynamic alloca or stack malloc if: |
3377 | | // 1) There is inline asm: too often it makes assumptions on which registers |
3378 | | // are available. |
3379 | | // 2) There is a returns_twice call (typically setjmp), which is |
3380 | | // optimization-hostile, and doesn't play well with introduced indirect |
3381 | | // register-relative calculation of local variable addresses. |
3382 | 0 | DoDynamicAlloca &= !HasInlineAsm && !HasReturnsTwiceCall; |
3383 | 0 | DoStackMalloc &= !HasInlineAsm && !HasReturnsTwiceCall; |
3384 | |
|
3385 | 0 | Value *StaticAlloca = |
3386 | 0 | DoDynamicAlloca ? nullptr : createAllocaForLayout(IRB, L, false); |
3387 | |
|
3388 | 0 | Value *FakeStack; |
3389 | 0 | Value *LocalStackBase; |
3390 | 0 | Value *LocalStackBaseAlloca; |
3391 | 0 | uint8_t DIExprFlags = DIExpression::ApplyOffset; |
3392 | |
|
3393 | 0 | if (DoStackMalloc) { |
3394 | 0 | LocalStackBaseAlloca = |
3395 | 0 | IRB.CreateAlloca(IntptrTy, nullptr, "asan_local_stack_base"); |
3396 | 0 | if (ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Runtime) { |
3397 | | // void *FakeStack = __asan_option_detect_stack_use_after_return |
3398 | | // ? __asan_stack_malloc_N(LocalStackSize) |
3399 | | // : nullptr; |
3400 | | // void *LocalStackBase = (FakeStack) ? FakeStack : |
3401 | | // alloca(LocalStackSize); |
3402 | 0 | Constant *OptionDetectUseAfterReturn = F.getParent()->getOrInsertGlobal( |
3403 | 0 | kAsanOptionDetectUseAfterReturn, IRB.getInt32Ty()); |
3404 | 0 | Value *UseAfterReturnIsEnabled = IRB.CreateICmpNE( |
3405 | 0 | IRB.CreateLoad(IRB.getInt32Ty(), OptionDetectUseAfterReturn), |
3406 | 0 | Constant::getNullValue(IRB.getInt32Ty())); |
3407 | 0 | Instruction *Term = |
3408 | 0 | SplitBlockAndInsertIfThen(UseAfterReturnIsEnabled, InsBefore, false); |
3409 | 0 | IRBuilder<> IRBIf(Term); |
3410 | 0 | StackMallocIdx = StackMallocSizeClass(LocalStackSize); |
3411 | 0 | assert(StackMallocIdx <= kMaxAsanStackMallocSizeClass); |
3412 | 0 | Value *FakeStackValue = |
3413 | 0 | IRBIf.CreateCall(AsanStackMallocFunc[StackMallocIdx], |
3414 | 0 | ConstantInt::get(IntptrTy, LocalStackSize)); |
3415 | 0 | IRB.SetInsertPoint(InsBefore); |
3416 | 0 | FakeStack = createPHI(IRB, UseAfterReturnIsEnabled, FakeStackValue, Term, |
3417 | 0 | ConstantInt::get(IntptrTy, 0)); |
3418 | 0 | } else { |
3419 | | // assert(ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode:Always) |
3420 | | // void *FakeStack = __asan_stack_malloc_N(LocalStackSize); |
3421 | | // void *LocalStackBase = (FakeStack) ? FakeStack : |
3422 | | // alloca(LocalStackSize); |
3423 | 0 | StackMallocIdx = StackMallocSizeClass(LocalStackSize); |
3424 | 0 | FakeStack = IRB.CreateCall(AsanStackMallocFunc[StackMallocIdx], |
3425 | 0 | ConstantInt::get(IntptrTy, LocalStackSize)); |
3426 | 0 | } |
3427 | 0 | Value *NoFakeStack = |
3428 | 0 | IRB.CreateICmpEQ(FakeStack, Constant::getNullValue(IntptrTy)); |
3429 | 0 | Instruction *Term = |
3430 | 0 | SplitBlockAndInsertIfThen(NoFakeStack, InsBefore, false); |
3431 | 0 | IRBuilder<> IRBIf(Term); |
3432 | 0 | Value *AllocaValue = |
3433 | 0 | DoDynamicAlloca ? createAllocaForLayout(IRBIf, L, true) : StaticAlloca; |
3434 | |
|
3435 | 0 | IRB.SetInsertPoint(InsBefore); |
3436 | 0 | LocalStackBase = createPHI(IRB, NoFakeStack, AllocaValue, Term, FakeStack); |
3437 | 0 | IRB.CreateStore(LocalStackBase, LocalStackBaseAlloca); |
3438 | 0 | DIExprFlags |= DIExpression::DerefBefore; |
3439 | 0 | } else { |
3440 | | // void *FakeStack = nullptr; |
3441 | | // void *LocalStackBase = alloca(LocalStackSize); |
3442 | 0 | FakeStack = ConstantInt::get(IntptrTy, 0); |
3443 | 0 | LocalStackBase = |
3444 | 0 | DoDynamicAlloca ? createAllocaForLayout(IRB, L, true) : StaticAlloca; |
3445 | 0 | LocalStackBaseAlloca = LocalStackBase; |
3446 | 0 | } |
3447 | | |
3448 | | // It shouldn't matter whether we pass an `alloca` or a `ptrtoint` as the |
3449 | | // dbg.declare address opereand, but passing a `ptrtoint` seems to confuse |
3450 | | // later passes and can result in dropped variable coverage in debug info. |
3451 | 0 | Value *LocalStackBaseAllocaPtr = |
3452 | 0 | isa<PtrToIntInst>(LocalStackBaseAlloca) |
3453 | 0 | ? cast<PtrToIntInst>(LocalStackBaseAlloca)->getPointerOperand() |
3454 | 0 | : LocalStackBaseAlloca; |
3455 | 0 | assert(isa<AllocaInst>(LocalStackBaseAllocaPtr) && |
3456 | 0 | "Variable descriptions relative to ASan stack base will be dropped"); |
3457 | | |
3458 | | // Replace Alloca instructions with base+offset. |
3459 | 0 | for (const auto &Desc : SVD) { |
3460 | 0 | AllocaInst *AI = Desc.AI; |
3461 | 0 | replaceDbgDeclare(AI, LocalStackBaseAllocaPtr, DIB, DIExprFlags, |
3462 | 0 | Desc.Offset); |
3463 | 0 | Value *NewAllocaPtr = IRB.CreateIntToPtr( |
3464 | 0 | IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Desc.Offset)), |
3465 | 0 | AI->getType()); |
3466 | 0 | AI->replaceAllUsesWith(NewAllocaPtr); |
3467 | 0 | } |
3468 | | |
3469 | | // The left-most redzone has enough space for at least 4 pointers. |
3470 | | // Write the Magic value to redzone[0]. |
3471 | 0 | Value *BasePlus0 = IRB.CreateIntToPtr(LocalStackBase, IntptrPtrTy); |
3472 | 0 | IRB.CreateStore(ConstantInt::get(IntptrTy, kCurrentStackFrameMagic), |
3473 | 0 | BasePlus0); |
3474 | | // Write the frame description constant to redzone[1]. |
3475 | 0 | Value *BasePlus1 = IRB.CreateIntToPtr( |
3476 | 0 | IRB.CreateAdd(LocalStackBase, |
3477 | 0 | ConstantInt::get(IntptrTy, ASan.LongSize / 8)), |
3478 | 0 | IntptrPtrTy); |
3479 | 0 | GlobalVariable *StackDescriptionGlobal = |
3480 | 0 | createPrivateGlobalForString(*F.getParent(), DescriptionString, |
3481 | 0 | /*AllowMerging*/ true, kAsanGenPrefix); |
3482 | 0 | Value *Description = IRB.CreatePointerCast(StackDescriptionGlobal, IntptrTy); |
3483 | 0 | IRB.CreateStore(Description, BasePlus1); |
3484 | | // Write the PC to redzone[2]. |
3485 | 0 | Value *BasePlus2 = IRB.CreateIntToPtr( |
3486 | 0 | IRB.CreateAdd(LocalStackBase, |
3487 | 0 | ConstantInt::get(IntptrTy, 2 * ASan.LongSize / 8)), |
3488 | 0 | IntptrPtrTy); |
3489 | 0 | IRB.CreateStore(IRB.CreatePointerCast(&F, IntptrTy), BasePlus2); |
3490 | |
|
3491 | 0 | const auto &ShadowAfterScope = GetShadowBytesAfterScope(SVD, L); |
3492 | | |
3493 | | // Poison the stack red zones at the entry. |
3494 | 0 | Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB); |
3495 | | // As mask we must use most poisoned case: red zones and after scope. |
3496 | | // As bytes we can use either the same or just red zones only. |
3497 | 0 | copyToShadow(ShadowAfterScope, ShadowAfterScope, IRB, ShadowBase); |
3498 | |
|
3499 | 0 | if (!StaticAllocaPoisonCallVec.empty()) { |
3500 | 0 | const auto &ShadowInScope = GetShadowBytes(SVD, L); |
3501 | | |
3502 | | // Poison static allocas near lifetime intrinsics. |
3503 | 0 | for (const auto &APC : StaticAllocaPoisonCallVec) { |
3504 | 0 | const ASanStackVariableDescription &Desc = *AllocaToSVDMap[APC.AI]; |
3505 | 0 | assert(Desc.Offset % L.Granularity == 0); |
3506 | 0 | size_t Begin = Desc.Offset / L.Granularity; |
3507 | 0 | size_t End = Begin + (APC.Size + L.Granularity - 1) / L.Granularity; |
3508 | |
|
3509 | 0 | IRBuilder<> IRB(APC.InsBefore); |
3510 | 0 | copyToShadow(ShadowAfterScope, |
3511 | 0 | APC.DoPoison ? ShadowAfterScope : ShadowInScope, Begin, End, |
3512 | 0 | IRB, ShadowBase); |
3513 | 0 | } |
3514 | 0 | } |
3515 | |
|
3516 | 0 | SmallVector<uint8_t, 64> ShadowClean(ShadowAfterScope.size(), 0); |
3517 | 0 | SmallVector<uint8_t, 64> ShadowAfterReturn; |
3518 | | |
3519 | | // (Un)poison the stack before all ret instructions. |
3520 | 0 | for (Instruction *Ret : RetVec) { |
3521 | 0 | IRBuilder<> IRBRet(Ret); |
3522 | | // Mark the current frame as retired. |
3523 | 0 | IRBRet.CreateStore(ConstantInt::get(IntptrTy, kRetiredStackFrameMagic), |
3524 | 0 | BasePlus0); |
3525 | 0 | if (DoStackMalloc) { |
3526 | 0 | assert(StackMallocIdx >= 0); |
3527 | | // if FakeStack != 0 // LocalStackBase == FakeStack |
3528 | | // // In use-after-return mode, poison the whole stack frame. |
3529 | | // if StackMallocIdx <= 4 |
3530 | | // // For small sizes inline the whole thing: |
3531 | | // memset(ShadowBase, kAsanStackAfterReturnMagic, ShadowSize); |
3532 | | // **SavedFlagPtr(FakeStack) = 0 |
3533 | | // else |
3534 | | // __asan_stack_free_N(FakeStack, LocalStackSize) |
3535 | | // else |
3536 | | // <This is not a fake stack; unpoison the redzones> |
3537 | 0 | Value *Cmp = |
3538 | 0 | IRBRet.CreateICmpNE(FakeStack, Constant::getNullValue(IntptrTy)); |
3539 | 0 | Instruction *ThenTerm, *ElseTerm; |
3540 | 0 | SplitBlockAndInsertIfThenElse(Cmp, Ret, &ThenTerm, &ElseTerm); |
3541 | |
|
3542 | 0 | IRBuilder<> IRBPoison(ThenTerm); |
3543 | 0 | if (ASan.MaxInlinePoisoningSize != 0 && StackMallocIdx <= 4) { |
3544 | 0 | int ClassSize = kMinStackMallocSize << StackMallocIdx; |
3545 | 0 | ShadowAfterReturn.resize(ClassSize / L.Granularity, |
3546 | 0 | kAsanStackUseAfterReturnMagic); |
3547 | 0 | copyToShadow(ShadowAfterReturn, ShadowAfterReturn, IRBPoison, |
3548 | 0 | ShadowBase); |
3549 | 0 | Value *SavedFlagPtrPtr = IRBPoison.CreateAdd( |
3550 | 0 | FakeStack, |
3551 | 0 | ConstantInt::get(IntptrTy, ClassSize - ASan.LongSize / 8)); |
3552 | 0 | Value *SavedFlagPtr = IRBPoison.CreateLoad( |
3553 | 0 | IntptrTy, IRBPoison.CreateIntToPtr(SavedFlagPtrPtr, IntptrPtrTy)); |
3554 | 0 | IRBPoison.CreateStore( |
3555 | 0 | Constant::getNullValue(IRBPoison.getInt8Ty()), |
3556 | 0 | IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getPtrTy())); |
3557 | 0 | } else { |
3558 | | // For larger frames call __asan_stack_free_*. |
3559 | 0 | IRBPoison.CreateCall( |
3560 | 0 | AsanStackFreeFunc[StackMallocIdx], |
3561 | 0 | {FakeStack, ConstantInt::get(IntptrTy, LocalStackSize)}); |
3562 | 0 | } |
3563 | |
|
3564 | 0 | IRBuilder<> IRBElse(ElseTerm); |
3565 | 0 | copyToShadow(ShadowAfterScope, ShadowClean, IRBElse, ShadowBase); |
3566 | 0 | } else { |
3567 | 0 | copyToShadow(ShadowAfterScope, ShadowClean, IRBRet, ShadowBase); |
3568 | 0 | } |
3569 | 0 | } |
3570 | | |
3571 | | // We are done. Remove the old unused alloca instructions. |
3572 | 0 | for (auto *AI : AllocaVec) |
3573 | 0 | AI->eraseFromParent(); |
3574 | 0 | } |
3575 | | |
3576 | | void FunctionStackPoisoner::poisonAlloca(Value *V, uint64_t Size, |
3577 | 0 | IRBuilder<> &IRB, bool DoPoison) { |
3578 | | // For now just insert the call to ASan runtime. |
3579 | 0 | Value *AddrArg = IRB.CreatePointerCast(V, IntptrTy); |
3580 | 0 | Value *SizeArg = ConstantInt::get(IntptrTy, Size); |
3581 | 0 | IRB.CreateCall( |
3582 | 0 | DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc, |
3583 | 0 | {AddrArg, SizeArg}); |
3584 | 0 | } |
3585 | | |
3586 | | // Handling llvm.lifetime intrinsics for a given %alloca: |
3587 | | // (1) collect all llvm.lifetime.xxx(%size, %value) describing the alloca. |
3588 | | // (2) if %size is constant, poison memory for llvm.lifetime.end (to detect |
3589 | | // invalid accesses) and unpoison it for llvm.lifetime.start (the memory |
3590 | | // could be poisoned by previous llvm.lifetime.end instruction, as the |
3591 | | // variable may go in and out of scope several times, e.g. in loops). |
3592 | | // (3) if we poisoned at least one %alloca in a function, |
3593 | | // unpoison the whole stack frame at function exit. |
3594 | 0 | void FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) { |
3595 | 0 | IRBuilder<> IRB(AI); |
3596 | |
|
3597 | 0 | const Align Alignment = std::max(Align(kAllocaRzSize), AI->getAlign()); |
3598 | 0 | const uint64_t AllocaRedzoneMask = kAllocaRzSize - 1; |
3599 | |
|
3600 | 0 | Value *Zero = Constant::getNullValue(IntptrTy); |
3601 | 0 | Value *AllocaRzSize = ConstantInt::get(IntptrTy, kAllocaRzSize); |
3602 | 0 | Value *AllocaRzMask = ConstantInt::get(IntptrTy, AllocaRedzoneMask); |
3603 | | |
3604 | | // Since we need to extend alloca with additional memory to locate |
3605 | | // redzones, and OldSize is number of allocated blocks with |
3606 | | // ElementSize size, get allocated memory size in bytes by |
3607 | | // OldSize * ElementSize. |
3608 | 0 | const unsigned ElementSize = |
3609 | 0 | F.getParent()->getDataLayout().getTypeAllocSize(AI->getAllocatedType()); |
3610 | 0 | Value *OldSize = |
3611 | 0 | IRB.CreateMul(IRB.CreateIntCast(AI->getArraySize(), IntptrTy, false), |
3612 | 0 | ConstantInt::get(IntptrTy, ElementSize)); |
3613 | | |
3614 | | // PartialSize = OldSize % 32 |
3615 | 0 | Value *PartialSize = IRB.CreateAnd(OldSize, AllocaRzMask); |
3616 | | |
3617 | | // Misalign = kAllocaRzSize - PartialSize; |
3618 | 0 | Value *Misalign = IRB.CreateSub(AllocaRzSize, PartialSize); |
3619 | | |
3620 | | // PartialPadding = Misalign != kAllocaRzSize ? Misalign : 0; |
3621 | 0 | Value *Cond = IRB.CreateICmpNE(Misalign, AllocaRzSize); |
3622 | 0 | Value *PartialPadding = IRB.CreateSelect(Cond, Misalign, Zero); |
3623 | | |
3624 | | // AdditionalChunkSize = Alignment + PartialPadding + kAllocaRzSize |
3625 | | // Alignment is added to locate left redzone, PartialPadding for possible |
3626 | | // partial redzone and kAllocaRzSize for right redzone respectively. |
3627 | 0 | Value *AdditionalChunkSize = IRB.CreateAdd( |
3628 | 0 | ConstantInt::get(IntptrTy, Alignment.value() + kAllocaRzSize), |
3629 | 0 | PartialPadding); |
3630 | |
|
3631 | 0 | Value *NewSize = IRB.CreateAdd(OldSize, AdditionalChunkSize); |
3632 | | |
3633 | | // Insert new alloca with new NewSize and Alignment params. |
3634 | 0 | AllocaInst *NewAlloca = IRB.CreateAlloca(IRB.getInt8Ty(), NewSize); |
3635 | 0 | NewAlloca->setAlignment(Alignment); |
3636 | | |
3637 | | // NewAddress = Address + Alignment |
3638 | 0 | Value *NewAddress = |
3639 | 0 | IRB.CreateAdd(IRB.CreatePtrToInt(NewAlloca, IntptrTy), |
3640 | 0 | ConstantInt::get(IntptrTy, Alignment.value())); |
3641 | | |
3642 | | // Insert __asan_alloca_poison call for new created alloca. |
3643 | 0 | IRB.CreateCall(AsanAllocaPoisonFunc, {NewAddress, OldSize}); |
3644 | | |
3645 | | // Store the last alloca's address to DynamicAllocaLayout. We'll need this |
3646 | | // for unpoisoning stuff. |
3647 | 0 | IRB.CreateStore(IRB.CreatePtrToInt(NewAlloca, IntptrTy), DynamicAllocaLayout); |
3648 | |
|
3649 | 0 | Value *NewAddressPtr = IRB.CreateIntToPtr(NewAddress, AI->getType()); |
3650 | | |
3651 | | // Replace all uses of AddessReturnedByAlloca with NewAddressPtr. |
3652 | 0 | AI->replaceAllUsesWith(NewAddressPtr); |
3653 | | |
3654 | | // We are done. Erase old alloca from parent. |
3655 | 0 | AI->eraseFromParent(); |
3656 | 0 | } |
3657 | | |
3658 | | // isSafeAccess returns true if Addr is always inbounds with respect to its |
3659 | | // base object. For example, it is a field access or an array access with |
3660 | | // constant inbounds index. |
3661 | | bool AddressSanitizer::isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis, |
3662 | 0 | Value *Addr, TypeSize TypeStoreSize) const { |
3663 | 0 | if (TypeStoreSize.isScalable()) |
3664 | | // TODO: We can use vscale_range to convert a scalable value to an |
3665 | | // upper bound on the access size. |
3666 | 0 | return false; |
3667 | | |
3668 | 0 | SizeOffsetAPInt SizeOffset = ObjSizeVis.compute(Addr); |
3669 | 0 | if (!SizeOffset.bothKnown()) |
3670 | 0 | return false; |
3671 | | |
3672 | 0 | uint64_t Size = SizeOffset.Size.getZExtValue(); |
3673 | 0 | int64_t Offset = SizeOffset.Offset.getSExtValue(); |
3674 | | |
3675 | | // Three checks are required to ensure safety: |
3676 | | // . Offset >= 0 (since the offset is given from the base ptr) |
3677 | | // . Size >= Offset (unsigned) |
3678 | | // . Size - Offset >= NeededSize (unsigned) |
3679 | 0 | return Offset >= 0 && Size >= uint64_t(Offset) && |
3680 | 0 | Size - uint64_t(Offset) >= TypeStoreSize / 8; |
3681 | 0 | } |