LLVM 24.0.0git
DataFlowSanitizer.cpp
Go to the documentation of this file.
1//===- DataFlowSanitizer.cpp - dynamic data flow analysis -----------------===//
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/// \file
10/// This file is a part of DataFlowSanitizer, a generalised dynamic data flow
11/// analysis.
12///
13/// Unlike other Sanitizer tools, this tool is not designed to detect a specific
14/// class of bugs on its own. Instead, it provides a generic dynamic data flow
15/// analysis framework to be used by clients to help detect application-specific
16/// issues within their own code.
17///
18/// The analysis is based on automatic propagation of data flow labels (also
19/// known as taint labels) through a program as it performs computation.
20///
21/// Argument and return value labels are passed through TLS variables
22/// __dfsan_arg_tls and __dfsan_retval_tls.
23///
24/// Each byte of application memory is backed by a shadow memory byte. The
25/// shadow byte can represent up to 8 labels. On Linux/x86_64, memory is then
26/// laid out as follows:
27///
28/// +--------------------+ 0x800000000000 (top of memory)
29/// | application 3 |
30/// +--------------------+ 0x700000000000
31/// | invalid |
32/// +--------------------+ 0x610000000000
33/// | origin 1 |
34/// +--------------------+ 0x600000000000
35/// | application 2 |
36/// +--------------------+ 0x510000000000
37/// | shadow 1 |
38/// +--------------------+ 0x500000000000
39/// | invalid |
40/// +--------------------+ 0x400000000000
41/// | origin 3 |
42/// +--------------------+ 0x300000000000
43/// | shadow 3 |
44/// +--------------------+ 0x200000000000
45/// | origin 2 |
46/// +--------------------+ 0x110000000000
47/// | invalid |
48/// +--------------------+ 0x100000000000
49/// | shadow 2 |
50/// +--------------------+ 0x010000000000
51/// | application 1 |
52/// +--------------------+ 0x000000000000
53///
54/// MEM_TO_SHADOW(mem) = mem ^ 0x500000000000
55/// SHADOW_TO_ORIGIN(shadow) = shadow + 0x100000000000
56///
57/// For more information, please refer to the design document:
58/// http://clang.llvm.org/docs/DataFlowSanitizerDesign.html
59//
60//===----------------------------------------------------------------------===//
61
63#include "llvm/ADT/DenseMap.h"
64#include "llvm/ADT/DenseSet.h"
68#include "llvm/ADT/StringRef.h"
69#include "llvm/ADT/StringSet.h"
70#include "llvm/ADT/iterator.h"
75#include "llvm/IR/Argument.h"
77#include "llvm/IR/Attributes.h"
78#include "llvm/IR/BasicBlock.h"
79#include "llvm/IR/Constant.h"
80#include "llvm/IR/Constants.h"
81#include "llvm/IR/DataLayout.h"
83#include "llvm/IR/Dominators.h"
84#include "llvm/IR/Function.h"
85#include "llvm/IR/GlobalAlias.h"
86#include "llvm/IR/GlobalValue.h"
88#include "llvm/IR/IRBuilder.h"
89#include "llvm/IR/InstVisitor.h"
90#include "llvm/IR/InstrTypes.h"
91#include "llvm/IR/Instruction.h"
94#include "llvm/IR/MDBuilder.h"
95#include "llvm/IR/Module.h"
96#include "llvm/IR/PassManager.h"
97#include "llvm/IR/Type.h"
98#include "llvm/IR/User.h"
99#include "llvm/IR/Value.h"
101#include "llvm/Support/Casting.h"
110#include <algorithm>
111#include <cassert>
112#include <cstddef>
113#include <cstdint>
114#include <memory>
115#include <set>
116#include <string>
117#include <utility>
118#include <vector>
119
120using namespace llvm;
121
122// This must be consistent with ShadowWidthBits.
124
126
127// The size of TLS variables. These constants must be kept in sync with the ones
128// in dfsan.cpp.
129static const unsigned ArgTLSSize = 800;
130static const unsigned RetvalTLSSize = 800;
131
132// The -dfsan-preserve-alignment flag controls whether this pass assumes that
133// alignment requirements provided by the input IR are correct. For example,
134// if the input IR contains a load with alignment 8, this flag will cause
135// the shadow load to have alignment 16. This flag is disabled by default as
136// we have unfortunately encountered too much code (including Clang itself;
137// see PR14291) which performs misaligned access.
139 "dfsan-preserve-alignment",
140 cl::desc("respect alignment requirements provided by input IR"), cl::Hidden,
141 cl::init(false));
142
143// The ABI list files control how shadow parameters are passed. The pass treats
144// every function labelled "uninstrumented" in the ABI list file as conforming
145// to the "native" (i.e. unsanitized) ABI. Unless the ABI list contains
146// additional annotations for those functions, a call to one of those functions
147// will produce a warning message, as the labelling behaviour of the function is
148// unknown. The other supported annotations for uninstrumented functions are
149// "functional" and "discard", which are described below under
150// DataFlowSanitizer::WrapperKind.
151// Functions will often be labelled with both "uninstrumented" and one of
152// "functional" or "discard". This will leave the function unchanged by this
153// pass, and create a wrapper function that will call the original.
154//
155// Instrumented functions can also be annotated as "force_zero_labels", which
156// will make all shadow and return values set zero labels.
157// Functions should never be labelled with both "force_zero_labels" and
158// "uninstrumented" or any of the unistrumented wrapper kinds.
160 "dfsan-abilist",
161 cl::desc("File listing native ABI functions and how the pass treats them"),
162 cl::Hidden);
163
164// Controls whether the pass includes or ignores the labels of pointers in load
165// instructions.
167 "dfsan-combine-pointer-labels-on-load",
168 cl::desc("Combine the label of the pointer with the label of the data when "
169 "loading from memory."),
170 cl::Hidden, cl::init(true));
171
172// Controls whether the pass includes or ignores the labels of pointers in
173// stores instructions.
175 "dfsan-combine-pointer-labels-on-store",
176 cl::desc("Combine the label of the pointer with the label of the data when "
177 "storing in memory."),
178 cl::Hidden, cl::init(false));
179
180// Controls whether the pass propagates labels of offsets in GEP instructions.
182 "dfsan-combine-offset-labels-on-gep",
183 cl::desc(
184 "Combine the label of the offset with the label of the pointer when "
185 "doing pointer arithmetic."),
186 cl::Hidden, cl::init(true));
187
189 "dfsan-combine-taint-lookup-table",
190 cl::desc(
191 "When dfsan-combine-offset-labels-on-gep and/or "
192 "dfsan-combine-pointer-labels-on-load are false, this flag can "
193 "be used to re-enable combining offset and/or pointer taint when "
194 "loading specific constant global variables (i.e. lookup tables)."),
195 cl::Hidden);
196
198 "dfsan-debug-nonzero-labels",
199 cl::desc("Insert calls to __dfsan_nonzero_label on observing a parameter, "
200 "load or return with a nonzero label"),
201 cl::Hidden);
202
203// Experimental feature that inserts callbacks for certain data events.
204// Currently callbacks are only inserted for loads, stores, memory transfers
205// (i.e. memcpy and memmove), and comparisons.
206//
207// If this flag is set to true, the user must provide definitions for the
208// following callback functions:
209// void __dfsan_load_callback(dfsan_label Label, void* addr);
210// void __dfsan_store_callback(dfsan_label Label, void* addr);
211// void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len);
212// void __dfsan_cmp_callback(dfsan_label CombinedLabel);
214 "dfsan-event-callbacks",
215 cl::desc("Insert calls to __dfsan_*_callback functions on data events."),
216 cl::Hidden, cl::init(false));
217
218// Experimental feature that inserts callbacks for conditionals, including:
219// conditional branch, switch, select.
220// This must be true for dfsan_set_conditional_callback() to have effect.
222 "dfsan-conditional-callbacks",
223 cl::desc("Insert calls to callback functions on conditionals."), cl::Hidden,
224 cl::init(false));
225
226// Experimental feature that inserts callbacks for data reaching a function,
227// either via function arguments and loads.
228// This must be true for dfsan_set_reaches_function_callback() to have effect.
230 "dfsan-reaches-function-callbacks",
231 cl::desc("Insert calls to callback functions on data reaching a function."),
232 cl::Hidden, cl::init(false));
233
234// Controls whether the pass tracks the control flow of select instructions.
236 "dfsan-track-select-control-flow",
237 cl::desc("Propagate labels from condition values of select instructions "
238 "to results."),
239 cl::Hidden, cl::init(true));
240
241// TODO: This default value follows MSan. DFSan may use a different value.
243 "dfsan-instrument-with-call-threshold",
244 cl::desc("If the function being instrumented requires more than "
245 "this number of origin stores, use callbacks instead of "
246 "inline checks (-1 means never use callbacks)."),
247 cl::Hidden, cl::init(3500));
248
249// Controls how to track origins.
250// * 0: do not track origins.
251// * 1: track origins at memory store operations.
252// * 2: track origins at memory load and store operations.
253// TODO: track callsites.
254static cl::opt<int> ClTrackOrigins("dfsan-track-origins",
255 cl::desc("Track origins of labels"),
256 cl::Hidden, cl::init(0));
257
259 "dfsan-ignore-personality-routine",
260 cl::desc("If a personality routine is marked uninstrumented from the ABI "
261 "list, do not create a wrapper for it."),
262 cl::Hidden, cl::init(false));
263
265 "dfsan-add-global-name-suffix",
266 cl::desc("Whether to add .dfsan suffix to global names"), cl::Hidden,
267 cl::init(true));
268
270 // Types of GlobalVariables are always pointer types.
271 Type *GType = G.getValueType();
272 // For now we support excluding struct types only.
273 if (StructType *SGType = dyn_cast<StructType>(GType)) {
274 if (!SGType->isLiteral())
275 return SGType->getName();
276 }
277 return "<unknown type>";
278}
279
280namespace {
281
282// Memory map parameters used in application-to-shadow address calculation.
283// Offset = (Addr & ~AndMask) ^ XorMask
284// Shadow = ShadowBase + Offset
285// Origin = (OriginBase + Offset) & ~3ULL
286struct MemoryMapParams {
287 uint64_t AndMask;
288 uint64_t XorMask;
289 uint64_t ShadowBase;
290 uint64_t OriginBase;
291};
292
293} // end anonymous namespace
294
295// NOLINTBEGIN(readability-identifier-naming)
296// aarch64 Linux
297const MemoryMapParams Linux_AArch64_MemoryMapParams = {
298 0, // AndMask (not used)
299 0x0B00000000000, // XorMask
300 0, // ShadowBase (not used)
301 0x0200000000000, // OriginBase
302};
303
304// x86_64 Linux
305const MemoryMapParams Linux_X86_64_MemoryMapParams = {
306 0, // AndMask (not used)
307 0x500000000000, // XorMask
308 0, // ShadowBase (not used)
309 0x100000000000, // OriginBase
310};
311// NOLINTEND(readability-identifier-naming)
312
313// loongarch64 Linux
314const MemoryMapParams Linux_LoongArch64_MemoryMapParams = {
315 0, // AndMask (not used)
316 0x500000000000, // XorMask
317 0, // ShadowBase (not used)
318 0x100000000000, // OriginBase
319};
320
321// s390x Linux
322const MemoryMapParams Linux_S390X_MemoryMapParams = {
323 0xC00000000000, // AndMask
324 0, // XorMask (not used)
325 0x080000000000, // ShadowBase
326 0x1C0000000000, // OriginBase
327};
328
329namespace {
330
331class DFSanABIList {
332 std::unique_ptr<SpecialCaseList> SCL;
333
334public:
335 DFSanABIList() = default;
336
337 void set(std::unique_ptr<SpecialCaseList> List) { SCL = std::move(List); }
338
339 /// Returns whether either this function or its source file are listed in the
340 /// given category.
341 bool isIn(const Function &F, StringRef Category) const {
342 return isIn(*F.getParent(), Category) ||
343 SCL->inSection("dataflow", "fun", F.getName(), Category);
344 }
345
346 /// Returns whether this global alias is listed in the given category.
347 ///
348 /// If GA aliases a function, the alias's name is matched as a function name
349 /// would be. Similarly, aliases of globals are matched like globals.
350 bool isIn(const GlobalAlias &GA, StringRef Category) const {
351 if (isIn(*GA.getParent(), Category))
352 return true;
353
355 return SCL->inSection("dataflow", "fun", GA.getName(), Category);
356
357 return SCL->inSection("dataflow", "global", GA.getName(), Category) ||
358 SCL->inSection("dataflow", "type", getGlobalTypeString(GA),
359 Category);
360 }
361
362 /// Returns whether this module is listed in the given category.
363 bool isIn(const Module &M, StringRef Category) const {
364 return SCL->inSection("dataflow", "src", M.getModuleIdentifier(), Category);
365 }
366};
367
368/// TransformedFunction is used to express the result of transforming one
369/// function type into another. This struct is immutable. It holds metadata
370/// useful for updating calls of the old function to the new type.
371struct TransformedFunction {
372 TransformedFunction(FunctionType *OriginalType, FunctionType *TransformedType,
373 const std::vector<unsigned> &ArgumentIndexMapping,
374 AttributeList &NewParamAttrs)
375 : OriginalType(OriginalType), TransformedType(TransformedType),
376 ArgumentIndexMapping(ArgumentIndexMapping),
377 NewParamAttrs(NewParamAttrs) {}
378
379 // Disallow copies.
380 TransformedFunction(const TransformedFunction &) = delete;
381 TransformedFunction &operator=(const TransformedFunction &) = delete;
382
383 // Allow moves.
384 TransformedFunction(TransformedFunction &&) = default;
385 TransformedFunction &operator=(TransformedFunction &&) = default;
386
387 /// Type of the function before the transformation.
388 FunctionType *OriginalType;
389
390 /// Type of the function after the transformation.
391 FunctionType *TransformedType;
392
393 /// Transforming a function may change the position of arguments. This
394 /// member records the mapping from each argument's old position to its new
395 /// position. Argument positions are zero-indexed. If the transformation
396 /// from F to F' made the first argument of F into the third argument of F',
397 /// then ArgumentIndexMapping[0] will equal 2.
398 std::vector<unsigned> ArgumentIndexMapping;
399
400 /// The (extension) attributes that new Shadow and Origin parameters in
401 /// TransformedType should have.
402 AttributeList NewParamAttrs;
403};
404
405/// Given function attributes from a call site for the original function,
406/// return function attributes appropriate for a call to the transformed
407/// function.
409transformFunctionAttributes(const TransformedFunction &TransformedFunction,
410 LLVMContext &Ctx, AttributeList CallSiteAttrs) {
411
412 // Construct a vector of AttributeSet for each function argument.
413 std::vector<llvm::AttributeSet> ArgumentAttributes(
414 TransformedFunction.TransformedType->getNumParams());
415
416 // Copy attributes from the parameter of the original function to the
417 // transformed version. 'ArgumentIndexMapping' holds the mapping from
418 // old argument position to new.
419 for (unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
420 I < IE; ++I) {
421 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[I];
422 ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttrs(I);
423 }
424
425 // Copy annotations on varargs arguments.
426 for (unsigned I = TransformedFunction.OriginalType->getNumParams(),
427 IE = CallSiteAttrs.getNumAttrSets();
428 I < IE; ++I) {
429 ArgumentAttributes.push_back(CallSiteAttrs.getParamAttrs(I));
430 }
431
432 return AttributeList::get(Ctx, CallSiteAttrs.getFnAttrs(),
433 CallSiteAttrs.getRetAttrs(),
434 llvm::ArrayRef(ArgumentAttributes));
435}
436
437class DataFlowSanitizer {
438 friend struct DFSanFunction;
439 friend class DFSanVisitor;
440
441 enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
442
443 enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
444
445 /// How should calls to uninstrumented functions be handled?
446 enum WrapperKind {
447 /// This function is present in an uninstrumented form but we don't know
448 /// how it should be handled. Print a warning and call the function anyway.
449 /// Don't label the return value.
450 WK_Warning,
451
452 /// This function does not write to (user-accessible) memory, and its return
453 /// value is unlabelled.
454 WK_Discard,
455
456 /// This function does not write to (user-accessible) memory, and the label
457 /// of its return value is the union of the label of its arguments.
458 WK_Functional,
459
460 /// Instead of calling the function, a custom wrapper __dfsw_F is called,
461 /// where F is the name of the function. This function may wrap the
462 /// original function or provide its own implementation. WK_Custom uses an
463 /// extra pointer argument to return the shadow. This allows the wrapped
464 /// form of the function type to be expressed in C.
465 WK_Custom
466 };
467
468 Module *Mod;
469 LLVMContext *Ctx;
470 Type *Int8Ptr;
471 IntegerType *OriginTy;
472 PointerType *OriginPtrTy;
473 ConstantInt *ZeroOrigin;
474 /// The shadow type for all primitive types and vector types.
475 IntegerType *PrimitiveShadowTy;
476 PointerType *PrimitiveShadowPtrTy;
477 IntegerType *IntptrTy;
478 ConstantInt *ZeroPrimitiveShadow;
479 Constant *ArgTLS;
480 ArrayType *ArgOriginTLSTy;
481 Constant *ArgOriginTLS;
482 Constant *RetvalTLS;
483 Constant *RetvalOriginTLS;
484 FunctionType *DFSanUnionLoadFnTy;
485 FunctionType *DFSanLoadLabelAndOriginFnTy;
486 FunctionType *DFSanUnimplementedFnTy;
487 FunctionType *DFSanWrapperExternWeakNullFnTy;
488 FunctionType *DFSanSetLabelFnTy;
489 FunctionType *DFSanNonzeroLabelFnTy;
490 FunctionType *DFSanVarargWrapperFnTy;
491 FunctionType *DFSanConditionalCallbackFnTy;
492 FunctionType *DFSanConditionalCallbackOriginFnTy;
493 FunctionType *DFSanReachesFunctionCallbackFnTy;
494 FunctionType *DFSanReachesFunctionCallbackOriginFnTy;
495 FunctionType *DFSanCmpCallbackFnTy;
496 FunctionType *DFSanLoadStoreCallbackFnTy;
497 FunctionType *DFSanMemTransferCallbackFnTy;
498 FunctionType *DFSanChainOriginFnTy;
499 FunctionType *DFSanChainOriginIfTaintedFnTy;
500 FunctionType *DFSanMemOriginTransferFnTy;
501 FunctionType *DFSanMemShadowOriginTransferFnTy;
502 FunctionType *DFSanMemShadowOriginConditionalExchangeFnTy;
503 FunctionType *DFSanMaybeStoreOriginFnTy;
504 FunctionCallee DFSanUnionLoadFn;
505 FunctionCallee DFSanLoadLabelAndOriginFn;
506 FunctionCallee DFSanUnimplementedFn;
507 FunctionCallee DFSanWrapperExternWeakNullFn;
508 FunctionCallee DFSanSetLabelFn;
509 FunctionCallee DFSanNonzeroLabelFn;
510 FunctionCallee DFSanVarargWrapperFn;
511 FunctionCallee DFSanLoadCallbackFn;
512 FunctionCallee DFSanStoreCallbackFn;
513 FunctionCallee DFSanMemTransferCallbackFn;
514 FunctionCallee DFSanConditionalCallbackFn;
515 FunctionCallee DFSanConditionalCallbackOriginFn;
516 FunctionCallee DFSanReachesFunctionCallbackFn;
517 FunctionCallee DFSanReachesFunctionCallbackOriginFn;
518 FunctionCallee DFSanCmpCallbackFn;
519 FunctionCallee DFSanChainOriginFn;
520 FunctionCallee DFSanChainOriginIfTaintedFn;
521 FunctionCallee DFSanMemOriginTransferFn;
522 FunctionCallee DFSanMemShadowOriginTransferFn;
523 FunctionCallee DFSanMemShadowOriginConditionalExchangeFn;
524 FunctionCallee DFSanMaybeStoreOriginFn;
525 SmallPtrSet<Value *, 16> DFSanRuntimeFunctions;
526 MDNode *ColdCallWeights;
527 MDNode *OriginStoreWeights;
528 DFSanABIList ABIList;
529 DenseMap<Value *, Function *> UnwrappedFnMap;
530 AttributeMask ReadOnlyNoneAttrs;
531 StringSet<> CombineTaintLookupTableNames;
532
533 /// Memory map parameters used in calculation mapping application addresses
534 /// to shadow addresses and origin addresses.
535 const MemoryMapParams *MapParams;
536
537 Value *getShadowOffset(Value *Addr, IRBuilder<> &IRB);
538 Value *getShadowAddress(Value *Addr, BasicBlock::iterator Pos);
539 Value *getShadowAddress(Value *Addr, BasicBlock::iterator Pos,
540 Value *ShadowOffset);
541 std::pair<Value *, Value *> getShadowOriginAddress(Value *Addr,
542 Align InstAlignment,
544 bool isInstrumented(const Function *F);
545 bool isInstrumented(const GlobalAlias *GA);
546 bool isForceZeroLabels(const Function *F);
547 TransformedFunction getCustomFunctionType(FunctionType *T,
548 TargetLibraryInfo &TLI);
549 WrapperKind getWrapperKind(Function *F);
550 void addGlobalNameSuffix(GlobalValue *GV);
551 void buildExternWeakCheckIfNeeded(IRBuilder<> &IRB, Function *F);
552 Function *buildWrapperFunction(Function *F, StringRef NewFName,
554 FunctionType *NewFT);
555 void initializeCallbackFunctions(Module &M);
556 void initializeRuntimeFunctions(Module &M);
557 bool initializeModule(Module &M);
558
559 /// Advances \p OriginAddr to point to the next 32-bit origin and then loads
560 /// from it. Returns the origin's loaded value.
561 Value *loadNextOrigin(BasicBlock::iterator Pos, Align OriginAlign,
562 Value **OriginAddr);
563
564 /// Returns whether the given load byte size is amenable to inlined
565 /// optimization patterns.
566 bool hasLoadSizeForFastPath(uint64_t Size);
567
568 /// Returns whether the pass tracks origins. Supports only TLS ABI mode.
569 bool shouldTrackOrigins();
570
571 /// Returns a zero constant with the shadow type of OrigTy.
572 ///
573 /// getZeroShadow({T1,T2,...}) = {getZeroShadow(T1),getZeroShadow(T2,...}
574 /// getZeroShadow([n x T]) = [n x getZeroShadow(T)]
575 /// getZeroShadow(other type) = i16(0)
576 Constant *getZeroShadow(Type *OrigTy);
577 /// Returns a zero constant with the shadow type of V's type.
578 Constant *getZeroShadow(Value *V);
579
580 /// Checks if V is a zero shadow.
581 bool isZeroShadow(Value *V);
582
583 /// Returns the shadow type of OrigTy.
584 ///
585 /// getShadowTy({T1,T2,...}) = {getShadowTy(T1),getShadowTy(T2),...}
586 /// getShadowTy([n x T]) = [n x getShadowTy(T)]
587 /// getShadowTy(other type) = i16
588 Type *getShadowTy(Type *OrigTy);
589 /// Returns the shadow type of V's type.
590 Type *getShadowTy(Value *V);
591
592 const uint64_t NumOfElementsInArgOrgTLS = ArgTLSSize / OriginWidthBytes;
593
594public:
595 DataFlowSanitizer(const std::vector<std::string> &ABIListFiles,
596 IntrusiveRefCntPtr<vfs::FileSystem> FS);
597
598 bool runImpl(Module &M,
599 llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI);
600};
601
602struct DFSanFunction {
603 DataFlowSanitizer &DFS;
604 Function *F;
605 DominatorTree DT;
606 bool IsNativeABI;
607 bool IsForceZeroLabels;
608 TargetLibraryInfo &TLI;
609 AllocaInst *LabelReturnAlloca = nullptr;
610 AllocaInst *OriginReturnAlloca = nullptr;
611 DenseMap<Value *, Value *> ValShadowMap;
612 DenseMap<Value *, Value *> ValOriginMap;
613 DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
614 DenseMap<AllocaInst *, AllocaInst *> AllocaOriginMap;
615
616 struct PHIFixupElement {
617 PHINode *Phi;
618 PHINode *ShadowPhi;
619 PHINode *OriginPhi;
620 };
621 std::vector<PHIFixupElement> PHIFixups;
622
623 DenseSet<Instruction *> SkipInsts;
624 std::vector<Value *> NonZeroChecks;
625
626 struct CachedShadow {
627 BasicBlock *Block; // The block where Shadow is defined.
628 Value *Shadow;
629 };
630 /// Maps a value to its latest shadow value in terms of domination tree.
631 DenseMap<std::pair<Value *, Value *>, CachedShadow> CachedShadows;
632 /// Maps a value to its latest collapsed shadow value it was converted to in
633 /// terms of domination tree. When ClDebugNonzeroLabels is on, this cache is
634 /// used at a post process where CFG blocks are split. So it does not cache
635 /// BasicBlock like CachedShadows, but uses domination between values.
636 DenseMap<Value *, Value *> CachedCollapsedShadows;
637 DenseMap<Value *, std::set<Value *>> ShadowElements;
638
639 DFSanFunction(DataFlowSanitizer &DFS, Function *F, bool IsNativeABI,
640 bool IsForceZeroLabels, TargetLibraryInfo &TLI)
641 : DFS(DFS), F(F), IsNativeABI(IsNativeABI),
642 IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
643 DT.recalculate(*F);
644 }
645
646 /// Computes the shadow address for a given function argument.
647 ///
648 /// Shadow = ArgTLS+ArgOffset.
649 Value *getArgTLS(Type *T, unsigned ArgOffset, IRBuilder<> &IRB);
650
651 /// Computes the shadow address for a return value.
652 Value *getRetvalTLS(Type *T, IRBuilder<> &IRB);
653
654 /// Computes the origin address for a given function argument.
655 ///
656 /// Origin = ArgOriginTLS[ArgNo].
657 Value *getArgOriginTLS(unsigned ArgNo, IRBuilder<> &IRB);
658
659 /// Computes the origin address for a return value.
660 Value *getRetvalOriginTLS();
661
662 Value *getOrigin(Value *V);
663 void setOrigin(Instruction *I, Value *Origin);
664 /// Generates IR to compute the origin of the last operand with a taint label.
665 Value *combineOperandOrigins(Instruction *Inst);
666 /// Before the instruction Pos, generates IR to compute the last origin with a
667 /// taint label. Labels and origins are from vectors Shadows and Origins
668 /// correspondingly. The generated IR is like
669 /// Sn-1 != Zero ? On-1: ... S2 != Zero ? O2: S1 != Zero ? O1: O0
670 /// When Zero is nullptr, it uses ZeroPrimitiveShadow. Otherwise it can be
671 /// zeros with other bitwidths.
672 Value *combineOrigins(const std::vector<Value *> &Shadows,
673 const std::vector<Value *> &Origins,
674 BasicBlock::iterator Pos, ConstantInt *Zero = nullptr);
675
676 Value *getShadow(Value *V);
677 void setShadow(Instruction *I, Value *Shadow);
678 /// Generates IR to compute the union of the two given shadows, inserting it
679 /// before Pos. The combined value is with primitive type.
680 Value *combineShadows(Value *V1, Value *V2, BasicBlock::iterator Pos);
681 /// Combines the shadow values of V1 and V2, then converts the combined value
682 /// with primitive type into a shadow value with the original type T.
683 Value *combineShadowsThenConvert(Type *T, Value *V1, Value *V2,
685 Value *combineOperandShadows(Instruction *Inst);
686
687 /// Generates IR to load shadow and origin corresponding to bytes [\p
688 /// Addr, \p Addr + \p Size), where addr has alignment \p
689 /// InstAlignment, and take the union of each of those shadows. The returned
690 /// shadow always has primitive type.
691 ///
692 /// When tracking loads is enabled, the returned origin is a chain at the
693 /// current stack if the returned shadow is tainted.
694 std::pair<Value *, Value *> loadShadowOrigin(Value *Addr, uint64_t Size,
695 Align InstAlignment,
697
698 void storePrimitiveShadowOrigin(Value *Addr, uint64_t Size,
699 Align InstAlignment, Value *PrimitiveShadow,
700 Value *Origin, BasicBlock::iterator Pos);
701 /// Applies PrimitiveShadow to all primitive subtypes of T, returning
702 /// the expanded shadow value.
703 ///
704 /// EFP({T1,T2, ...}, PS) = {EFP(T1,PS),EFP(T2,PS),...}
705 /// EFP([n x T], PS) = [n x EFP(T,PS)]
706 /// EFP(other types, PS) = PS
707 Value *expandFromPrimitiveShadow(Type *T, Value *PrimitiveShadow,
709 /// Collapses Shadow into a single primitive shadow value, unioning all
710 /// primitive shadow values in the process. Returns the final primitive
711 /// shadow value.
712 ///
713 /// CTP({V1,V2, ...}) = UNION(CFP(V1,PS),CFP(V2,PS),...)
714 /// CTP([V1,V2,...]) = UNION(CFP(V1,PS),CFP(V2,PS),...)
715 /// CTP(other types, PS) = PS
716 Value *collapseToPrimitiveShadow(Value *Shadow, BasicBlock::iterator Pos);
717
718 void storeZeroPrimitiveShadow(Value *Addr, uint64_t Size, Align ShadowAlign,
720
721 Align getShadowAlign(Align InstAlignment);
722
723 // If ClConditionalCallbacks is enabled, insert a callback after a given
724 // branch instruction using the given conditional expression.
725 void addConditionalCallbacksIfEnabled(Instruction &I, Value *Condition);
726
727 // If ClReachesFunctionCallbacks is enabled, insert a callback for each
728 // argument and load instruction.
729 void addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB, Instruction &I,
730 Value *Data);
731
732 bool isLookupTableConstant(Value *P);
733
734private:
735 /// Collapses the shadow with aggregate type into a single primitive shadow
736 /// value.
737 template <class AggregateType>
738 Value *collapseAggregateShadow(AggregateType *AT, Value *Shadow,
739 IRBuilder<> &IRB);
740
741 Value *collapseToPrimitiveShadow(Value *Shadow, IRBuilder<> &IRB);
742
743 /// Returns the shadow value of an argument A.
744 Value *getShadowForTLSArgument(Argument *A);
745
746 /// The fast path of loading shadows.
747 std::pair<Value *, Value *>
748 loadShadowFast(Value *ShadowAddr, Value *OriginAddr, uint64_t Size,
749 Align ShadowAlign, Align OriginAlign, Value *FirstOrigin,
751
752 Align getOriginAlign(Align InstAlignment);
753
754 /// Because 4 contiguous bytes share one 4-byte origin, the most accurate load
755 /// is __dfsan_load_label_and_origin. This function returns the union of all
756 /// labels and the origin of the first taint label. However this is an
757 /// additional call with many instructions. To ensure common cases are fast,
758 /// checks if it is possible to load labels and origins without using the
759 /// callback function.
760 ///
761 /// When enabling tracking load instructions, we always use
762 /// __dfsan_load_label_and_origin to reduce code size.
763 bool useCallbackLoadLabelAndOrigin(uint64_t Size, Align InstAlignment);
764
765 /// Returns a chain at the current stack with previous origin V.
766 Value *updateOrigin(Value *V, IRBuilder<> &IRB);
767
768 /// Returns a chain at the current stack with previous origin V if Shadow is
769 /// tainted.
770 Value *updateOriginIfTainted(Value *Shadow, Value *Origin, IRBuilder<> &IRB);
771
772 /// Creates an Intptr = Origin | Origin << 32 if Intptr's size is 64. Returns
773 /// Origin otherwise.
774 Value *originToIntptr(IRBuilder<> &IRB, Value *Origin);
775
776 /// Stores Origin into the address range [StoreOriginAddr, StoreOriginAddr +
777 /// Size).
778 void paintOrigin(IRBuilder<> &IRB, Value *Origin, Value *StoreOriginAddr,
779 uint64_t StoreOriginSize, Align Alignment);
780
781 /// Stores Origin in terms of its Shadow value.
782 /// * Do not write origins for zero shadows because we do not trace origins
783 /// for untainted sinks.
784 /// * Use __dfsan_maybe_store_origin if there are too many origin store
785 /// instrumentations.
786 void storeOrigin(BasicBlock::iterator Pos, Value *Addr, uint64_t Size,
787 Value *Shadow, Value *Origin, Value *StoreOriginAddr,
788 Align InstAlignment);
789
790 /// Convert a scalar value to an i1 by comparing with 0.
791 Value *convertToBool(Value *V, IRBuilder<> &IRB, const Twine &Name = "");
792
793 bool shouldInstrumentWithCall();
794
795 /// Generates IR to load shadow and origin corresponding to bytes [\p
796 /// Addr, \p Addr + \p Size), where addr has alignment \p
797 /// InstAlignment, and take the union of each of those shadows. The returned
798 /// shadow always has primitive type.
799 std::pair<Value *, Value *>
800 loadShadowOriginSansLoadTracking(Value *Addr, uint64_t Size,
801 Align InstAlignment,
803 int NumOriginStores = 0;
804};
805
806class DFSanVisitor : public InstVisitor<DFSanVisitor> {
807public:
808 DFSanFunction &DFSF;
809
810 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
811
812 const DataLayout &getDataLayout() const {
813 return DFSF.F->getDataLayout();
814 }
815
816 // Combines shadow values and origins for all of I's operands.
817 void visitInstOperands(Instruction &I);
818
819 void visitUnaryOperator(UnaryOperator &UO);
820 void visitBinaryOperator(BinaryOperator &BO);
821 void visitBitCastInst(BitCastInst &BCI);
822 void visitCastInst(CastInst &CI);
823 void visitCmpInst(CmpInst &CI);
824 void visitLandingPadInst(LandingPadInst &LPI);
825 void visitGetElementPtrInst(GetElementPtrInst &GEPI);
826 void visitLoadInst(LoadInst &LI);
827 void visitStoreInst(StoreInst &SI);
828 void visitAtomicRMWInst(AtomicRMWInst &I);
829 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);
830 void visitReturnInst(ReturnInst &RI);
831 void visitLibAtomicLoad(CallBase &CB);
832 void visitLibAtomicStore(CallBase &CB);
833 void visitLibAtomicExchange(CallBase &CB);
834 void visitLibAtomicCompareExchange(CallBase &CB);
835 void visitCallBase(CallBase &CB);
836 void visitPHINode(PHINode &PN);
837 void visitExtractElementInst(ExtractElementInst &I);
838 void visitInsertElementInst(InsertElementInst &I);
839 void visitShuffleVectorInst(ShuffleVectorInst &I);
840 void visitExtractValueInst(ExtractValueInst &I);
841 void visitInsertValueInst(InsertValueInst &I);
842 void visitAllocaInst(AllocaInst &I);
843 void visitSelectInst(SelectInst &I);
844 void visitMemSetInst(MemSetInst &I);
845 void visitMemTransferInst(MemTransferInst &I);
846 void visitCondBrInst(CondBrInst &BR);
847 void visitSwitchInst(SwitchInst &SW);
848
849private:
850 void visitCASOrRMW(Align InstAlignment, Instruction &I);
851
852 // Returns false when this is an invoke of a custom function.
853 bool visitWrappedCallBase(Function &F, CallBase &CB);
854
855 // Combines origins for all of I's operands.
856 void visitInstOperandOrigins(Instruction &I);
857
858 void addShadowArguments(Function &F, CallBase &CB, std::vector<Value *> &Args,
859 IRBuilder<> &IRB);
860
861 void addOriginArguments(Function &F, CallBase &CB, std::vector<Value *> &Args,
862 IRBuilder<> &IRB);
863
864 Value *makeAddAcquireOrderingTable(IRBuilder<> &IRB);
865 Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB);
866};
867
868bool LibAtomicFunction(const Function &F) {
869 // This is a bit of a hack because TargetLibraryInfo is a function pass.
870 // The DFSan pass would need to be refactored to be function pass oriented
871 // (like MSan is) in order to fit together nicely with TargetLibraryInfo.
872 // We need this check to prevent them from being instrumented, or wrapped.
873 // Match on name and number of arguments.
874 if (!F.hasName() || F.isVarArg())
875 return false;
876 switch (F.arg_size()) {
877 case 4:
878 return F.getName() == "__atomic_load" || F.getName() == "__atomic_store";
879 case 5:
880 return F.getName() == "__atomic_exchange";
881 case 6:
882 return F.getName() == "__atomic_compare_exchange";
883 default:
884 return false;
885 }
886}
887
888} // end anonymous namespace
889
890DataFlowSanitizer::DataFlowSanitizer(
891 const std::vector<std::string> &ABIListFiles,
893 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
894 llvm::append_range(AllABIListFiles, ClABIListFiles);
895 ABIList.set(SpecialCaseList::createOrDie(AllABIListFiles, *FS));
896
897 CombineTaintLookupTableNames.insert_range(ClCombineTaintLookupTables);
898}
899
900TransformedFunction
901DataFlowSanitizer::getCustomFunctionType(FunctionType *T,
902 TargetLibraryInfo &TLI) {
903 SmallVector<Type *, 4> ArgTypes;
904 AttributeList NewParamAttrs;
905 Attribute::AttrKind ShadowParamExtAttr =
906 TLI.getExtAttrForI8Param(/*Signed=*/false);
907 Attribute::AttrKind OriginParamExtAttr =
908 TLI.getExtAttrForI32Param(/*Signed=*/false);
909
910 // Some parameters of the custom function being constructed are
911 // parameters of T. Record the mapping from parameters of T to
912 // parameters of the custom function, so that parameter attributes
913 // at call sites can be updated.
914 std::vector<unsigned> ArgumentIndexMapping;
915 for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
916 Type *ParamType = T->getParamType(I);
917 ArgumentIndexMapping.push_back(ArgTypes.size());
918 ArgTypes.push_back(ParamType);
919 }
920 for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
921 NewParamAttrs = NewParamAttrs.maybeAddParamAttribute(*Ctx, ArgTypes.size(),
922 ShadowParamExtAttr);
923 ArgTypes.push_back(PrimitiveShadowTy);
924 }
925 if (T->isVarArg())
926 ArgTypes.push_back(PrimitiveShadowPtrTy);
927 Type *RetType = T->getReturnType();
928 if (!RetType->isVoidTy())
929 ArgTypes.push_back(PrimitiveShadowPtrTy);
930
931 if (shouldTrackOrigins()) {
932 for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
933 NewParamAttrs = NewParamAttrs.maybeAddParamAttribute(
934 *Ctx, ArgTypes.size(), OriginParamExtAttr);
935 ArgTypes.push_back(OriginTy);
936 }
937 if (T->isVarArg())
938 ArgTypes.push_back(OriginPtrTy);
939 if (!RetType->isVoidTy())
940 ArgTypes.push_back(OriginPtrTy);
941 }
942
943 return TransformedFunction(
944 T, FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()),
945 ArgumentIndexMapping, NewParamAttrs);
946}
947
948bool DataFlowSanitizer::isZeroShadow(Value *V) {
949 Type *T = V->getType();
950 if (!isa<ArrayType>(T) && !isa<StructType>(T)) {
951 if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
952 return CI->isZero();
953 return false;
954 }
955
957}
958
959bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t Size) {
960 uint64_t ShadowSize = Size * ShadowWidthBytes;
961 return ShadowSize % 8 == 0 || ShadowSize == 4;
962}
963
964bool DataFlowSanitizer::shouldTrackOrigins() {
965 static const bool ShouldTrackOrigins = ClTrackOrigins;
966 return ShouldTrackOrigins;
967}
968
969Constant *DataFlowSanitizer::getZeroShadow(Type *OrigTy) {
970 if (!isa<ArrayType>(OrigTy) && !isa<StructType>(OrigTy))
971 return ZeroPrimitiveShadow;
972 Type *ShadowTy = getShadowTy(OrigTy);
973 return ConstantAggregateZero::get(ShadowTy);
974}
975
976Constant *DataFlowSanitizer::getZeroShadow(Value *V) {
977 return getZeroShadow(V->getType());
978}
979
981 Value *Shadow, SmallVector<unsigned, 4> &Indices, Type *SubShadowTy,
982 Value *PrimitiveShadow, IRBuilder<> &IRB) {
983 if (!isa<ArrayType>(SubShadowTy) && !isa<StructType>(SubShadowTy))
984 return IRB.CreateInsertValue(Shadow, PrimitiveShadow, Indices);
985
986 if (ArrayType *AT = dyn_cast<ArrayType>(SubShadowTy)) {
987 for (unsigned Idx = 0; Idx < AT->getNumElements(); Idx++) {
988 Indices.push_back(Idx);
990 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
991 Indices.pop_back();
992 }
993 return Shadow;
994 }
995
996 if (StructType *ST = dyn_cast<StructType>(SubShadowTy)) {
997 for (unsigned Idx = 0; Idx < ST->getNumElements(); Idx++) {
998 Indices.push_back(Idx);
1000 Shadow, Indices, ST->getElementType(Idx), PrimitiveShadow, IRB);
1001 Indices.pop_back();
1002 }
1003 return Shadow;
1004 }
1005 llvm_unreachable("Unexpected shadow type");
1006}
1007
1008bool DFSanFunction::shouldInstrumentWithCall() {
1009 return ClInstrumentWithCallThreshold >= 0 &&
1010 NumOriginStores >= ClInstrumentWithCallThreshold;
1011}
1012
1013Value *DFSanFunction::expandFromPrimitiveShadow(Type *T, Value *PrimitiveShadow,
1015 Type *ShadowTy = DFS.getShadowTy(T);
1016
1017 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1018 return PrimitiveShadow;
1019
1020 if (DFS.isZeroShadow(PrimitiveShadow))
1021 return DFS.getZeroShadow(ShadowTy);
1022
1023 IRBuilder<> IRB(Pos->getParent(), Pos);
1024 SmallVector<unsigned, 4> Indices;
1025 Value *Shadow = UndefValue::get(ShadowTy);
1026 Shadow = expandFromPrimitiveShadowRecursive(Shadow, Indices, ShadowTy,
1027 PrimitiveShadow, IRB);
1028
1029 // Caches the primitive shadow value that built the shadow value.
1030 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
1031 return Shadow;
1032}
1033
1034template <class AggregateType>
1035Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT, Value *Shadow,
1036 IRBuilder<> &IRB) {
1037 if (!AT->getNumElements())
1038 return DFS.ZeroPrimitiveShadow;
1039
1040 Value *FirstItem = IRB.CreateExtractValue(Shadow, 0);
1041 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1042
1043 for (unsigned Idx = 1; Idx < AT->getNumElements(); Idx++) {
1044 Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx);
1045 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1046 Aggregator = IRB.CreateOr(Aggregator, ShadowInner);
1047 }
1048 return Aggregator;
1049}
1050
1051Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
1052 IRBuilder<> &IRB) {
1053 Type *ShadowTy = Shadow->getType();
1054 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1055 return Shadow;
1056 if (ArrayType *AT = dyn_cast<ArrayType>(ShadowTy))
1057 return collapseAggregateShadow<>(AT, Shadow, IRB);
1058 if (StructType *ST = dyn_cast<StructType>(ShadowTy))
1059 return collapseAggregateShadow<>(ST, Shadow, IRB);
1060 llvm_unreachable("Unexpected shadow type");
1061}
1062
1063Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
1065 Type *ShadowTy = Shadow->getType();
1066 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1067 return Shadow;
1068
1069 // Checks if the cached collapsed shadow value dominates Pos.
1070 Value *&CS = CachedCollapsedShadows[Shadow];
1071 if (CS && DT.dominates(CS, Pos))
1072 return CS;
1073
1074 IRBuilder<> IRB(Pos->getParent(), Pos);
1075 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1076 // Caches the converted primitive shadow value.
1077 CS = PrimitiveShadow;
1078 return PrimitiveShadow;
1079}
1080
1081void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &I,
1082 Value *Condition) {
1084 return;
1085 }
1086 IRBuilder<> IRB(&I);
1087 Value *CondShadow = getShadow(Condition);
1088 CallInst *CI;
1089 if (DFS.shouldTrackOrigins()) {
1090 Value *CondOrigin = getOrigin(Condition);
1091 CI = IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1092 {CondShadow, CondOrigin});
1093 CI->maybeAddParamAttr(1, TLI.getExtAttrForI32Param(/*Signed=*/false));
1094 } else {
1095 CI = IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1096 }
1097 CI->maybeAddParamAttr(0, TLI.getExtAttrForI8Param(/*Signed=*/false));
1098}
1099
1100void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB,
1101 Instruction &I,
1102 Value *Data) {
1104 return;
1105 }
1106 const DebugLoc &dbgloc = I.getDebugLoc();
1107 Value *DataShadow = collapseToPrimitiveShadow(getShadow(Data), IRB);
1108 ConstantInt *CILine;
1109 llvm::Value *FilePathPtr;
1110
1111 if (dbgloc.get() == nullptr) {
1112 CILine = llvm::ConstantInt::get(I.getContext(), llvm::APInt(32, 0));
1113 FilePathPtr = IRB.CreateGlobalString(
1114 I.getFunction()->getParent()->getSourceFileName());
1115 } else {
1116 CILine = llvm::ConstantInt::get(I.getContext(),
1117 llvm::APInt(32, dbgloc.getLine()));
1118 FilePathPtr = IRB.CreateGlobalString(dbgloc->getFilename());
1119 }
1120
1121 llvm::Value *FunctionNamePtr =
1122 IRB.CreateGlobalString(I.getFunction()->getName());
1123
1124 CallInst *CB;
1125 std::vector<Value *> args;
1126
1127 Attribute::AttrKind I32ParamExtAttr =
1128 TLI.getExtAttrForI32Param(/*Signed=*/false);
1129 if (DFS.shouldTrackOrigins()) {
1130 Value *DataOrigin = getOrigin(Data);
1131 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1132 CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn, args);
1133 CB->maybeAddParamAttr(1, I32ParamExtAttr);
1134 CB->maybeAddParamAttr(3, I32ParamExtAttr);
1135 } else {
1136 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1137 CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackFn, args);
1138 CB->maybeAddParamAttr(2, I32ParamExtAttr);
1139 }
1140 CB->maybeAddParamAttr(0, TLI.getExtAttrForI8Param(/*Signed=*/false));
1141 CB->setDebugLoc(dbgloc);
1142}
1143
1144Type *DataFlowSanitizer::getShadowTy(Type *OrigTy) {
1145 if (!OrigTy->isSized())
1146 return PrimitiveShadowTy;
1147 if (isa<IntegerType>(OrigTy))
1148 return PrimitiveShadowTy;
1149 if (isa<VectorType>(OrigTy))
1150 return PrimitiveShadowTy;
1151 if (ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1152 return ArrayType::get(getShadowTy(AT->getElementType()),
1153 AT->getNumElements());
1154 if (StructType *ST = dyn_cast<StructType>(OrigTy)) {
1156 for (unsigned I = 0, N = ST->getNumElements(); I < N; ++I)
1157 Elements.push_back(getShadowTy(ST->getElementType(I)));
1158 return StructType::get(*Ctx, Elements);
1159 }
1160 return PrimitiveShadowTy;
1161}
1162
1163Type *DataFlowSanitizer::getShadowTy(Value *V) {
1164 return getShadowTy(V->getType());
1165}
1166
1167bool DataFlowSanitizer::initializeModule(Module &M) {
1168 Triple TargetTriple(M.getTargetTriple());
1169 const DataLayout &DL = M.getDataLayout();
1170
1171 if (TargetTriple.getOS() != Triple::Linux)
1172 report_fatal_error("unsupported operating system");
1173 switch (TargetTriple.getArch()) {
1174 case Triple::aarch64:
1175 MapParams = &Linux_AArch64_MemoryMapParams;
1176 break;
1177 case Triple::x86_64:
1178 MapParams = &Linux_X86_64_MemoryMapParams;
1179 break;
1182 break;
1183 case Triple::systemz:
1184 MapParams = &Linux_S390X_MemoryMapParams;
1185 break;
1186 default:
1187 report_fatal_error("unsupported architecture");
1188 }
1189
1190 Mod = &M;
1191 Ctx = &M.getContext();
1192 Int8Ptr = PointerType::getUnqual(*Ctx);
1193 OriginTy = IntegerType::get(*Ctx, OriginWidthBits);
1194 OriginPtrTy = PointerType::getUnqual(*Ctx);
1195 PrimitiveShadowTy = IntegerType::get(*Ctx, ShadowWidthBits);
1196 PrimitiveShadowPtrTy = PointerType::getUnqual(*Ctx);
1197 IntptrTy = DL.getIntPtrType(*Ctx);
1198 ZeroPrimitiveShadow = ConstantInt::getSigned(PrimitiveShadowTy, 0);
1199 ZeroOrigin = ConstantInt::getSigned(OriginTy, 0);
1200
1201 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1202 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1203 /*isVarArg=*/false);
1204 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1205 DFSanLoadLabelAndOriginFnTy =
1206 FunctionType::get(IntegerType::get(*Ctx, 64), DFSanLoadLabelAndOriginArgs,
1207 /*isVarArg=*/false);
1208 DFSanUnimplementedFnTy = FunctionType::get(
1209 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx), /*isVarArg=*/false);
1210 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1211 DFSanWrapperExternWeakNullFnTy =
1212 FunctionType::get(Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1213 /*isVarArg=*/false);
1214 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1215 PointerType::getUnqual(*Ctx), IntptrTy};
1216 DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
1217 DFSanSetLabelArgs, /*isVarArg=*/false);
1218 DFSanNonzeroLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx), {},
1219 /*isVarArg=*/false);
1220 DFSanVarargWrapperFnTy = FunctionType::get(
1221 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx), /*isVarArg=*/false);
1222 DFSanConditionalCallbackFnTy =
1223 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1224 /*isVarArg=*/false);
1225 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1226 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1227 Type::getVoidTy(*Ctx), DFSanConditionalCallbackOriginArgs,
1228 /*isVarArg=*/false);
1229 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1230 OriginTy, Int8Ptr};
1231 DFSanReachesFunctionCallbackFnTy =
1232 FunctionType::get(Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1233 /*isVarArg=*/false);
1234 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1235 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1236 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1237 Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackOriginArgs,
1238 /*isVarArg=*/false);
1239 DFSanCmpCallbackFnTy =
1240 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1241 /*isVarArg=*/false);
1242 DFSanChainOriginFnTy =
1243 FunctionType::get(OriginTy, OriginTy, /*isVarArg=*/false);
1244 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1245 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1246 OriginTy, DFSanChainOriginIfTaintedArgs, /*isVarArg=*/false);
1247 Type *DFSanMaybeStoreOriginArgs[4] = {IntegerType::get(*Ctx, ShadowWidthBits),
1248 Int8Ptr, IntptrTy, OriginTy};
1249 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1250 Type::getVoidTy(*Ctx), DFSanMaybeStoreOriginArgs, /*isVarArg=*/false);
1251 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1252 DFSanMemOriginTransferFnTy = FunctionType::get(
1253 Type::getVoidTy(*Ctx), DFSanMemOriginTransferArgs, /*isVarArg=*/false);
1254 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1255 DFSanMemShadowOriginTransferFnTy =
1256 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1257 /*isVarArg=*/false);
1258 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1259 IntegerType::get(*Ctx, 8), Int8Ptr, Int8Ptr, Int8Ptr, IntptrTy};
1260 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1261 Type::getVoidTy(*Ctx), DFSanMemShadowOriginConditionalExchangeArgs,
1262 /*isVarArg=*/false);
1263 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1264 DFSanLoadStoreCallbackFnTy =
1265 FunctionType::get(Type::getVoidTy(*Ctx), DFSanLoadStoreCallbackArgs,
1266 /*isVarArg=*/false);
1267 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1268 DFSanMemTransferCallbackFnTy =
1269 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1270 /*isVarArg=*/false);
1271
1272 ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1273 OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1274 return true;
1275}
1276
1277bool DataFlowSanitizer::isInstrumented(const Function *F) {
1278 return !ABIList.isIn(*F, "uninstrumented");
1279}
1280
1281bool DataFlowSanitizer::isInstrumented(const GlobalAlias *GA) {
1282 return !ABIList.isIn(*GA, "uninstrumented");
1283}
1284
1285bool DataFlowSanitizer::isForceZeroLabels(const Function *F) {
1286 return ABIList.isIn(*F, "force_zero_labels");
1287}
1288
1289DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(Function *F) {
1290 if (ABIList.isIn(*F, "functional"))
1291 return WK_Functional;
1292 if (ABIList.isIn(*F, "discard"))
1293 return WK_Discard;
1294 if (ABIList.isIn(*F, "custom"))
1295 return WK_Custom;
1296
1297 return WK_Warning;
1298}
1299
1300void DataFlowSanitizer::addGlobalNameSuffix(GlobalValue *GV) {
1302 return;
1303
1304 std::string GVName = std::string(GV->getName()), Suffix = ".dfsan";
1305 GV->setName(GVName + Suffix);
1306
1307 // Try to change the name of the function in module inline asm. We only do
1308 // this for specific asm directives, currently only ".symver", to try to avoid
1309 // corrupting asm which happens to contain the symbol name as a substring.
1310 // Note that the substitution for .symver assumes that the versioned symbol
1311 // also has an instrumented name.
1312 for (Module::GlobalAsmFragment &Frag :
1313 GV->getParent()->getModuleInlineAsm()) {
1314 std::string SearchStr = ".symver " + GVName + ",";
1315 size_t Pos = Frag.Asm.find(SearchStr);
1316 if (Pos != std::string::npos) {
1317 Frag.Asm.replace(Pos, SearchStr.size(),
1318 ".symver " + GVName + Suffix + ",");
1319 Pos = Frag.Asm.find('@');
1320
1321 if (Pos == std::string::npos)
1322 report_fatal_error(Twine("unsupported .symver: ", Frag.Asm));
1323
1324 Frag.Asm.replace(Pos, 1, Suffix + "@");
1325 }
1326 }
1327}
1328
1329void DataFlowSanitizer::buildExternWeakCheckIfNeeded(IRBuilder<> &IRB,
1330 Function *F) {
1331 // If the function we are wrapping was ExternWeak, it may be null.
1332 // The original code before calling this wrapper may have checked for null,
1333 // but replacing with a known-to-not-be-null wrapper can break this check.
1334 // When replacing uses of the extern weak function with the wrapper we try
1335 // to avoid replacing uses in conditionals, but this is not perfect.
1336 // In the case where we fail, and accidentally optimize out a null check
1337 // for a extern weak function, add a check here to help identify the issue.
1338 if (GlobalValue::isExternalWeakLinkage(F->getLinkage())) {
1339 std::vector<Value *> Args;
1340 Args.push_back(F);
1341 Args.push_back(IRB.CreateGlobalString(F->getName()));
1342 IRB.CreateCall(DFSanWrapperExternWeakNullFn, Args);
1343 }
1344}
1345
1346Function *
1347DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName,
1349 FunctionType *NewFT) {
1350 FunctionType *FT = F->getFunctionType();
1351 Function *NewF = Function::Create(NewFT, NewFLink, F->getAddressSpace(),
1352 NewFName, F->getParent());
1353 NewF->copyAttributesFrom(F);
1354 NewF->removeRetAttrs(AttributeFuncs::typeIncompatible(
1355 NewFT->getReturnType(), NewF->getAttributes().getRetAttrs()));
1356
1357 BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", NewF);
1358 if (F->isVarArg()) {
1359 NewF->removeFnAttr("split-stack");
1360 CallInst::Create(DFSanVarargWrapperFn,
1361 IRBuilder<>(BB).CreateGlobalString(F->getName()), "", BB);
1362 new UnreachableInst(*Ctx, BB);
1363 } else {
1364 auto ArgIt = pointer_iterator<Argument *>(NewF->arg_begin());
1365 std::vector<Value *> Args(ArgIt, ArgIt + FT->getNumParams());
1366
1367 CallInst *CI = CallInst::Create(F, Args, "", BB);
1368 if (FT->getReturnType()->isVoidTy())
1369 ReturnInst::Create(*Ctx, BB);
1370 else
1371 ReturnInst::Create(*Ctx, CI, BB);
1372 }
1373
1374 return NewF;
1375}
1376
1377// Initialize DataFlowSanitizer runtime functions and declare them in the module
1378void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
1379 LLVMContext &C = M.getContext();
1380 Attribute::AttrKind I8ParamExtAttr =
1382 Attribute::AttrKind I32ParamExtAttr =
1383 TargetLibraryInfo::getExtAttrForI32Param(M.getTargetTriple(),
1384 /*Signed=*/false);
1385 {
1386 AttributeList AL;
1387 AL = AL.addFnAttribute(C, Attribute::NoUnwind);
1388 AL = AL.addFnAttribute(
1389 C, Attribute::getWithMemoryEffects(C, MemoryEffects::readOnly()));
1390 AL = AL.addRetAttribute(C, Attribute::ZExt);
1391 DFSanUnionLoadFn =
1392 Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1393 }
1394 {
1395 AttributeList AL;
1396 AL = AL.addFnAttribute(C, Attribute::NoUnwind);
1397 AL = AL.addFnAttribute(
1398 C, Attribute::getWithMemoryEffects(C, MemoryEffects::readOnly()));
1399 AL = AL.addRetAttribute(C, Attribute::ZExt);
1400 DFSanLoadLabelAndOriginFn = Mod->getOrInsertFunction(
1401 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1402 }
1403 DFSanUnimplementedFn =
1404 Mod->getOrInsertFunction("__dfsan_unimplemented", DFSanUnimplementedFnTy);
1405 DFSanWrapperExternWeakNullFn = Mod->getOrInsertFunction(
1406 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1407 {
1408 AttributeList AL;
1409 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1410 AL = AL.maybeAddParamAttribute(M.getContext(), 1, I32ParamExtAttr);
1411 DFSanSetLabelFn =
1412 Mod->getOrInsertFunction("__dfsan_set_label", DFSanSetLabelFnTy, AL);
1413 }
1414 DFSanNonzeroLabelFn =
1415 Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1416 DFSanVarargWrapperFn = Mod->getOrInsertFunction("__dfsan_vararg_wrapper",
1417 DFSanVarargWrapperFnTy);
1418 {
1419 AttributeList AL;
1420 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I32ParamExtAttr);
1421 AL = AL.addRetAttribute(M.getContext(), Attribute::ZExt);
1422 DFSanChainOriginFn = Mod->getOrInsertFunction("__dfsan_chain_origin",
1423 DFSanChainOriginFnTy, AL);
1424 }
1425 {
1426 AttributeList AL;
1427 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1428 AL = AL.maybeAddParamAttribute(M.getContext(), 1, I32ParamExtAttr);
1429 AL = AL.addRetAttribute(M.getContext(), Attribute::ZExt);
1430 DFSanChainOriginIfTaintedFn = Mod->getOrInsertFunction(
1431 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1432 }
1433 DFSanMemOriginTransferFn = Mod->getOrInsertFunction(
1434 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1435
1436 DFSanMemShadowOriginTransferFn = Mod->getOrInsertFunction(
1437 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1438
1439 {
1440 AttributeList AL;
1441 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1442 DFSanMemShadowOriginConditionalExchangeFn = Mod->getOrInsertFunction(
1443 "__dfsan_mem_shadow_origin_conditional_exchange",
1444 DFSanMemShadowOriginConditionalExchangeFnTy, AL);
1445 }
1446
1447 {
1448 AttributeList AL;
1449 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1450 AL = AL.maybeAddParamAttribute(M.getContext(), 3, I32ParamExtAttr);
1451 DFSanMaybeStoreOriginFn = Mod->getOrInsertFunction(
1452 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1453 }
1454
1455 DFSanRuntimeFunctions.insert(
1456 DFSanUnionLoadFn.getCallee()->stripPointerCasts());
1457 DFSanRuntimeFunctions.insert(
1458 DFSanLoadLabelAndOriginFn.getCallee()->stripPointerCasts());
1459 DFSanRuntimeFunctions.insert(
1460 DFSanUnimplementedFn.getCallee()->stripPointerCasts());
1461 DFSanRuntimeFunctions.insert(
1462 DFSanWrapperExternWeakNullFn.getCallee()->stripPointerCasts());
1463 DFSanRuntimeFunctions.insert(
1464 DFSanSetLabelFn.getCallee()->stripPointerCasts());
1465 DFSanRuntimeFunctions.insert(
1466 DFSanNonzeroLabelFn.getCallee()->stripPointerCasts());
1467 DFSanRuntimeFunctions.insert(
1468 DFSanVarargWrapperFn.getCallee()->stripPointerCasts());
1469 DFSanRuntimeFunctions.insert(
1470 DFSanLoadCallbackFn.getCallee()->stripPointerCasts());
1471 DFSanRuntimeFunctions.insert(
1472 DFSanStoreCallbackFn.getCallee()->stripPointerCasts());
1473 DFSanRuntimeFunctions.insert(
1474 DFSanMemTransferCallbackFn.getCallee()->stripPointerCasts());
1475 DFSanRuntimeFunctions.insert(
1476 DFSanConditionalCallbackFn.getCallee()->stripPointerCasts());
1477 DFSanRuntimeFunctions.insert(
1478 DFSanConditionalCallbackOriginFn.getCallee()->stripPointerCasts());
1479 DFSanRuntimeFunctions.insert(
1480 DFSanReachesFunctionCallbackFn.getCallee()->stripPointerCasts());
1481 DFSanRuntimeFunctions.insert(
1482 DFSanReachesFunctionCallbackOriginFn.getCallee()->stripPointerCasts());
1483 DFSanRuntimeFunctions.insert(
1484 DFSanCmpCallbackFn.getCallee()->stripPointerCasts());
1485 DFSanRuntimeFunctions.insert(
1486 DFSanChainOriginFn.getCallee()->stripPointerCasts());
1487 DFSanRuntimeFunctions.insert(
1488 DFSanChainOriginIfTaintedFn.getCallee()->stripPointerCasts());
1489 DFSanRuntimeFunctions.insert(
1490 DFSanMemOriginTransferFn.getCallee()->stripPointerCasts());
1491 DFSanRuntimeFunctions.insert(
1492 DFSanMemShadowOriginTransferFn.getCallee()->stripPointerCasts());
1493 DFSanRuntimeFunctions.insert(
1494 DFSanMemShadowOriginConditionalExchangeFn.getCallee()
1495 ->stripPointerCasts());
1496 DFSanRuntimeFunctions.insert(
1497 DFSanMaybeStoreOriginFn.getCallee()->stripPointerCasts());
1498}
1499
1500// Initializes event callback functions and declare them in the module
1501void DataFlowSanitizer::initializeCallbackFunctions(Module &M) {
1502 Attribute::AttrKind I8ParamExtAttr =
1504 Attribute::AttrKind I32ParamExtAttr =
1505 TargetLibraryInfo::getExtAttrForI32Param(M.getTargetTriple(),
1506 /*Signed=*/false);
1507 {
1508 AttributeList AL;
1509 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1510 DFSanLoadCallbackFn = Mod->getOrInsertFunction(
1511 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1512 }
1513 {
1514 AttributeList AL;
1515 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1516 DFSanStoreCallbackFn = Mod->getOrInsertFunction(
1517 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1518 }
1519 DFSanMemTransferCallbackFn = Mod->getOrInsertFunction(
1520 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1521 {
1522 AttributeList AL;
1523 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1524 DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback",
1525 DFSanCmpCallbackFnTy, AL);
1526 }
1527 {
1528 AttributeList AL;
1529 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1530 DFSanConditionalCallbackFn = Mod->getOrInsertFunction(
1531 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1532 }
1533 {
1534 AttributeList AL;
1535 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1536 AL = AL.maybeAddParamAttribute(M.getContext(), 1, I32ParamExtAttr);
1537 DFSanConditionalCallbackOriginFn =
1538 Mod->getOrInsertFunction("__dfsan_conditional_callback_origin",
1539 DFSanConditionalCallbackOriginFnTy, AL);
1540 }
1541 {
1542 AttributeList AL;
1543 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1544 AL = AL.maybeAddParamAttribute(M.getContext(), 2, I32ParamExtAttr);
1545 DFSanReachesFunctionCallbackFn =
1546 Mod->getOrInsertFunction("__dfsan_reaches_function_callback",
1547 DFSanReachesFunctionCallbackFnTy, AL);
1548 }
1549 {
1550 AttributeList AL;
1551 AL = AL.maybeAddParamAttribute(M.getContext(), 0, I8ParamExtAttr);
1552 AL = AL.maybeAddParamAttribute(M.getContext(), 1, I32ParamExtAttr);
1553 AL = AL.maybeAddParamAttribute(M.getContext(), 3, I32ParamExtAttr);
1554 DFSanReachesFunctionCallbackOriginFn =
1555 Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin",
1556 DFSanReachesFunctionCallbackOriginFnTy, AL);
1557 }
1558}
1559
1560bool DataFlowSanitizer::runImpl(
1561 Module &M, llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1562 initializeModule(M);
1563
1564 if (ABIList.isIn(M, "skip"))
1565 return false;
1566
1567 const unsigned InitialGlobalSize = M.global_size();
1568 const unsigned InitialModuleSize = M.size();
1569
1570 bool Changed = false;
1571
1572 auto GetOrInsertGlobal = [this, &Changed](StringRef Name,
1573 Type *Ty) -> Constant * {
1574 GlobalVariable *G = Mod->getOrInsertGlobal(Name, Ty);
1575 Changed |= G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1576 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1577 return G;
1578 };
1579
1580 // These globals must be kept in sync with the ones in dfsan.cpp.
1581 ArgTLS =
1582 GetOrInsertGlobal("__dfsan_arg_tls",
1583 ArrayType::get(Type::getInt64Ty(*Ctx), ArgTLSSize / 8));
1584 RetvalTLS = GetOrInsertGlobal(
1585 "__dfsan_retval_tls",
1586 ArrayType::get(Type::getInt64Ty(*Ctx), RetvalTLSSize / 8));
1587 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1588 ArgOriginTLS = GetOrInsertGlobal("__dfsan_arg_origin_tls", ArgOriginTLSTy);
1589 RetvalOriginTLS = GetOrInsertGlobal("__dfsan_retval_origin_tls", OriginTy);
1590
1591 (void)Mod->getOrInsertGlobal("__dfsan_track_origins", OriginTy, [&] {
1592 Changed = true;
1593 return new GlobalVariable(
1594 M, OriginTy, true, GlobalValue::WeakODRLinkage,
1595 ConstantInt::getSigned(OriginTy,
1596 shouldTrackOrigins() ? ClTrackOrigins : 0),
1597 "__dfsan_track_origins");
1598 });
1599
1600 initializeCallbackFunctions(M);
1601 initializeRuntimeFunctions(M);
1602
1603 std::vector<Function *> FnsToInstrument;
1604 SmallPtrSet<Function *, 2> FnsWithNativeABI;
1605 SmallPtrSet<Function *, 2> FnsWithForceZeroLabel;
1606 SmallPtrSet<Constant *, 1> PersonalityFns;
1607 for (Function &F : M)
1608 if (!F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F) &&
1609 !LibAtomicFunction(F) &&
1610 !F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1611 FnsToInstrument.push_back(&F);
1612 if (F.hasPersonalityFn())
1613 PersonalityFns.insert(F.getPersonalityFn()->stripPointerCasts());
1614 }
1615
1617 for (auto *C : PersonalityFns) {
1618 assert(isa<Function>(C) && "Personality routine is not a function!");
1620 if (!isInstrumented(F))
1621 llvm::erase(FnsToInstrument, F);
1622 }
1623 }
1624
1625 // Give function aliases prefixes when necessary, and build wrappers where the
1626 // instrumentedness is inconsistent.
1627 for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) {
1628 // Don't stop on weak. We assume people aren't playing games with the
1629 // instrumentedness of overridden weak aliases.
1631 if (!F)
1632 continue;
1633
1634 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(F);
1635 if (GAInst && FInst) {
1636 addGlobalNameSuffix(&GA);
1637 } else if (GAInst != FInst) {
1638 // Non-instrumented alias of an instrumented function, or vice versa.
1639 // Replace the alias with a native-ABI wrapper of the aliasee. The pass
1640 // below will take care of instrumenting it.
1641 Function *NewF =
1642 buildWrapperFunction(F, "", GA.getLinkage(), F->getFunctionType());
1643 GA.replaceAllUsesWith(NewF);
1644 NewF->takeName(&GA);
1645 GA.eraseFromParent();
1646 FnsToInstrument.push_back(NewF);
1647 }
1648 }
1649
1650 // TODO: This could be more precise.
1651 ReadOnlyNoneAttrs.addAttribute(Attribute::Memory);
1652
1653 // First, change the ABI of every function in the module. ABI-listed
1654 // functions keep their original ABI and get a wrapper function.
1655 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1656 FE = FnsToInstrument.end();
1657 FI != FE; ++FI) {
1658 Function &F = **FI;
1659 FunctionType *FT = F.getFunctionType();
1660
1661 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1662 FT->getReturnType()->isVoidTy());
1663
1664 if (isInstrumented(&F)) {
1665 if (isForceZeroLabels(&F))
1666 FnsWithForceZeroLabel.insert(&F);
1667
1668 // Instrumented functions get a '.dfsan' suffix. This allows us to more
1669 // easily identify cases of mismatching ABIs. This naming scheme is
1670 // mangling-compatible (see Itanium ABI), using a vendor-specific suffix.
1671 addGlobalNameSuffix(&F);
1672 } else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
1673 // Build a wrapper function for F. The wrapper simply calls F, and is
1674 // added to FnsToInstrument so that any instrumentation according to its
1675 // WrapperKind is done in the second pass below.
1676
1677 // If the function being wrapped has local linkage, then preserve the
1678 // function's linkage in the wrapper function.
1679 GlobalValue::LinkageTypes WrapperLinkage =
1680 F.hasLocalLinkage() ? F.getLinkage()
1682
1683 Function *NewF = buildWrapperFunction(
1684 &F,
1685 (shouldTrackOrigins() ? std::string("dfso$") : std::string("dfsw$")) +
1686 std::string(F.getName()),
1687 WrapperLinkage, FT);
1688 NewF->removeFnAttrs(ReadOnlyNoneAttrs);
1689
1690 // Extern weak functions can sometimes be null at execution time.
1691 // Code will sometimes check if an extern weak function is null.
1692 // This could look something like:
1693 // declare extern_weak i8 @my_func(i8)
1694 // br i1 icmp ne (i8 (i8)* @my_func, i8 (i8)* null), label %use_my_func,
1695 // label %avoid_my_func
1696 // The @"dfsw$my_func" wrapper is never null, so if we replace this use
1697 // in the comparison, the icmp will simplify to false and we have
1698 // accidentally optimized away a null check that is necessary.
1699 // This can lead to a crash when the null extern_weak my_func is called.
1700 //
1701 // To prevent (the most common pattern of) this problem,
1702 // do not replace uses in comparisons with the wrapper.
1703 // We definitely want to replace uses in call instructions.
1704 // Other uses (e.g. store the function address somewhere) might be
1705 // called or compared or both - this case may not be handled correctly.
1706 // We will default to replacing with wrapper in cases we are unsure.
1707 auto IsNotCmpUse = [](Use &U) -> bool {
1708 User *Usr = U.getUser();
1709 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
1710 // This is the most common case for icmp ne null
1711 if (CE->getOpcode() == Instruction::ICmp) {
1712 return false;
1713 }
1714 }
1715 if (Instruction *I = dyn_cast<Instruction>(Usr)) {
1716 if (I->getOpcode() == Instruction::ICmp) {
1717 return false;
1718 }
1719 }
1720 return true;
1721 };
1722 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1723
1724 UnwrappedFnMap[NewF] = &F;
1725 *FI = NewF;
1726
1727 if (!F.isDeclaration()) {
1728 // This function is probably defining an interposition of an
1729 // uninstrumented function and hence needs to keep the original ABI.
1730 // But any functions it may call need to use the instrumented ABI, so
1731 // we instrument it in a mode which preserves the original ABI.
1732 FnsWithNativeABI.insert(&F);
1733
1734 // This code needs to rebuild the iterators, as they may be invalidated
1735 // by the push_back, taking care that the new range does not include
1736 // any functions added by this code.
1737 size_t N = FI - FnsToInstrument.begin(),
1738 Count = FE - FnsToInstrument.begin();
1739 FnsToInstrument.push_back(&F);
1740 FI = FnsToInstrument.begin() + N;
1741 FE = FnsToInstrument.begin() + Count;
1742 }
1743 // Hopefully, nobody will try to indirectly call a vararg
1744 // function... yet.
1745 } else if (FT->isVarArg()) {
1746 UnwrappedFnMap[&F] = &F;
1747 *FI = nullptr;
1748 }
1749 }
1750
1751 for (Function *F : FnsToInstrument) {
1752 if (!F || F->isDeclaration())
1753 continue;
1754
1756
1757 DFSanFunction DFSF(*this, F, FnsWithNativeABI.count(F),
1758 FnsWithForceZeroLabel.count(F), GetTLI(*F));
1759
1761 // Add callback for arguments reaching this function.
1762 for (auto &FArg : F->args()) {
1763 Instruction *Next = &F->getEntryBlock().front();
1764 Value *FArgShadow = DFSF.getShadow(&FArg);
1765 if (isZeroShadow(FArgShadow))
1766 continue;
1767 if (Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1768 Next = FArgShadowInst->getNextNode();
1769 }
1770 if (shouldTrackOrigins()) {
1771 if (Instruction *Origin =
1772 dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1773 // Ensure IRB insertion point is after loads for shadow and origin.
1774 Instruction *OriginNext = Origin->getNextNode();
1775 if (Next->comesBefore(OriginNext)) {
1776 Next = OriginNext;
1777 }
1778 }
1779 }
1780 IRBuilder<> IRB(Next);
1781 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1782 }
1783 }
1784
1785 // DFSanVisitor may create new basic blocks, which confuses df_iterator.
1786 // Build a copy of the list before iterating over it.
1787 SmallVector<BasicBlock *, 4> BBList(depth_first(&F->getEntryBlock()));
1788
1789 for (BasicBlock *BB : BBList) {
1790 Instruction *Inst = &BB->front();
1791 while (true) {
1792 // DFSanVisitor may split the current basic block, changing the current
1793 // instruction's next pointer and moving the next instruction to the
1794 // tail block from which we should continue.
1795 Instruction *Next = Inst->getNextNode();
1796 // DFSanVisitor may delete Inst, so keep track of whether it was a
1797 // terminator.
1798 bool IsTerminator = Inst->isTerminator();
1799 if (!DFSF.SkipInsts.count(Inst))
1800 DFSanVisitor(DFSF).visit(Inst);
1801 if (IsTerminator)
1802 break;
1803 Inst = Next;
1804 }
1805 }
1806
1807 // We will not necessarily be able to compute the shadow for every phi node
1808 // until we have visited every block. Therefore, the code that handles phi
1809 // nodes adds them to the PHIFixups list so that they can be properly
1810 // handled here.
1811 for (DFSanFunction::PHIFixupElement &P : DFSF.PHIFixups) {
1812 for (unsigned Val = 0, N = P.Phi->getNumIncomingValues(); Val != N;
1813 ++Val) {
1814 P.ShadowPhi->setIncomingValue(
1815 Val, DFSF.getShadow(P.Phi->getIncomingValue(Val)));
1816 if (P.OriginPhi)
1817 P.OriginPhi->setIncomingValue(
1818 Val, DFSF.getOrigin(P.Phi->getIncomingValue(Val)));
1819 }
1820 }
1821
1822 // -dfsan-debug-nonzero-labels will split the CFG in all kinds of crazy
1823 // places (i.e. instructions in basic blocks we haven't even begun visiting
1824 // yet). To make our life easier, do this work in a pass after the main
1825 // instrumentation.
1827 for (Value *V : DFSF.NonZeroChecks) {
1829 if (Instruction *I = dyn_cast<Instruction>(V))
1830 Pos = std::next(I->getIterator());
1831 else
1832 Pos = DFSF.F->getEntryBlock().begin();
1833 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1834 Pos = std::next(Pos->getIterator());
1835 IRBuilder<> IRB(Pos->getParent(), Pos);
1836 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1837 Value *Ne =
1838 IRB.CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1840 Ne, Pos, /*Unreachable=*/false, ColdCallWeights));
1841 IRBuilder<> ThenIRB(BI);
1842 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1843 }
1844 }
1845 }
1846
1847 return Changed || !FnsToInstrument.empty() ||
1848 M.global_size() != InitialGlobalSize || M.size() != InitialModuleSize;
1849}
1850
1851Value *DFSanFunction::getArgTLS(Type *T, unsigned ArgOffset, IRBuilder<> &IRB) {
1852 return IRB.CreatePtrAdd(DFS.ArgTLS, ConstantInt::get(DFS.IntptrTy, ArgOffset),
1853 "_dfsarg");
1854}
1855
1856Value *DFSanFunction::getRetvalTLS(Type *T, IRBuilder<> &IRB) {
1857 return IRB.CreatePointerCast(DFS.RetvalTLS, PointerType::get(*DFS.Ctx, 0),
1858 "_dfsret");
1859}
1860
1861Value *DFSanFunction::getRetvalOriginTLS() { return DFS.RetvalOriginTLS; }
1862
1863Value *DFSanFunction::getArgOriginTLS(unsigned ArgNo, IRBuilder<> &IRB) {
1864 return IRB.CreateConstInBoundsGEP2_64(DFS.ArgOriginTLSTy, DFS.ArgOriginTLS, 0,
1865 ArgNo, "_dfsarg_o");
1866}
1867
1868Value *DFSanFunction::getOrigin(Value *V) {
1869 assert(DFS.shouldTrackOrigins());
1870 if (!isa<Argument>(V) && !isa<Instruction>(V))
1871 return DFS.ZeroOrigin;
1872 Value *&Origin = ValOriginMap[V];
1873 if (!Origin) {
1874 if (Argument *A = dyn_cast<Argument>(V)) {
1875 if (IsNativeABI)
1876 return DFS.ZeroOrigin;
1877 if (A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1878 Instruction *ArgOriginTLSPos = &*F->getEntryBlock().begin();
1879 IRBuilder<> IRB(ArgOriginTLSPos);
1880 Value *ArgOriginPtr = getArgOriginTLS(A->getArgNo(), IRB);
1881 Origin = IRB.CreateLoad(DFS.OriginTy, ArgOriginPtr);
1882 } else {
1883 // Overflow
1884 Origin = DFS.ZeroOrigin;
1885 }
1886 } else {
1887 Origin = DFS.ZeroOrigin;
1888 }
1889 }
1890 return Origin;
1891}
1892
1893void DFSanFunction::setOrigin(Instruction *I, Value *Origin) {
1894 if (!DFS.shouldTrackOrigins())
1895 return;
1896 assert(!ValOriginMap.count(I));
1897 assert(Origin->getType() == DFS.OriginTy);
1898 ValOriginMap[I] = Origin;
1899}
1900
1901Value *DFSanFunction::getShadowForTLSArgument(Argument *A) {
1902 unsigned ArgOffset = 0;
1903 const DataLayout &DL = F->getDataLayout();
1904 for (auto &FArg : F->args()) {
1905 if (!FArg.getType()->isSized()) {
1906 if (A == &FArg)
1907 break;
1908 continue;
1909 }
1910
1911 unsigned Size = DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1912 if (A != &FArg) {
1913 ArgOffset += alignTo(Size, ShadowTLSAlignment);
1914 if (ArgOffset > ArgTLSSize)
1915 break; // ArgTLS overflows, uses a zero shadow.
1916 continue;
1917 }
1918
1919 if (ArgOffset + Size > ArgTLSSize)
1920 break; // ArgTLS overflows, uses a zero shadow.
1921
1922 Instruction *ArgTLSPos = &*F->getEntryBlock().begin();
1923 IRBuilder<> IRB(ArgTLSPos);
1924 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1925 return IRB.CreateAlignedLoad(DFS.getShadowTy(&FArg), ArgShadowPtr,
1927 }
1928
1929 return DFS.getZeroShadow(A);
1930}
1931
1932Value *DFSanFunction::getShadow(Value *V) {
1933 if (!isa<Argument>(V) && !isa<Instruction>(V))
1934 return DFS.getZeroShadow(V);
1935 if (IsForceZeroLabels)
1936 return DFS.getZeroShadow(V);
1937 Value *&Shadow = ValShadowMap[V];
1938 if (!Shadow) {
1939 if (Argument *A = dyn_cast<Argument>(V)) {
1940 if (IsNativeABI)
1941 return DFS.getZeroShadow(V);
1942 Shadow = getShadowForTLSArgument(A);
1943 NonZeroChecks.push_back(Shadow);
1944 } else {
1945 Shadow = DFS.getZeroShadow(V);
1946 }
1947 }
1948 return Shadow;
1949}
1950
1951void DFSanFunction::setShadow(Instruction *I, Value *Shadow) {
1952 assert(!ValShadowMap.count(I));
1953 ValShadowMap[I] = Shadow;
1954}
1955
1956/// Compute the integer shadow offset that corresponds to a given
1957/// application address.
1958///
1959/// Offset = (Addr & ~AndMask) ^ XorMask
1960Value *DataFlowSanitizer::getShadowOffset(Value *Addr, IRBuilder<> &IRB) {
1961 assert(Addr != RetvalTLS && "Reinstrumenting?");
1962 Value *OffsetLong = IRB.CreatePointerCast(Addr, IntptrTy);
1963
1964 uint64_t AndMask = MapParams->AndMask;
1965 if (AndMask)
1966 OffsetLong =
1967 IRB.CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1968
1969 uint64_t XorMask = MapParams->XorMask;
1970 if (XorMask)
1971 OffsetLong = IRB.CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1972 return OffsetLong;
1973}
1974
1975std::pair<Value *, Value *>
1976DataFlowSanitizer::getShadowOriginAddress(Value *Addr, Align InstAlignment,
1978 // Returns ((Addr & shadow_mask) + origin_base - shadow_base) & ~4UL
1979 IRBuilder<> IRB(Pos->getParent(), Pos);
1980 Value *ShadowOffset = getShadowOffset(Addr, IRB);
1981 Value *ShadowLong = ShadowOffset;
1982 uint64_t ShadowBase = MapParams->ShadowBase;
1983 if (ShadowBase != 0) {
1984 ShadowLong =
1985 IRB.CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1986 }
1987 Value *ShadowPtr = IRB.CreateIntToPtr(ShadowLong, PointerType::get(*Ctx, 0));
1988 Value *OriginPtr = nullptr;
1989 if (shouldTrackOrigins()) {
1990 Value *OriginLong = ShadowOffset;
1991 uint64_t OriginBase = MapParams->OriginBase;
1992 if (OriginBase != 0)
1993 OriginLong =
1994 IRB.CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1995 const Align Alignment = llvm::assumeAligned(InstAlignment.value());
1996 // When alignment is >= 4, Addr must be aligned to 4, otherwise it is UB.
1997 // So Mask is unnecessary.
1998 if (Alignment < MinOriginAlignment) {
2000 OriginLong = IRB.CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
2001 }
2002 OriginPtr = IRB.CreateIntToPtr(OriginLong, OriginPtrTy);
2003 }
2004 return std::make_pair(ShadowPtr, OriginPtr);
2005}
2006
2007Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
2009 Value *ShadowOffset) {
2010 IRBuilder<> IRB(Pos->getParent(), Pos);
2011 return IRB.CreateIntToPtr(ShadowOffset, PrimitiveShadowPtrTy);
2012}
2013
2014Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
2016 IRBuilder<> IRB(Pos->getParent(), Pos);
2017 Value *ShadowAddr = getShadowOffset(Addr, IRB);
2018 uint64_t ShadowBase = MapParams->ShadowBase;
2019 if (ShadowBase != 0)
2020 ShadowAddr =
2021 IRB.CreateAdd(ShadowAddr, ConstantInt::get(IntptrTy, ShadowBase));
2022 return getShadowAddress(Addr, Pos, ShadowAddr);
2023}
2024
2025Value *DFSanFunction::combineShadowsThenConvert(Type *T, Value *V1, Value *V2,
2027 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
2028 return expandFromPrimitiveShadow(T, PrimitiveValue, Pos);
2029}
2030
2031// Generates IR to compute the union of the two given shadows, inserting it
2032// before Pos. The combined value is with primitive type.
2033Value *DFSanFunction::combineShadows(Value *V1, Value *V2,
2035 if (DFS.isZeroShadow(V1))
2036 return collapseToPrimitiveShadow(V2, Pos);
2037 if (DFS.isZeroShadow(V2))
2038 return collapseToPrimitiveShadow(V1, Pos);
2039 if (V1 == V2)
2040 return collapseToPrimitiveShadow(V1, Pos);
2041
2042 auto V1Elems = ShadowElements.find(V1);
2043 auto V2Elems = ShadowElements.find(V2);
2044 if (V1Elems != ShadowElements.end() && V2Elems != ShadowElements.end()) {
2045 if (llvm::includes(V1Elems->second, V2Elems->second)) {
2046 return collapseToPrimitiveShadow(V1, Pos);
2047 }
2048 if (llvm::includes(V2Elems->second, V1Elems->second)) {
2049 return collapseToPrimitiveShadow(V2, Pos);
2050 }
2051 } else if (V1Elems != ShadowElements.end()) {
2052 if (V1Elems->second.count(V2))
2053 return collapseToPrimitiveShadow(V1, Pos);
2054 } else if (V2Elems != ShadowElements.end()) {
2055 if (V2Elems->second.count(V1))
2056 return collapseToPrimitiveShadow(V2, Pos);
2057 }
2058
2059 auto Key = std::make_pair(V1, V2);
2060 if (V1 > V2)
2061 std::swap(Key.first, Key.second);
2062 CachedShadow &CCS = CachedShadows[Key];
2063 if (CCS.Block && DT.dominates(CCS.Block, Pos->getParent()))
2064 return CCS.Shadow;
2065
2066 // Converts inputs shadows to shadows with primitive types.
2067 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2068 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2069
2070 IRBuilder<> IRB(Pos->getParent(), Pos);
2071 CCS.Block = Pos->getParent();
2072 CCS.Shadow = IRB.CreateOr(PV1, PV2);
2073
2074 std::set<Value *> UnionElems;
2075 if (V1Elems != ShadowElements.end()) {
2076 UnionElems = V1Elems->second;
2077 } else {
2078 UnionElems.insert(V1);
2079 }
2080 if (V2Elems != ShadowElements.end()) {
2081 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2082 } else {
2083 UnionElems.insert(V2);
2084 }
2085 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2086
2087 return CCS.Shadow;
2088}
2089
2090// A convenience function which folds the shadows of each of the operands
2091// of the provided instruction Inst, inserting the IR before Inst. Returns
2092// the computed union Value.
2093Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
2094 if (Inst->getNumOperands() == 0)
2095 return DFS.getZeroShadow(Inst);
2096
2097 Value *Shadow = getShadow(Inst->getOperand(0));
2098 for (unsigned I = 1, N = Inst->getNumOperands(); I < N; ++I)
2099 Shadow = combineShadows(Shadow, getShadow(Inst->getOperand(I)),
2100 Inst->getIterator());
2101
2102 return expandFromPrimitiveShadow(Inst->getType(), Shadow,
2103 Inst->getIterator());
2104}
2105
2106void DFSanVisitor::visitInstOperands(Instruction &I) {
2107 Value *CombinedShadow = DFSF.combineOperandShadows(&I);
2108 DFSF.setShadow(&I, CombinedShadow);
2109 visitInstOperandOrigins(I);
2110}
2111
2112Value *DFSanFunction::combineOrigins(const std::vector<Value *> &Shadows,
2113 const std::vector<Value *> &Origins,
2115 ConstantInt *Zero) {
2116 assert(Shadows.size() == Origins.size());
2117 size_t Size = Origins.size();
2118 if (Size == 0)
2119 return DFS.ZeroOrigin;
2120 Value *Origin = nullptr;
2121 if (!Zero)
2122 Zero = DFS.ZeroPrimitiveShadow;
2123 for (size_t I = 0; I != Size; ++I) {
2124 Value *OpOrigin = Origins[I];
2125 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2126 if (ConstOpOrigin && ConstOpOrigin->isNullValue())
2127 continue;
2128 if (!Origin) {
2129 Origin = OpOrigin;
2130 continue;
2131 }
2132 Value *OpShadow = Shadows[I];
2133 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2134 IRBuilder<> IRB(Pos->getParent(), Pos);
2135 Value *Cond = IRB.CreateICmpNE(PrimitiveShadow, Zero);
2136 Origin = IRB.CreateSelect(Cond, OpOrigin, Origin);
2137 }
2138 return Origin ? Origin : DFS.ZeroOrigin;
2139}
2140
2141Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) {
2142 size_t Size = Inst->getNumOperands();
2143 std::vector<Value *> Shadows(Size);
2144 std::vector<Value *> Origins(Size);
2145 for (unsigned I = 0; I != Size; ++I) {
2146 Shadows[I] = getShadow(Inst->getOperand(I));
2147 Origins[I] = getOrigin(Inst->getOperand(I));
2148 }
2149 return combineOrigins(Shadows, Origins, Inst->getIterator());
2150}
2151
2152void DFSanVisitor::visitInstOperandOrigins(Instruction &I) {
2153 if (!DFSF.DFS.shouldTrackOrigins())
2154 return;
2155 Value *CombinedOrigin = DFSF.combineOperandOrigins(&I);
2156 DFSF.setOrigin(&I, CombinedOrigin);
2157}
2158
2159Align DFSanFunction::getShadowAlign(Align InstAlignment) {
2160 const Align Alignment = ClPreserveAlignment ? InstAlignment : Align(1);
2161 return Align(Alignment.value() * DFS.ShadowWidthBytes);
2162}
2163
2164Align DFSanFunction::getOriginAlign(Align InstAlignment) {
2165 const Align Alignment = llvm::assumeAligned(InstAlignment.value());
2166 return Align(std::max(MinOriginAlignment, Alignment));
2167}
2168
2169bool DFSanFunction::isLookupTableConstant(Value *P) {
2170 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(P->stripPointerCasts()))
2171 if (GV->isConstant() && GV->hasName())
2172 return DFS.CombineTaintLookupTableNames.count(GV->getName());
2173
2174 return false;
2175}
2176
2177bool DFSanFunction::useCallbackLoadLabelAndOrigin(uint64_t Size,
2178 Align InstAlignment) {
2179 // When enabling tracking load instructions, we always use
2180 // __dfsan_load_label_and_origin to reduce code size.
2181 if (ClTrackOrigins == 2)
2182 return true;
2183
2184 assert(Size != 0);
2185 // * if Size == 1, it is sufficient to load its origin aligned at 4.
2186 // * if Size == 2, we assume most cases Addr % 2 == 0, so it is sufficient to
2187 // load its origin aligned at 4. If not, although origins may be lost, it
2188 // should not happen very often.
2189 // * if align >= 4, Addr must be aligned to 4, otherwise it is UB. When
2190 // Size % 4 == 0, it is more efficient to load origins without callbacks.
2191 // * Otherwise we use __dfsan_load_label_and_origin.
2192 // This should ensure that common cases run efficiently.
2193 if (Size <= 2)
2194 return false;
2195
2196 const Align Alignment = llvm::assumeAligned(InstAlignment.value());
2197 return Alignment < MinOriginAlignment || !DFS.hasLoadSizeForFastPath(Size);
2198}
2199
2200Value *DataFlowSanitizer::loadNextOrigin(BasicBlock::iterator Pos,
2201 Align OriginAlign,
2202 Value **OriginAddr) {
2203 IRBuilder<> IRB(Pos->getParent(), Pos);
2204 *OriginAddr =
2205 IRB.CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2206 return IRB.CreateAlignedLoad(OriginTy, *OriginAddr, OriginAlign);
2207}
2208
2209std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2210 Value *ShadowAddr, Value *OriginAddr, uint64_t Size, Align ShadowAlign,
2211 Align OriginAlign, Value *FirstOrigin, BasicBlock::iterator Pos) {
2212 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2213 const uint64_t ShadowSize = Size * DFS.ShadowWidthBytes;
2214
2215 assert(Size >= 4 && "Not large enough load size for fast path!");
2216
2217 // Used for origin tracking.
2218 std::vector<Value *> Shadows;
2219 std::vector<Value *> Origins;
2220
2221 // Load instructions in LLVM can have arbitrary byte sizes (e.g., 3, 12, 20)
2222 // but this function is only used in a subset of cases that make it possible
2223 // to optimize the instrumentation.
2224 //
2225 // Specifically, when the shadow size in bytes (i.e., loaded bytes x shadow
2226 // per byte) is either:
2227 // - a multiple of 8 (common)
2228 // - equal to 4 (only for load32)
2229 //
2230 // For the second case, we can fit the wide shadow in a 32-bit integer. In all
2231 // other cases, we use a 64-bit integer to hold the wide shadow.
2232 Type *WideShadowTy =
2233 ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) : Type::getInt64Ty(*DFS.Ctx);
2234
2235 IRBuilder<> IRB(Pos->getParent(), Pos);
2236 Value *CombinedWideShadow =
2237 IRB.CreateAlignedLoad(WideShadowTy, ShadowAddr, ShadowAlign);
2238
2239 unsigned WideShadowBitWidth = WideShadowTy->getIntegerBitWidth();
2240 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2241
2242 auto AppendWideShadowAndOrigin = [&](Value *WideShadow, Value *Origin) {
2243 if (BytesPerWideShadow > 4) {
2244 assert(BytesPerWideShadow == 8);
2245 // The wide shadow relates to two origin pointers: one for the first four
2246 // application bytes, and one for the latest four. We use a left shift to
2247 // get just the shadow bytes that correspond to the first origin pointer,
2248 // and then the entire shadow for the second origin pointer (which will be
2249 // chosen by combineOrigins() iff the least-significant half of the wide
2250 // shadow was empty but the other half was not).
2251 Value *WideShadowLo =
2252 F->getParent()->getDataLayout().isLittleEndian()
2253 ? IRB.CreateShl(
2254 WideShadow,
2255 ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2))
2256 : IRB.CreateAnd(
2257 WideShadow,
2258 ConstantInt::get(WideShadowTy,
2259 ((1ULL << (WideShadowBitWidth / 2)) - 1)
2260 << (WideShadowBitWidth / 2)));
2261 Shadows.push_back(WideShadow);
2262 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2263
2264 Shadows.push_back(WideShadowLo);
2265 Origins.push_back(Origin);
2266 } else {
2267 Shadows.push_back(WideShadow);
2268 Origins.push_back(Origin);
2269 }
2270 };
2271
2272 if (ShouldTrackOrigins)
2273 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2274
2275 // First OR all the WideShadows (i.e., 64bit or 32bit shadow chunks) linearly;
2276 // then OR individual shadows within the combined WideShadow by binary ORing.
2277 // This is fewer instructions than ORing shadows individually, since it
2278 // needs logN shift/or instructions (N being the bytes of the combined wide
2279 // shadow).
2280 for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs < Size;
2281 ByteOfs += BytesPerWideShadow) {
2282 ShadowAddr = IRB.CreateGEP(WideShadowTy, ShadowAddr,
2283 ConstantInt::get(DFS.IntptrTy, 1));
2284 Value *NextWideShadow =
2285 IRB.CreateAlignedLoad(WideShadowTy, ShadowAddr, ShadowAlign);
2286 CombinedWideShadow = IRB.CreateOr(CombinedWideShadow, NextWideShadow);
2287 if (ShouldTrackOrigins) {
2288 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2289 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2290 }
2291 }
2292 for (unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2293 Width >>= 1) {
2294 Value *ShrShadow = IRB.CreateLShr(CombinedWideShadow, Width);
2295 CombinedWideShadow = IRB.CreateOr(CombinedWideShadow, ShrShadow);
2296 }
2297 return {IRB.CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2298 ShouldTrackOrigins
2299 ? combineOrigins(Shadows, Origins, Pos,
2301 : DFS.ZeroOrigin};
2302}
2303
2304std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2305 Value *Addr, uint64_t Size, Align InstAlignment, BasicBlock::iterator Pos) {
2306 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2307
2308 // Non-escaped loads.
2309 if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
2310 const auto SI = AllocaShadowMap.find(AI);
2311 if (SI != AllocaShadowMap.end()) {
2312 IRBuilder<> IRB(Pos->getParent(), Pos);
2313 Value *ShadowLI = IRB.CreateLoad(DFS.PrimitiveShadowTy, SI->second);
2314 const auto OI = AllocaOriginMap.find(AI);
2315 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.end());
2316 return {ShadowLI, ShouldTrackOrigins
2317 ? IRB.CreateLoad(DFS.OriginTy, OI->second)
2318 : nullptr};
2319 }
2320 }
2321
2322 // Load from constant addresses.
2323 SmallVector<const Value *, 2> Objs;
2324 getUnderlyingObjects(Addr, Objs);
2325 bool AllConstants = true;
2326 for (const Value *Obj : Objs) {
2327 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2328 continue;
2330 continue;
2331
2332 AllConstants = false;
2333 break;
2334 }
2335 if (AllConstants)
2336 return {DFS.ZeroPrimitiveShadow,
2337 ShouldTrackOrigins ? DFS.ZeroOrigin : nullptr};
2338
2339 if (Size == 0)
2340 return {DFS.ZeroPrimitiveShadow,
2341 ShouldTrackOrigins ? DFS.ZeroOrigin : nullptr};
2342
2343 // Use callback to load if this is not an optimizable case for origin
2344 // tracking.
2345 if (ShouldTrackOrigins &&
2346 useCallbackLoadLabelAndOrigin(Size, InstAlignment)) {
2347 IRBuilder<> IRB(Pos->getParent(), Pos);
2348 CallInst *Call =
2349 IRB.CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2350 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2351 Call->addRetAttr(Attribute::ZExt);
2352 return {IRB.CreateTrunc(IRB.CreateLShr(Call, DFS.OriginWidthBits),
2353 DFS.PrimitiveShadowTy),
2354 IRB.CreateTrunc(Call, DFS.OriginTy)};
2355 }
2356
2357 // Other cases that support loading shadows or origins in a fast way.
2358 Value *ShadowAddr, *OriginAddr;
2359 std::tie(ShadowAddr, OriginAddr) =
2360 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2361
2362 const Align ShadowAlign = getShadowAlign(InstAlignment);
2363 const Align OriginAlign = getOriginAlign(InstAlignment);
2364 Value *Origin = nullptr;
2365 if (ShouldTrackOrigins) {
2366 IRBuilder<> IRB(Pos->getParent(), Pos);
2367 Origin = IRB.CreateAlignedLoad(DFS.OriginTy, OriginAddr, OriginAlign);
2368 }
2369
2370 // When the byte size is small enough, we can load the shadow directly with
2371 // just a few instructions.
2372 switch (Size) {
2373 case 1: {
2374 LoadInst *LI = new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr, "", Pos);
2375 LI->setAlignment(ShadowAlign);
2376 return {LI, Origin};
2377 }
2378 case 2: {
2379 IRBuilder<> IRB(Pos->getParent(), Pos);
2380 Value *ShadowAddr1 = IRB.CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2381 ConstantInt::get(DFS.IntptrTy, 1));
2382 Value *Load =
2383 IRB.CreateAlignedLoad(DFS.PrimitiveShadowTy, ShadowAddr, ShadowAlign);
2384 Value *Load1 =
2385 IRB.CreateAlignedLoad(DFS.PrimitiveShadowTy, ShadowAddr1, ShadowAlign);
2386 return {combineShadows(Load, Load1, Pos), Origin};
2387 }
2388 }
2389 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(Size);
2390
2391 if (HasSizeForFastPath)
2392 return loadShadowFast(ShadowAddr, OriginAddr, Size, ShadowAlign,
2393 OriginAlign, Origin, Pos);
2394
2395 IRBuilder<> IRB(Pos->getParent(), Pos);
2396 CallInst *FallbackCall = IRB.CreateCall(
2397 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2398 FallbackCall->addRetAttr(Attribute::ZExt);
2399 return {FallbackCall, Origin};
2400}
2401
2402std::pair<Value *, Value *>
2403DFSanFunction::loadShadowOrigin(Value *Addr, uint64_t Size, Align InstAlignment,
2405 Value *PrimitiveShadow, *Origin;
2406 std::tie(PrimitiveShadow, Origin) =
2407 loadShadowOriginSansLoadTracking(Addr, Size, InstAlignment, Pos);
2408 if (DFS.shouldTrackOrigins()) {
2409 if (ClTrackOrigins == 2) {
2410 IRBuilder<> IRB(Pos->getParent(), Pos);
2411 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2412 if (!ConstantShadow || !ConstantShadow->isNullValue())
2413 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2414 }
2415 }
2416 return {PrimitiveShadow, Origin};
2417}
2418
2435
2437 if (!V->getType()->isPointerTy())
2438 return V;
2439
2440 // DFSan pass should be running on valid IR, but we'll
2441 // keep a seen set to ensure there are no issues.
2443 Visited.insert(V);
2444 do {
2445 if (auto *GEP = dyn_cast<GEPOperator>(V)) {
2446 V = GEP->getPointerOperand();
2447 } else if (Operator::getOpcode(V) == Instruction::BitCast) {
2448 V = cast<Operator>(V)->getOperand(0);
2449 if (!V->getType()->isPointerTy())
2450 return V;
2451 } else if (isa<GlobalAlias>(V)) {
2452 V = cast<GlobalAlias>(V)->getAliasee();
2453 }
2454 } while (Visited.insert(V).second);
2455
2456 return V;
2457}
2458
2459void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2460 auto &DL = LI.getDataLayout();
2461 uint64_t Size = DL.getTypeStoreSize(LI.getType());
2462 if (Size == 0) {
2463 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2464 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2465 return;
2466 }
2467
2468 // When an application load is atomic, increase atomic ordering between
2469 // atomic application loads and stores to ensure happen-before order; load
2470 // shadow data after application data; store zero shadow data before
2471 // application data. This ensure shadow loads return either labels of the
2472 // initial application data or zeros.
2473 if (LI.isAtomic())
2475
2476 BasicBlock::iterator AfterLi = std::next(LI.getIterator());
2478 if (LI.isAtomic())
2479 Pos = std::next(Pos);
2480
2481 std::vector<Value *> Shadows;
2482 std::vector<Value *> Origins;
2483 Value *PrimitiveShadow, *Origin;
2484 std::tie(PrimitiveShadow, Origin) =
2485 DFSF.loadShadowOrigin(LI.getPointerOperand(), Size, LI.getAlign(), Pos);
2486 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2487 if (ShouldTrackOrigins) {
2488 Shadows.push_back(PrimitiveShadow);
2489 Origins.push_back(Origin);
2490 }
2492 DFSF.isLookupTableConstant(
2494 Value *PtrShadow = DFSF.getShadow(LI.getPointerOperand());
2495 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2496 if (ShouldTrackOrigins) {
2497 Shadows.push_back(PtrShadow);
2498 Origins.push_back(DFSF.getOrigin(LI.getPointerOperand()));
2499 }
2500 }
2501 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2502 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2503
2504 Value *Shadow =
2505 DFSF.expandFromPrimitiveShadow(LI.getType(), PrimitiveShadow, Pos);
2506 DFSF.setShadow(&LI, Shadow);
2507
2508 if (ShouldTrackOrigins) {
2509 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2510 }
2511
2512 if (ClEventCallbacks) {
2513 IRBuilder<> IRB(Pos->getParent(), Pos);
2514 Value *Addr = LI.getPointerOperand();
2515 CallInst *CI =
2516 IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2517 CI->maybeAddParamAttr(0, DFSF.TLI.getExtAttrForI8Param(/*Signed=*/false));
2518 }
2519
2520 IRBuilder<> IRB(AfterLi->getParent(), AfterLi);
2521 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2522}
2523
2524Value *DFSanFunction::updateOriginIfTainted(Value *Shadow, Value *Origin,
2525 IRBuilder<> &IRB) {
2526 assert(DFS.shouldTrackOrigins());
2527 return IRB.CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2528}
2529
2530Value *DFSanFunction::updateOrigin(Value *V, IRBuilder<> &IRB) {
2531 if (!DFS.shouldTrackOrigins())
2532 return V;
2533 return IRB.CreateCall(DFS.DFSanChainOriginFn, V);
2534}
2535
2536Value *DFSanFunction::originToIntptr(IRBuilder<> &IRB, Value *Origin) {
2537 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2538 const DataLayout &DL = F->getDataLayout();
2539 unsigned IntptrSize = DL.getTypeStoreSize(DFS.IntptrTy);
2540 if (IntptrSize == OriginSize)
2541 return Origin;
2542 assert(IntptrSize == OriginSize * 2);
2543 Origin = IRB.CreateIntCast(Origin, DFS.IntptrTy, /* isSigned */ false);
2544 return IRB.CreateOr(Origin, IRB.CreateShl(Origin, OriginSize * 8));
2545}
2546
2547void DFSanFunction::paintOrigin(IRBuilder<> &IRB, Value *Origin,
2548 Value *StoreOriginAddr,
2549 uint64_t StoreOriginSize, Align Alignment) {
2550 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2551 const DataLayout &DL = F->getDataLayout();
2552 const Align IntptrAlignment = DL.getABITypeAlign(DFS.IntptrTy);
2553 unsigned IntptrSize = DL.getTypeStoreSize(DFS.IntptrTy);
2554 assert(IntptrAlignment >= MinOriginAlignment);
2555 assert(IntptrSize >= OriginSize);
2556
2557 unsigned Ofs = 0;
2558 Align CurrentAlignment = Alignment;
2559 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2560 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2561 Value *IntptrStoreOriginPtr =
2562 IRB.CreatePointerCast(StoreOriginAddr, PointerType::get(*DFS.Ctx, 0));
2563 for (unsigned I = 0; I < StoreOriginSize / IntptrSize; ++I) {
2564 Value *Ptr =
2565 I ? IRB.CreateConstGEP1_32(DFS.IntptrTy, IntptrStoreOriginPtr, I)
2566 : IntptrStoreOriginPtr;
2567 IRB.CreateAlignedStore(IntptrOrigin, Ptr, CurrentAlignment);
2568 Ofs += IntptrSize / OriginSize;
2569 CurrentAlignment = IntptrAlignment;
2570 }
2571 }
2572
2573 for (unsigned I = Ofs; I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2574 ++I) {
2575 Value *GEP = I ? IRB.CreateConstGEP1_32(DFS.OriginTy, StoreOriginAddr, I)
2576 : StoreOriginAddr;
2577 IRB.CreateAlignedStore(Origin, GEP, CurrentAlignment);
2578 CurrentAlignment = MinOriginAlignment;
2579 }
2580}
2581
2582Value *DFSanFunction::convertToBool(Value *V, IRBuilder<> &IRB,
2583 const Twine &Name) {
2584 Type *VTy = V->getType();
2585 assert(VTy->isIntegerTy());
2586 if (VTy->getIntegerBitWidth() == 1)
2587 // Just converting a bool to a bool, so do nothing.
2588 return V;
2589 return IRB.CreateICmpNE(V, ConstantInt::get(VTy, 0), Name);
2590}
2591
2592void DFSanFunction::storeOrigin(BasicBlock::iterator Pos, Value *Addr,
2593 uint64_t Size, Value *Shadow, Value *Origin,
2594 Value *StoreOriginAddr, Align InstAlignment) {
2595 // Do not write origins for zero shadows because we do not trace origins for
2596 // untainted sinks.
2597 const Align OriginAlignment = getOriginAlign(InstAlignment);
2598 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2599 IRBuilder<> IRB(Pos->getParent(), Pos);
2600 if (auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2601 if (!ConstantShadow->isNullValue())
2602 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr, Size,
2603 OriginAlignment);
2604 return;
2605 }
2606
2607 if (shouldInstrumentWithCall()) {
2608 IRB.CreateCall(
2609 DFS.DFSanMaybeStoreOriginFn,
2610 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2611 } else {
2612 Value *Cmp = convertToBool(CollapsedShadow, IRB, "_dfscmp");
2613 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2615 Cmp, &*IRB.GetInsertPoint(), false, DFS.OriginStoreWeights, &DTU);
2616 IRBuilder<> IRBNew(CheckTerm);
2617 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr, Size,
2618 OriginAlignment);
2619 ++NumOriginStores;
2620 }
2621}
2622
2623void DFSanFunction::storeZeroPrimitiveShadow(Value *Addr, uint64_t Size,
2624 Align ShadowAlign,
2626 IRBuilder<> IRB(Pos->getParent(), Pos);
2627 IntegerType *ShadowTy =
2628 IntegerType::get(*DFS.Ctx, Size * DFS.ShadowWidthBits);
2629 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2630 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
2631 IRB.CreateAlignedStore(ExtZeroShadow, ShadowAddr, ShadowAlign);
2632 // Do not write origins for 0 shadows because we do not trace origins for
2633 // untainted sinks.
2634}
2635
2636void DFSanFunction::storePrimitiveShadowOrigin(Value *Addr, uint64_t Size,
2637 Align InstAlignment,
2638 Value *PrimitiveShadow,
2639 Value *Origin,
2641 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2642
2643 if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
2644 const auto SI = AllocaShadowMap.find(AI);
2645 if (SI != AllocaShadowMap.end()) {
2646 IRBuilder<> IRB(Pos->getParent(), Pos);
2647 IRB.CreateStore(PrimitiveShadow, SI->second);
2648
2649 // Do not write origins for 0 shadows because we do not trace origins for
2650 // untainted sinks.
2651 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2652 const auto OI = AllocaOriginMap.find(AI);
2653 assert(OI != AllocaOriginMap.end() && Origin);
2654 IRB.CreateStore(Origin, OI->second);
2655 }
2656 return;
2657 }
2658 }
2659
2660 const Align ShadowAlign = getShadowAlign(InstAlignment);
2661 if (DFS.isZeroShadow(PrimitiveShadow)) {
2662 storeZeroPrimitiveShadow(Addr, Size, ShadowAlign, Pos);
2663 return;
2664 }
2665
2666 IRBuilder<> IRB(Pos->getParent(), Pos);
2667 Value *ShadowAddr, *OriginAddr;
2668 std::tie(ShadowAddr, OriginAddr) =
2669 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2670
2671 const unsigned ShadowVecSize = 8;
2672 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2673 "Shadow vector is too large!");
2674
2675 uint64_t Offset = 0;
2676 uint64_t LeftSize = Size;
2677 if (LeftSize >= ShadowVecSize) {
2678 auto *ShadowVecTy =
2679 FixedVectorType::get(DFS.PrimitiveShadowTy, ShadowVecSize);
2680 Value *ShadowVec = PoisonValue::get(ShadowVecTy);
2681 for (unsigned I = 0; I != ShadowVecSize; ++I) {
2682 ShadowVec = IRB.CreateInsertElement(
2683 ShadowVec, PrimitiveShadow,
2684 ConstantInt::get(Type::getInt32Ty(*DFS.Ctx), I));
2685 }
2686 do {
2687 Value *CurShadowVecAddr =
2688 IRB.CreateConstGEP1_32(ShadowVecTy, ShadowAddr, Offset);
2689 IRB.CreateAlignedStore(ShadowVec, CurShadowVecAddr, ShadowAlign);
2690 LeftSize -= ShadowVecSize;
2691 ++Offset;
2692 } while (LeftSize >= ShadowVecSize);
2693 Offset *= ShadowVecSize;
2694 }
2695 while (LeftSize > 0) {
2696 Value *CurShadowAddr =
2697 IRB.CreateConstGEP1_32(DFS.PrimitiveShadowTy, ShadowAddr, Offset);
2698 IRB.CreateAlignedStore(PrimitiveShadow, CurShadowAddr, ShadowAlign);
2699 --LeftSize;
2700 ++Offset;
2701 }
2702
2703 if (ShouldTrackOrigins) {
2704 storeOrigin(Pos, Addr, Size, PrimitiveShadow, Origin, OriginAddr,
2705 InstAlignment);
2706 }
2707}
2708
2725
2726void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2727 auto &DL = SI.getDataLayout();
2728 Value *Val = SI.getValueOperand();
2729 uint64_t Size = DL.getTypeStoreSize(Val->getType());
2730 if (Size == 0)
2731 return;
2732
2733 // When an application store is atomic, increase atomic ordering between
2734 // atomic application loads and stores to ensure happen-before order; load
2735 // shadow data after application data; store zero shadow data before
2736 // application data. This ensure shadow loads return either labels of the
2737 // initial application data or zeros.
2738 if (SI.isAtomic())
2739 SI.setOrdering(addReleaseOrdering(SI.getOrdering()));
2740
2741 const bool ShouldTrackOrigins =
2742 DFSF.DFS.shouldTrackOrigins() && !SI.isAtomic();
2743 std::vector<Value *> Shadows;
2744 std::vector<Value *> Origins;
2745
2746 Value *Shadow =
2747 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2748
2749 if (ShouldTrackOrigins) {
2750 Shadows.push_back(Shadow);
2751 Origins.push_back(DFSF.getOrigin(Val));
2752 }
2753
2754 Value *PrimitiveShadow;
2756 Value *PtrShadow = DFSF.getShadow(SI.getPointerOperand());
2757 if (ShouldTrackOrigins) {
2758 Shadows.push_back(PtrShadow);
2759 Origins.push_back(DFSF.getOrigin(SI.getPointerOperand()));
2760 }
2761 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow, SI.getIterator());
2762 } else {
2763 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow, SI.getIterator());
2764 }
2765 Value *Origin = nullptr;
2766 if (ShouldTrackOrigins)
2767 Origin = DFSF.combineOrigins(Shadows, Origins, SI.getIterator());
2768 DFSF.storePrimitiveShadowOrigin(SI.getPointerOperand(), Size, SI.getAlign(),
2769 PrimitiveShadow, Origin, SI.getIterator());
2770 if (ClEventCallbacks) {
2771 IRBuilder<> IRB(&SI);
2772 Value *Addr = SI.getPointerOperand();
2773 CallInst *CI =
2774 IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2775 CI->maybeAddParamAttr(0, DFSF.TLI.getExtAttrForI8Param(/*Signed=*/false));
2776 }
2777}
2778
2779void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &I) {
2781
2782 Value *Val = I.getOperand(1);
2783 const auto &DL = I.getDataLayout();
2784 uint64_t Size = DL.getTypeStoreSize(Val->getType());
2785 if (Size == 0)
2786 return;
2787
2788 // Conservatively set data at stored addresses and return with zero shadow to
2789 // prevent shadow data races.
2790 IRBuilder<> IRB(&I);
2791 Value *Addr = I.getOperand(0);
2792 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2793 DFSF.storeZeroPrimitiveShadow(Addr, Size, ShadowAlign, I.getIterator());
2794 DFSF.setShadow(&I, DFSF.DFS.getZeroShadow(&I));
2795 DFSF.setOrigin(&I, DFSF.DFS.ZeroOrigin);
2796}
2797
2798void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
2799 visitCASOrRMW(I.getAlign(), I);
2800 // TODO: The ordering change follows MSan. It is possible not to change
2801 // ordering because we always set and use 0 shadows.
2802 I.setOrdering(addReleaseOrdering(I.getOrdering()));
2803}
2804
2805void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
2806 visitCASOrRMW(I.getAlign(), I);
2807 // TODO: The ordering change follows MSan. It is possible not to change
2808 // ordering because we always set and use 0 shadows.
2809 I.setSuccessOrdering(addReleaseOrdering(I.getSuccessOrdering()));
2810}
2811
2812void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2813 visitInstOperands(UO);
2814}
2815
2816void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2817 visitInstOperands(BO);
2818}
2819
2820void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2821 // Special case: if this is the bitcast (there is exactly 1 allowed) between
2822 // a musttail call and a ret, don't instrument. New instructions are not
2823 // allowed after a musttail call.
2824 if (auto *CI = dyn_cast<CallInst>(BCI.getOperand(0)))
2825 if (CI->isMustTailCall())
2826 return;
2827 visitInstOperands(BCI);
2828}
2829
2830void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
2831
2832void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2833 visitInstOperands(CI);
2834 if (ClEventCallbacks) {
2835 IRBuilder<> IRB(&CI);
2836 Value *CombinedShadow = DFSF.getShadow(&CI);
2837 CallInst *CallI =
2838 IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2839 CallI->maybeAddParamAttr(0,
2840 DFSF.TLI.getExtAttrForI8Param(/*Signed=*/false));
2841 }
2842}
2843
2844void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2845 // We do not need to track data through LandingPadInst.
2846 //
2847 // For the C++ exceptions, if a value is thrown, this value will be stored
2848 // in a memory location provided by __cxa_allocate_exception(...) (on the
2849 // throw side) or __cxa_begin_catch(...) (on the catch side).
2850 // This memory will have a shadow, so with the loads and stores we will be
2851 // able to propagate labels on data thrown through exceptions, without any
2852 // special handling of the LandingPadInst.
2853 //
2854 // The second element in the pair result of the LandingPadInst is a
2855 // register value, but it is for a type ID and should never be tainted.
2856 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2857 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2858}
2859
2860void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
2862 DFSF.isLookupTableConstant(
2864 visitInstOperands(GEPI);
2865 return;
2866 }
2867
2868 // Only propagate shadow/origin of base pointer value but ignore those of
2869 // offset operands.
2870 Value *BasePointer = GEPI.getPointerOperand();
2871 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2872 if (DFSF.DFS.shouldTrackOrigins())
2873 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2874}
2875
2876void DFSanVisitor::visitExtractElementInst(ExtractElementInst &I) {
2877 visitInstOperands(I);
2878}
2879
2880void DFSanVisitor::visitInsertElementInst(InsertElementInst &I) {
2881 visitInstOperands(I);
2882}
2883
2884void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &I) {
2885 visitInstOperands(I);
2886}
2887
2888void DFSanVisitor::visitExtractValueInst(ExtractValueInst &I) {
2889 IRBuilder<> IRB(&I);
2890 Value *Agg = I.getAggregateOperand();
2891 Value *AggShadow = DFSF.getShadow(Agg);
2892 Value *ResShadow = IRB.CreateExtractValue(AggShadow, I.getIndices());
2893 DFSF.setShadow(&I, ResShadow);
2894 visitInstOperandOrigins(I);
2895}
2896
2897void DFSanVisitor::visitInsertValueInst(InsertValueInst &I) {
2898 IRBuilder<> IRB(&I);
2899 Value *AggShadow = DFSF.getShadow(I.getAggregateOperand());
2900 Value *InsShadow = DFSF.getShadow(I.getInsertedValueOperand());
2901 Value *Res = IRB.CreateInsertValue(AggShadow, InsShadow, I.getIndices());
2902 DFSF.setShadow(&I, Res);
2903 visitInstOperandOrigins(I);
2904}
2905
2906void DFSanVisitor::visitAllocaInst(AllocaInst &I) {
2907 bool AllLoadsStores = true;
2908 for (User *U : I.users()) {
2909 if (isa<LoadInst>(U))
2910 continue;
2911
2912 if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
2913 if (SI->getPointerOperand() == &I)
2914 continue;
2915 }
2916
2917 AllLoadsStores = false;
2918 break;
2919 }
2920 if (AllLoadsStores) {
2921 IRBuilder<> IRB(&I);
2922 DFSF.AllocaShadowMap[&I] = IRB.CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2923 if (DFSF.DFS.shouldTrackOrigins()) {
2924 DFSF.AllocaOriginMap[&I] =
2925 IRB.CreateAlloca(DFSF.DFS.OriginTy, nullptr, "_dfsa");
2926 }
2927 }
2928 DFSF.setShadow(&I, DFSF.DFS.ZeroPrimitiveShadow);
2929 DFSF.setOrigin(&I, DFSF.DFS.ZeroOrigin);
2930}
2931
2932void DFSanVisitor::visitSelectInst(SelectInst &I) {
2933 Value *CondShadow = DFSF.getShadow(I.getCondition());
2934 Value *TrueShadow = DFSF.getShadow(I.getTrueValue());
2935 Value *FalseShadow = DFSF.getShadow(I.getFalseValue());
2936 Value *ShadowSel = nullptr;
2937 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2938 std::vector<Value *> Shadows;
2939 std::vector<Value *> Origins;
2940 Value *TrueOrigin =
2941 ShouldTrackOrigins ? DFSF.getOrigin(I.getTrueValue()) : nullptr;
2942 Value *FalseOrigin =
2943 ShouldTrackOrigins ? DFSF.getOrigin(I.getFalseValue()) : nullptr;
2944
2945 DFSF.addConditionalCallbacksIfEnabled(I, I.getCondition());
2946
2947 if (isa<VectorType>(I.getCondition()->getType())) {
2948 ShadowSel = DFSF.combineShadowsThenConvert(I.getType(), TrueShadow,
2949 FalseShadow, I.getIterator());
2950 if (ShouldTrackOrigins) {
2951 Shadows.push_back(TrueShadow);
2952 Shadows.push_back(FalseShadow);
2953 Origins.push_back(TrueOrigin);
2954 Origins.push_back(FalseOrigin);
2955 }
2956 } else {
2957 if (TrueShadow == FalseShadow) {
2958 ShadowSel = TrueShadow;
2959 if (ShouldTrackOrigins) {
2960 Shadows.push_back(TrueShadow);
2961 Origins.push_back(TrueOrigin);
2962 }
2963 } else {
2964 ShadowSel = SelectInst::Create(I.getCondition(), TrueShadow, FalseShadow,
2965 "", I.getIterator());
2966 if (ShouldTrackOrigins) {
2967 Shadows.push_back(ShadowSel);
2968 Origins.push_back(SelectInst::Create(I.getCondition(), TrueOrigin,
2969 FalseOrigin, "", I.getIterator()));
2970 }
2971 }
2972 }
2973 DFSF.setShadow(&I, ClTrackSelectControlFlow ? DFSF.combineShadowsThenConvert(
2974 I.getType(), CondShadow,
2975 ShadowSel, I.getIterator())
2976 : ShadowSel);
2977 if (ShouldTrackOrigins) {
2979 Shadows.push_back(CondShadow);
2980 Origins.push_back(DFSF.getOrigin(I.getCondition()));
2981 }
2982 DFSF.setOrigin(&I, DFSF.combineOrigins(Shadows, Origins, I.getIterator()));
2983 }
2984}
2985
2986void DFSanVisitor::visitMemSetInst(MemSetInst &I) {
2987 IRBuilder<> IRB(&I);
2988 Value *ValShadow = DFSF.getShadow(I.getValue());
2989 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2990 ? DFSF.getOrigin(I.getValue())
2991 : DFSF.DFS.ZeroOrigin;
2992 IRB.CreateCall(DFSF.DFS.DFSanSetLabelFn,
2993 {ValShadow, ValOrigin, I.getDest(),
2994 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2995}
2996
2997void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) {
2998 IRBuilder<> IRB(&I);
2999
3000 // CopyOrMoveOrigin transfers origins by refering to their shadows. So we
3001 // need to move origins before moving shadows.
3002 if (DFSF.DFS.shouldTrackOrigins()) {
3003 IRB.CreateCall(
3004 DFSF.DFS.DFSanMemOriginTransferFn,
3005 {I.getArgOperand(0), I.getArgOperand(1),
3006 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
3007 }
3008
3009 Value *DestShadow = DFSF.DFS.getShadowAddress(I.getDest(), I.getIterator());
3010 Value *SrcShadow = DFSF.DFS.getShadowAddress(I.getSource(), I.getIterator());
3011 Value *LenShadow =
3012 IRB.CreateMul(I.getLength(), ConstantInt::get(I.getLength()->getType(),
3013 DFSF.DFS.ShadowWidthBytes));
3014 auto *MTI = cast<MemTransferInst>(
3015 IRB.CreateCall(I.getFunctionType(), I.getCalledOperand(),
3016 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
3017 MTI->setDestAlignment(DFSF.getShadowAlign(I.getDestAlign().valueOrOne()));
3018 MTI->setSourceAlignment(DFSF.getShadowAlign(I.getSourceAlign().valueOrOne()));
3019 if (ClEventCallbacks) {
3020 IRB.CreateCall(
3021 DFSF.DFS.DFSanMemTransferCallbackFn,
3022 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
3023 }
3024}
3025
3026void DFSanVisitor::visitCondBrInst(CondBrInst &BR) {
3027 DFSF.addConditionalCallbacksIfEnabled(BR, BR.getCondition());
3028}
3029
3030void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
3031 DFSF.addConditionalCallbacksIfEnabled(SW, SW.getCondition());
3032}
3033
3034static bool isAMustTailRetVal(Value *RetVal) {
3035 // Tail call may have a bitcast between return.
3036 if (auto *I = dyn_cast<BitCastInst>(RetVal)) {
3037 RetVal = I->getOperand(0);
3038 }
3039 if (auto *I = dyn_cast<CallInst>(RetVal)) {
3040 return I->isMustTailCall();
3041 }
3042 return false;
3043}
3044
3045void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
3046 if (!DFSF.IsNativeABI && RI.getReturnValue()) {
3047 // Don't emit the instrumentation for musttail call returns.
3049 return;
3050
3051 Value *S = DFSF.getShadow(RI.getReturnValue());
3052 IRBuilder<> IRB(&RI);
3053 Type *RT = DFSF.F->getFunctionType()->getReturnType();
3054 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
3055 if (Size <= RetvalTLSSize) {
3056 // If the size overflows, stores nothing. At callsite, oversized return
3057 // shadows are set to zero.
3058 IRB.CreateAlignedStore(S, DFSF.getRetvalTLS(RT, IRB), ShadowTLSAlignment);
3059 }
3060 if (DFSF.DFS.shouldTrackOrigins()) {
3061 Value *O = DFSF.getOrigin(RI.getReturnValue());
3062 IRB.CreateStore(O, DFSF.getRetvalOriginTLS());
3063 }
3064 }
3065}
3066
3067void DFSanVisitor::addShadowArguments(Function &F, CallBase &CB,
3068 std::vector<Value *> &Args,
3069 IRBuilder<> &IRB) {
3070 FunctionType *FT = F.getFunctionType();
3071
3072 auto *I = CB.arg_begin();
3073
3074 // Adds non-variable argument shadows.
3075 for (unsigned N = FT->getNumParams(); N != 0; ++I, --N)
3076 Args.push_back(
3077 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*I), CB.getIterator()));
3078
3079 // Adds variable argument shadows.
3080 if (FT->isVarArg()) {
3081 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3082 CB.arg_size() - FT->getNumParams());
3083 auto *LabelVAAlloca =
3084 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3085 "labelva", DFSF.F->getEntryBlock().begin());
3086
3087 for (unsigned N = 0; I != CB.arg_end(); ++I, ++N) {
3088 auto *LabelVAPtr = IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, N);
3089 IRB.CreateStore(
3090 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*I), CB.getIterator()),
3091 LabelVAPtr);
3092 }
3093
3094 Args.push_back(IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, 0));
3095 }
3096
3097 // Adds the return value shadow.
3098 if (!FT->getReturnType()->isVoidTy()) {
3099 if (!DFSF.LabelReturnAlloca) {
3100 DFSF.LabelReturnAlloca = new AllocaInst(
3101 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3102 "labelreturn", DFSF.F->getEntryBlock().begin());
3103 }
3104 Args.push_back(DFSF.LabelReturnAlloca);
3105 }
3106}
3107
3108void DFSanVisitor::addOriginArguments(Function &F, CallBase &CB,
3109 std::vector<Value *> &Args,
3110 IRBuilder<> &IRB) {
3111 FunctionType *FT = F.getFunctionType();
3112
3113 auto *I = CB.arg_begin();
3114
3115 // Add non-variable argument origins.
3116 for (unsigned N = FT->getNumParams(); N != 0; ++I, --N)
3117 Args.push_back(DFSF.getOrigin(*I));
3118
3119 // Add variable argument origins.
3120 if (FT->isVarArg()) {
3121 auto *OriginVATy =
3122 ArrayType::get(DFSF.DFS.OriginTy, CB.arg_size() - FT->getNumParams());
3123 auto *OriginVAAlloca =
3124 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3125 "originva", DFSF.F->getEntryBlock().begin());
3126
3127 for (unsigned N = 0; I != CB.arg_end(); ++I, ++N) {
3128 auto *OriginVAPtr = IRB.CreateStructGEP(OriginVATy, OriginVAAlloca, N);
3129 IRB.CreateStore(DFSF.getOrigin(*I), OriginVAPtr);
3130 }
3131
3132 Args.push_back(IRB.CreateStructGEP(OriginVATy, OriginVAAlloca, 0));
3133 }
3134
3135 // Add the return value origin.
3136 if (!FT->getReturnType()->isVoidTy()) {
3137 if (!DFSF.OriginReturnAlloca) {
3138 DFSF.OriginReturnAlloca = new AllocaInst(
3139 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3140 "originreturn", DFSF.F->getEntryBlock().begin());
3141 }
3142 Args.push_back(DFSF.OriginReturnAlloca);
3143 }
3144}
3145
3146bool DFSanVisitor::visitWrappedCallBase(Function &F, CallBase &CB) {
3147 IRBuilder<> IRB(&CB);
3148 switch (DFSF.DFS.getWrapperKind(&F)) {
3149 case DataFlowSanitizer::WK_Warning:
3150 CB.setCalledFunction(&F);
3151 IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3152 IRB.CreateGlobalString(F.getName()));
3153 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3154 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3155 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3156 return true;
3157 case DataFlowSanitizer::WK_Discard:
3158 CB.setCalledFunction(&F);
3159 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3160 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3161 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3162 return true;
3163 case DataFlowSanitizer::WK_Functional:
3164 CB.setCalledFunction(&F);
3165 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3166 visitInstOperands(CB);
3167 return true;
3168 case DataFlowSanitizer::WK_Custom:
3169 // Don't try to handle invokes of custom functions, it's too complicated.
3170 // Instead, invoke the dfsw$ wrapper, which will in turn call the __dfsw_
3171 // wrapper.
3172 CallInst *CI = dyn_cast<CallInst>(&CB);
3173 if (!CI)
3174 return false;
3175
3176 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3177 FunctionType *FT = F.getFunctionType();
3178 TransformedFunction CustomFnTy =
3179 DFSF.DFS.getCustomFunctionType(FT, DFSF.TLI);
3180 std::string CustomFName = ShouldTrackOrigins ? "__dfso_" : "__dfsw_";
3181 CustomFName += F.getName();
3182 FunctionCallee CustomFunCallee = DFSF.DFS.Mod->getOrInsertFunction(
3183 CustomFName, CustomFnTy.TransformedType);
3184 if (Function *CustomFun = dyn_cast<Function>(CustomFunCallee.getCallee())) {
3185 // Strange things may occur here: F may have two i64 arguments while
3186 // getOrInsertFunction() returns a preexisting Function with those
3187 // (first) two args as i8:s. Make sure the extensions of those i8:s
3188 // survive copyAttributesFrom() and also add the extensions for the new
3189 // parameters.
3190 AttributeList CustomAL = CustomFun->getAttributes();
3191 CustomFun->copyAttributesFrom(&F);
3192 CustomFun->setAttributes(AttributeList::get(
3193 CI->getContext(),
3194 {CustomFun->getAttributes(), CustomAL, CustomFnTy.NewParamAttrs}));
3195
3196 // Custom functions returning non-void will write to the return label.
3197 if (!FT->getReturnType()->isVoidTy()) {
3198 CustomFun->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3199 }
3200 }
3201
3202 std::vector<Value *> Args;
3203
3204 // Adds non-variable arguments.
3205 auto *I = CB.arg_begin();
3206 for (unsigned N = FT->getNumParams(); N != 0; ++I, --N) {
3207 Args.push_back(*I);
3208 }
3209
3210 // Adds shadow arguments.
3211 addShadowArguments(F, CB, Args, IRB);
3212
3213 // Adds origin arguments.
3214 if (ShouldTrackOrigins)
3215 addOriginArguments(F, CB, Args, IRB);
3216
3217 // Adds variable arguments.
3218 append_range(Args, drop_begin(CB.args(), FT->getNumParams()));
3219
3220 CallInst *CustomCI = IRB.CreateCall(CustomFunCallee, Args);
3221 CustomCI->setCallingConv(CI->getCallingConv());
3222 // Add attributes to the parameters from the original call and Function
3223 // and as well those needed for the new parameters.
3224 CustomCI->setAttributes(AttributeList::get(
3225 CI->getContext(),
3226 {transformFunctionAttributes(CustomFnTy, CI->getContext(),
3227 CI->getAttributes()),
3228 F.getAttributes(), CustomFnTy.NewParamAttrs}));
3229
3230 // Loads the return value shadow and origin.
3231 if (!FT->getReturnType()->isVoidTy()) {
3232 LoadInst *LabelLoad =
3233 IRB.CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3234 DFSF.setShadow(CustomCI,
3235 DFSF.expandFromPrimitiveShadow(
3236 FT->getReturnType(), LabelLoad, CB.getIterator()));
3237 if (ShouldTrackOrigins) {
3238 LoadInst *OriginLoad =
3239 IRB.CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3240 DFSF.setOrigin(CustomCI, OriginLoad);
3241 }
3242 }
3243
3244 CI->replaceAllUsesWith(CustomCI);
3245 CI->eraseFromParent();
3246 return true;
3247 }
3248 return false;
3249}
3250
3251Value *DFSanVisitor::makeAddAcquireOrderingTable(IRBuilder<> &IRB) {
3252 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3253 uint32_t OrderingTable[NumOrderings] = {};
3254
3255 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3256 OrderingTable[(int)AtomicOrderingCABI::acquire] =
3257 OrderingTable[(int)AtomicOrderingCABI::consume] =
3258 (int)AtomicOrderingCABI::acquire;
3259 OrderingTable[(int)AtomicOrderingCABI::release] =
3260 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3261 (int)AtomicOrderingCABI::acq_rel;
3262 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3263 (int)AtomicOrderingCABI::seq_cst;
3264
3265 return ConstantDataVector::get(IRB.getContext(), OrderingTable);
3266}
3267
3268void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3269 // Since we use getNextNode here, we can't have CB terminate the BB.
3270 assert(isa<CallInst>(CB));
3271
3272 IRBuilder<> IRB(&CB);
3273 Value *Size = CB.getArgOperand(0);
3274 Value *SrcPtr = CB.getArgOperand(1);
3275 Value *DstPtr = CB.getArgOperand(2);
3276 Value *Ordering = CB.getArgOperand(3);
3277 // Convert the call to have at least Acquire ordering to make sure
3278 // the shadow operations aren't reordered before it.
3279 Value *NewOrdering =
3280 IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);
3281 CB.setArgOperand(3, NewOrdering);
3282
3283 IRBuilder<> NextIRB(CB.getNextNode());
3284 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
3285
3286 // TODO: Support ClCombinePointerLabelsOnLoad
3287 // TODO: Support ClEventCallbacks
3288
3289 NextIRB.CreateCall(
3290 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3291 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3292}
3293
3294Value *DFSanVisitor::makeAddReleaseOrderingTable(IRBuilder<> &IRB) {
3295 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3296 uint32_t OrderingTable[NumOrderings] = {};
3297
3298 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3299 OrderingTable[(int)AtomicOrderingCABI::release] =
3300 (int)AtomicOrderingCABI::release;
3301 OrderingTable[(int)AtomicOrderingCABI::consume] =
3302 OrderingTable[(int)AtomicOrderingCABI::acquire] =
3303 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3304 (int)AtomicOrderingCABI::acq_rel;
3305 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3306 (int)AtomicOrderingCABI::seq_cst;
3307
3308 return ConstantDataVector::get(IRB.getContext(), OrderingTable);
3309}
3310
3311void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3312 IRBuilder<> IRB(&CB);
3313 Value *Size = CB.getArgOperand(0);
3314 Value *SrcPtr = CB.getArgOperand(1);
3315 Value *DstPtr = CB.getArgOperand(2);
3316 Value *Ordering = CB.getArgOperand(3);
3317 // Convert the call to have at least Release ordering to make sure
3318 // the shadow operations aren't reordered after it.
3319 Value *NewOrdering =
3320 IRB.CreateExtractElement(makeAddReleaseOrderingTable(IRB), Ordering);
3321 CB.setArgOperand(3, NewOrdering);
3322
3323 // TODO: Support ClCombinePointerLabelsOnStore
3324 // TODO: Support ClEventCallbacks
3325
3326 IRB.CreateCall(
3327 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3328 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3329}
3330
3331void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3332 // void __atomic_exchange(size_t size, void *ptr, void *val, void *ret, int
3333 // ordering)
3334 IRBuilder<> IRB(&CB);
3335 Value *Size = CB.getArgOperand(0);
3336 Value *TargetPtr = CB.getArgOperand(1);
3337 Value *SrcPtr = CB.getArgOperand(2);
3338 Value *DstPtr = CB.getArgOperand(3);
3339
3340 // This operation is not atomic for the shadow and origin memory.
3341 // This could result in DFSan false positives or false negatives.
3342 // For now we will assume these operations are rare, and
3343 // the additional complexity to address this is not warrented.
3344
3345 // Current Target to Dest
3346 IRB.CreateCall(
3347 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3348 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3349
3350 // Current Src to Target (overriding)
3351 IRB.CreateCall(
3352 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3353 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3354}
3355
3356void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3357 // bool __atomic_compare_exchange(size_t size, void *ptr, void *expected, void
3358 // *desired, int success_order, int failure_order)
3359 Value *Size = CB.getArgOperand(0);
3360 Value *TargetPtr = CB.getArgOperand(1);
3361 Value *ExpectedPtr = CB.getArgOperand(2);
3362 Value *DesiredPtr = CB.getArgOperand(3);
3363
3364 // This operation is not atomic for the shadow and origin memory.
3365 // This could result in DFSan false positives or false negatives.
3366 // For now we will assume these operations are rare, and
3367 // the additional complexity to address this is not warrented.
3368
3369 IRBuilder<> NextIRB(CB.getNextNode());
3370 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
3371
3372 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3373
3374 // If original call returned true, copy Desired to Target.
3375 // If original call returned false, copy Target to Expected.
3376 CallInst *CI = NextIRB.CreateCall(
3377 DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3378 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false), TargetPtr,
3379 ExpectedPtr, DesiredPtr,
3380 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3381 CI->maybeAddParamAttr(0, DFSF.TLI.getExtAttrForI8Param(/*Signed=*/false));
3382}
3383
3384void DFSanVisitor::visitCallBase(CallBase &CB) {
3386 if ((F && F->isIntrinsic()) || CB.isInlineAsm()) {
3387 visitInstOperands(CB);
3388 return;
3389 }
3390
3391 // Calls to this function are synthesized in wrappers, and we shouldn't
3392 // instrument them.
3393 if (F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3394 return;
3395
3396 LibFunc LF = DFSF.TLI.getLibFunc(CB);
3397 if (LF != NotLibFunc) {
3398 // libatomic.a functions need to have special handling because there isn't
3399 // a good way to intercept them or compile the library with
3400 // instrumentation.
3401 switch (LF) {
3402 case LibFunc_atomic_load:
3403 if (!isa<CallInst>(CB)) {
3404 llvm::errs() << "DFSAN -- cannot instrument invoke of libatomic load. "
3405 "Ignoring!\n";
3406 break;
3407 }
3408 visitLibAtomicLoad(CB);
3409 return;
3410 case LibFunc_atomic_store:
3411 visitLibAtomicStore(CB);
3412 return;
3413 default:
3414 break;
3415 }
3416 }
3417
3418 // TODO: These are not supported by TLI? They are not in the enum.
3419 if (F && F->hasName() && !F->isVarArg()) {
3420 if (F->getName() == "__atomic_exchange") {
3421 visitLibAtomicExchange(CB);
3422 return;
3423 }
3424 if (F->getName() == "__atomic_compare_exchange") {
3425 visitLibAtomicCompareExchange(CB);
3426 return;
3427 }
3428 }
3429
3430 auto UnwrappedFnIt = DFSF.DFS.UnwrappedFnMap.find(CB.getCalledOperand());
3431 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3432 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3433 return;
3434
3435 IRBuilder<> IRB(&CB);
3436
3437 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3438 FunctionType *FT = CB.getFunctionType();
3439 const DataLayout &DL = getDataLayout();
3440
3441 // Stores argument shadows.
3442 unsigned ArgOffset = 0;
3443 for (unsigned I = 0, N = FT->getNumParams(); I != N; ++I) {
3444 if (ShouldTrackOrigins) {
3445 // Ignore overflowed origins
3446 Value *ArgShadow = DFSF.getShadow(CB.getArgOperand(I));
3447 if (I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3448 !DFSF.DFS.isZeroShadow(ArgShadow))
3449 IRB.CreateStore(DFSF.getOrigin(CB.getArgOperand(I)),
3450 DFSF.getArgOriginTLS(I, IRB));
3451 }
3452
3453 unsigned Size =
3454 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(I)));
3455 // Stop storing if arguments' size overflows. Inside a function, arguments
3456 // after overflow have zero shadow values.
3457 if (ArgOffset + Size > ArgTLSSize)
3458 break;
3459 IRB.CreateAlignedStore(DFSF.getShadow(CB.getArgOperand(I)),
3460 DFSF.getArgTLS(FT->getParamType(I), ArgOffset, IRB),
3462 ArgOffset += alignTo(Size, ShadowTLSAlignment);
3463 }
3464
3465 Instruction *Next = nullptr;
3466 if (!CB.getType()->isVoidTy()) {
3467 if (InvokeInst *II = dyn_cast<InvokeInst>(&CB)) {
3468 if (II->getNormalDest()->getSinglePredecessor()) {
3469 Next = &II->getNormalDest()->front();
3470 } else {
3471 BasicBlock *NewBB =
3472 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
3473 Next = &NewBB->front();
3474 }
3475 } else {
3476 assert(CB.getIterator() != CB.getParent()->end());
3477 Next = CB.getNextNode();
3478 }
3479
3480 // Don't emit the epilogue for musttail call returns.
3481 if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3482 return;
3483
3484 // Loads the return value shadow.
3485 IRBuilder<> NextIRB(Next);
3486 unsigned Size = DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3487 if (Size > RetvalTLSSize) {
3488 // Set overflowed return shadow to be zero.
3489 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3490 } else {
3491 LoadInst *LI = NextIRB.CreateAlignedLoad(
3492 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.getType(), NextIRB),
3493 ShadowTLSAlignment, "_dfsret");
3494 DFSF.SkipInsts.insert(LI);
3495 DFSF.setShadow(&CB, LI);
3496 DFSF.NonZeroChecks.push_back(LI);
3497 }
3498
3499 if (ShouldTrackOrigins) {
3500 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3501 DFSF.getRetvalOriginTLS(), "_dfsret_o");
3502 DFSF.SkipInsts.insert(LI);
3503 DFSF.setOrigin(&CB, LI);
3504 }
3505
3506 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3507 }
3508}
3509
3510void DFSanVisitor::visitPHINode(PHINode &PN) {
3511 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3512 PHINode *ShadowPN = PHINode::Create(ShadowTy, PN.getNumIncomingValues(), "",
3513 PN.getIterator());
3514
3515 // Give the shadow phi node valid predecessors to fool SplitEdge into working.
3516 Value *PoisonShadow = PoisonValue::get(ShadowTy);
3517 for (BasicBlock *BB : PN.blocks())
3518 ShadowPN->addIncoming(PoisonShadow, BB);
3519
3520 DFSF.setShadow(&PN, ShadowPN);
3521
3522 PHINode *OriginPN = nullptr;
3523 if (DFSF.DFS.shouldTrackOrigins()) {
3524 OriginPN = PHINode::Create(DFSF.DFS.OriginTy, PN.getNumIncomingValues(), "",
3525 PN.getIterator());
3526 Value *PoisonOrigin = PoisonValue::get(DFSF.DFS.OriginTy);
3527 for (BasicBlock *BB : PN.blocks())
3528 OriginPN->addIncoming(PoisonOrigin, BB);
3529 DFSF.setOrigin(&PN, OriginPN);
3530 }
3531
3532 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3533}
3534
3537 // Return early if nosanitize_dataflow module flag is present for the module.
3538 if (checkIfAlreadyInstrumented(M, "nosanitize_dataflow"))
3539 return PreservedAnalyses::all();
3540 auto GetTLI = [&](Function &F) -> TargetLibraryInfo & {
3541 auto &FAM =
3543 return FAM.getResult<TargetLibraryAnalysis>(F);
3544 };
3545 if (!DataFlowSanitizer(ABIListFiles, FS).runImpl(M, GetTLI))
3546 return PreservedAnalyses::all();
3547
3549 // GlobalsAA is considered stateless and does not get invalidated unless
3550 // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
3551 // make changes that require GlobalsAA to be invalidated.
3552 PA.abandon<GlobalsAA>();
3553 return PA;
3554}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static bool isConstant(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool runImpl(MachineFunction &MF)
Definition CFIFixup.cpp:304
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
static cl::opt< bool > ClAddGlobalNameSuffix("dfsan-add-global-name-suffix", cl::desc("Whether to add .dfsan suffix to global names"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClTrackSelectControlFlow("dfsan-track-select-control-flow", cl::desc("Propagate labels from condition values of select instructions " "to results."), cl::Hidden, cl::init(true))
static cl::list< std::string > ClCombineTaintLookupTables("dfsan-combine-taint-lookup-table", cl::desc("When dfsan-combine-offset-labels-on-gep and/or " "dfsan-combine-pointer-labels-on-load are false, this flag can " "be used to re-enable combining offset and/or pointer taint when " "loading specific constant global variables (i.e. lookup tables)."), cl::Hidden)
static const Align MinOriginAlignment
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
static cl::list< std::string > ClABIListFiles("dfsan-abilist", cl::desc("File listing native ABI functions and how the pass treats them"), cl::Hidden)
static cl::opt< bool > ClReachesFunctionCallbacks("dfsan-reaches-function-callbacks", cl::desc("Insert calls to callback functions on data reaching a function."), cl::Hidden, cl::init(false))
static Value * expandFromPrimitiveShadowRecursive(Value *Shadow, SmallVector< unsigned, 4 > &Indices, Type *SubShadowTy, Value *PrimitiveShadow, IRBuilder<> &IRB)
static cl::opt< int > ClInstrumentWithCallThreshold("dfsan-instrument-with-call-threshold", cl::desc("If the function being instrumented requires more than " "this number of origin stores, use callbacks instead of " "inline checks (-1 means never use callbacks)."), cl::Hidden, cl::init(3500))
static cl::opt< bool > ClPreserveAlignment("dfsan-preserve-alignment", cl::desc("respect alignment requirements provided by input IR"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClDebugNonzeroLabels("dfsan-debug-nonzero-labels", cl::desc("Insert calls to __dfsan_nonzero_label on observing a parameter, " "load or return with a nonzero label"), cl::Hidden)
static cl::opt< bool > ClCombineOffsetLabelsOnGEP("dfsan-combine-offset-labels-on-gep", cl::desc("Combine the label of the offset with the label of the pointer when " "doing pointer arithmetic."), cl::Hidden, cl::init(true))
static cl::opt< bool > ClIgnorePersonalityRoutine("dfsan-ignore-personality-routine", cl::desc("If a personality routine is marked uninstrumented from the ABI " "list, do not create a wrapper for it."), cl::Hidden, cl::init(false))
static const Align ShadowTLSAlignment
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_S390X_MemoryMapParams
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
Value * StripPointerGEPsAndCasts(Value *V)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static cl::opt< bool > ClConditionalCallbacks("dfsan-conditional-callbacks", cl::desc("Insert calls to callback functions on conditionals."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClCombinePointerLabelsOnLoad("dfsan-combine-pointer-labels-on-load", cl::desc("Combine the label of the pointer with the label of the data when " "loading from memory."), cl::Hidden, cl::init(true))
static StringRef getGlobalTypeString(const GlobalValue &G)
static cl::opt< bool > ClCombinePointerLabelsOnStore("dfsan-combine-pointer-labels-on-store", cl::desc("Combine the label of the pointer with the label of the data when " "storing in memory."), cl::Hidden, cl::init(false))
static const unsigned ArgTLSSize
static const unsigned RetvalTLSSize
static bool isAMustTailRetVal(Value *RetVal)
static cl::opt< bool > ClEventCallbacks("dfsan-event-callbacks", cl::desc("Insert calls to __dfsan_*_callback functions on data events."), cl::Hidden, cl::init(false))
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
This is the interface for a simple mod/ref and alias analysis over globals.
Hexagon Common GEP
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
Machine Check Debug Module
#define T
nvptx lower args
uint64_t IntrinsicInst * II
#define P(N)
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
StringSet - A set-like wrapper for the StringMap.
Defines the virtual file system interface vfs::FileSystem.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:446
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
const Instruction & front() const
Definition BasicBlock.h:469
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
bool isInlineAsm() const
Check if this call is an inline asm statement.
void setCallingConv(CallingConv::ID CC)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
void maybeAddParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
void addRetAttr(Attribute::AttrKind Kind)
Adds the attribute to the return value.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
bool isMustTailCall() const
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
static LLVM_ABI Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with vector type with an element count and element type matchi...
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
Definition Constants.h:135
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition Constant.h:64
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI unsigned getLine() const
Definition DebugLoc.cpp:43
DILocation * get() const
Get the underlying DILocation.
Definition DebugLoc.h:220
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:778
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:782
iterator end()
Definition DenseMap.h:702
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
Type * getReturnType() const
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:169
const BasicBlock & getEntryBlock() const
Definition Function.h:794
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
void removeFnAttrs(const AttributeMask &Attrs)
Definition Function.cpp:696
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:329
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition Function.cpp:688
arg_iterator arg_begin()
Definition Function.h:853
void removeRetAttrs(const AttributeMask &Attrs)
removes the attributes from the return value list of attributes.
Definition Function.cpp:708
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Definition Function.cpp:845
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:722
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:730
static bool isExternalWeakLinkage(LinkageTypes Linkage)
LinkageTypes getLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LinkageTypes
An enumeration for the kinds of linkage for global values.
Definition GlobalValue.h:52
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition GlobalValue.h:56
Type * getValueType() const
Analysis pass providing a never-invalidated alias analysis result.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2661
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Definition IRBuilder.h:2016
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Definition IRBuilder.h:1871
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2715
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2649
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Definition IRBuilder.h:1926
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2289
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2708
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
Definition IRBuilder.h:176
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Definition IRBuilder.h:2077
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2230
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1519
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2084
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Definition IRBuilder.h:518
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2378
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2003
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1898
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1498
LLVMContext & getContext() const
Definition IRBuilder.h:177
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1557
Value * CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
Definition IRBuilder.h:2068
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition IRBuilder.h:1917
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1409
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2553
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Definition IRBuilder.h:2099
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Definition IRBuilder.h:2315
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Definition IRBuilder.h:1945
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1609
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1579
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1443
LLVM_ABI GlobalVariable * CreateGlobalString(StringRef Str, const Twine &Name="", unsigned AddressSpace=0, Module *M=nullptr, bool AddNull=true)
Make a new global variable with initializer type i8*.
Definition IRBuilder.cpp:45
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2901
Base class for instruction visitors.
Definition InstVisitor.h:78
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
bool isTerminator() const
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
void setAlignment(Align Align)
Value * getPointerOperand()
void setOrdering(AtomicOrdering Ordering)
Sets the ordering constraint of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MemoryEffectsBase readOnly()
Definition ModRef.h:133
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
Definition Module.cpp:211
ArrayRef< GlobalAsmFragment > getModuleInlineAsm() const
Get any module-scope inline assembly blocks.
Definition Module.h:335
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
Definition Operator.h:43
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
iterator_range< const_block_iterator > blocks() const
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
Definition Analysis.h:171
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS)
Parses the special case list entries from files.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition StringMap.h:275
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
void insert_range(Range &&R)
Definition StringSet.h:49
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:467
Value * getCondition() const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
static Attribute::AttrKind getExtAttrForI8Param(bool Signed=true)
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
@ loongarch64
Definition Triple.h:66
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getIntegerBitWidth() const
bool isSized() const
Return true if it makes sense to take the size of this type.
Definition Type.h:321
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:712
bool hasName() const
Definition Value.h:263
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BR
Control flow instructions. These all have token chains.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
bool includes(R1 &&Range1, R2 &&Range2)
Provide wrappers to std::includes which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:2008
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
Definition Local.cpp:2912
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
Definition STLExtras.h:2216
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
Definition Alignment.h:100
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
iterator_range< df_iterator< T > > depth_first(const T &G)
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
LLVM_ABI BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77