xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- DataFlowSanitizer.cpp - dynamic data flow analysis -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file is a part of DataFlowSanitizer, a generalised dynamic data flow
110b57cec5SDimitry Andric /// analysis.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric /// Unlike other Sanitizer tools, this tool is not designed to detect a specific
140b57cec5SDimitry Andric /// class of bugs on its own.  Instead, it provides a generic dynamic data flow
150b57cec5SDimitry Andric /// analysis framework to be used by clients to help detect application-specific
160b57cec5SDimitry Andric /// issues within their own code.
170b57cec5SDimitry Andric ///
180b57cec5SDimitry Andric /// The analysis is based on automatic propagation of data flow labels (also
19fe6060f1SDimitry Andric /// known as taint labels) through a program as it performs computation.
20fe6060f1SDimitry Andric ///
21349cc55cSDimitry Andric /// Argument and return value labels are passed through TLS variables
22349cc55cSDimitry Andric /// __dfsan_arg_tls and __dfsan_retval_tls.
23349cc55cSDimitry Andric ///
24fe6060f1SDimitry Andric /// Each byte of application memory is backed by a shadow memory byte. The
25fe6060f1SDimitry Andric /// shadow byte can represent up to 8 labels. On Linux/x86_64, memory is then
26fe6060f1SDimitry Andric /// laid out as follows:
270b57cec5SDimitry Andric ///
280b57cec5SDimitry Andric /// +--------------------+ 0x800000000000 (top of memory)
29fe6060f1SDimitry Andric /// |    application 3   |
30fe6060f1SDimitry Andric /// +--------------------+ 0x700000000000
31fe6060f1SDimitry Andric /// |      invalid       |
32fe6060f1SDimitry Andric /// +--------------------+ 0x610000000000
33fe6060f1SDimitry Andric /// |      origin 1      |
34fe6060f1SDimitry Andric /// +--------------------+ 0x600000000000
35fe6060f1SDimitry Andric /// |    application 2   |
36fe6060f1SDimitry Andric /// +--------------------+ 0x510000000000
37fe6060f1SDimitry Andric /// |      shadow 1      |
38fe6060f1SDimitry Andric /// +--------------------+ 0x500000000000
39fe6060f1SDimitry Andric /// |      invalid       |
40fe6060f1SDimitry Andric /// +--------------------+ 0x400000000000
41fe6060f1SDimitry Andric /// |      origin 3      |
42fe6060f1SDimitry Andric /// +--------------------+ 0x300000000000
43fe6060f1SDimitry Andric /// |      shadow 3      |
44fe6060f1SDimitry Andric /// +--------------------+ 0x200000000000
45fe6060f1SDimitry Andric /// |      origin 2      |
46fe6060f1SDimitry Andric /// +--------------------+ 0x110000000000
47fe6060f1SDimitry Andric /// |      invalid       |
48fe6060f1SDimitry Andric /// +--------------------+ 0x100000000000
49fe6060f1SDimitry Andric /// |      shadow 2      |
50fe6060f1SDimitry Andric /// +--------------------+ 0x010000000000
51fe6060f1SDimitry Andric /// |    application 1   |
520b57cec5SDimitry Andric /// +--------------------+ 0x000000000000
530b57cec5SDimitry Andric ///
54fe6060f1SDimitry Andric /// MEM_TO_SHADOW(mem) = mem ^ 0x500000000000
55fe6060f1SDimitry Andric /// SHADOW_TO_ORIGIN(shadow) = shadow + 0x100000000000
560b57cec5SDimitry Andric ///
570b57cec5SDimitry Andric /// For more information, please refer to the design document:
580b57cec5SDimitry Andric /// http://clang.llvm.org/docs/DataFlowSanitizerDesign.html
590b57cec5SDimitry Andric //
600b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
610b57cec5SDimitry Andric 
62e8d8bef9SDimitry Andric #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
630b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
640b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
650b57cec5SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
660b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
670b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
680b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
6981ad6265SDimitry Andric #include "llvm/ADT/StringSet.h"
70fe6060f1SDimitry Andric #include "llvm/ADT/iterator.h"
7106c3fb27SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h"
72bdd1243dSDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
73bdd1243dSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
740b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
750b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
7606c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h"
770b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
780b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
790b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
800b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
810b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
820b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
830b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
840b57cec5SDimitry Andric #include "llvm/IR/Function.h"
850b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
860b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
870b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
880b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
890b57cec5SDimitry Andric #include "llvm/IR/InstVisitor.h"
900b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
910b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
920b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
930b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
940b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h"
950b57cec5SDimitry Andric #include "llvm/IR/Module.h"
96e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h"
970b57cec5SDimitry Andric #include "llvm/IR/Type.h"
980b57cec5SDimitry Andric #include "llvm/IR/User.h"
990b57cec5SDimitry Andric #include "llvm/IR/Value.h"
100fe6060f1SDimitry Andric #include "llvm/Support/Alignment.h"
1010b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
1020b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
1030b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1040b57cec5SDimitry Andric #include "llvm/Support/SpecialCaseList.h"
105480093f4SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
10606c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
1070b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation.h"
1080b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
109480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
1100b57cec5SDimitry Andric #include <algorithm>
1110b57cec5SDimitry Andric #include <cassert>
1120b57cec5SDimitry Andric #include <cstddef>
1130b57cec5SDimitry Andric #include <cstdint>
1140b57cec5SDimitry Andric #include <memory>
1150b57cec5SDimitry Andric #include <set>
1160b57cec5SDimitry Andric #include <string>
1170b57cec5SDimitry Andric #include <utility>
1180b57cec5SDimitry Andric #include <vector>
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric using namespace llvm;
1210b57cec5SDimitry Andric 
122e8d8bef9SDimitry Andric // This must be consistent with ShadowWidthBits.
123fe6060f1SDimitry Andric static const Align ShadowTLSAlignment = Align(2);
124fe6060f1SDimitry Andric 
125fe6060f1SDimitry Andric static const Align MinOriginAlignment = Align(4);
126e8d8bef9SDimitry Andric 
127e8d8bef9SDimitry Andric // The size of TLS variables. These constants must be kept in sync with the ones
128e8d8bef9SDimitry Andric // in dfsan.cpp.
129fe6060f1SDimitry Andric static const unsigned ArgTLSSize = 800;
130fe6060f1SDimitry Andric static const unsigned RetvalTLSSize = 800;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric // The -dfsan-preserve-alignment flag controls whether this pass assumes that
1330b57cec5SDimitry Andric // alignment requirements provided by the input IR are correct.  For example,
1340b57cec5SDimitry Andric // if the input IR contains a load with alignment 8, this flag will cause
1350b57cec5SDimitry Andric // the shadow load to have alignment 16.  This flag is disabled by default as
1360b57cec5SDimitry Andric // we have unfortunately encountered too much code (including Clang itself;
1370b57cec5SDimitry Andric // see PR14291) which performs misaligned access.
1380b57cec5SDimitry Andric static cl::opt<bool> ClPreserveAlignment(
1390b57cec5SDimitry Andric     "dfsan-preserve-alignment",
1400b57cec5SDimitry Andric     cl::desc("respect alignment requirements provided by input IR"), cl::Hidden,
1410b57cec5SDimitry Andric     cl::init(false));
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric // The ABI list files control how shadow parameters are passed. The pass treats
1440b57cec5SDimitry Andric // every function labelled "uninstrumented" in the ABI list file as conforming
1450b57cec5SDimitry Andric // to the "native" (i.e. unsanitized) ABI.  Unless the ABI list contains
1460b57cec5SDimitry Andric // additional annotations for those functions, a call to one of those functions
1470b57cec5SDimitry Andric // will produce a warning message, as the labelling behaviour of the function is
148349cc55cSDimitry Andric // unknown. The other supported annotations for uninstrumented functions are
149349cc55cSDimitry Andric // "functional" and "discard", which are described below under
150349cc55cSDimitry Andric // DataFlowSanitizer::WrapperKind.
151349cc55cSDimitry Andric // Functions will often be labelled with both "uninstrumented" and one of
152349cc55cSDimitry Andric // "functional" or "discard". This will leave the function unchanged by this
153349cc55cSDimitry Andric // pass, and create a wrapper function that will call the original.
154349cc55cSDimitry Andric //
155349cc55cSDimitry Andric // Instrumented functions can also be annotated as "force_zero_labels", which
156349cc55cSDimitry Andric // will make all shadow and return values set zero labels.
157349cc55cSDimitry Andric // Functions should never be labelled with both "force_zero_labels" and
158349cc55cSDimitry Andric // "uninstrumented" or any of the unistrumented wrapper kinds.
1590b57cec5SDimitry Andric static cl::list<std::string> ClABIListFiles(
1600b57cec5SDimitry Andric     "dfsan-abilist",
1610b57cec5SDimitry Andric     cl::desc("File listing native ABI functions and how the pass treats them"),
1620b57cec5SDimitry Andric     cl::Hidden);
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric // Controls whether the pass includes or ignores the labels of pointers in load
1650b57cec5SDimitry Andric // instructions.
1660b57cec5SDimitry Andric static cl::opt<bool> ClCombinePointerLabelsOnLoad(
1670b57cec5SDimitry Andric     "dfsan-combine-pointer-labels-on-load",
1680b57cec5SDimitry Andric     cl::desc("Combine the label of the pointer with the label of the data when "
1690b57cec5SDimitry Andric              "loading from memory."),
1700b57cec5SDimitry Andric     cl::Hidden, cl::init(true));
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric // Controls whether the pass includes or ignores the labels of pointers in
1730b57cec5SDimitry Andric // stores instructions.
1740b57cec5SDimitry Andric static cl::opt<bool> ClCombinePointerLabelsOnStore(
1750b57cec5SDimitry Andric     "dfsan-combine-pointer-labels-on-store",
1760b57cec5SDimitry Andric     cl::desc("Combine the label of the pointer with the label of the data when "
1770b57cec5SDimitry Andric              "storing in memory."),
1780b57cec5SDimitry Andric     cl::Hidden, cl::init(false));
1790b57cec5SDimitry Andric 
180fe6060f1SDimitry Andric // Controls whether the pass propagates labels of offsets in GEP instructions.
181fe6060f1SDimitry Andric static cl::opt<bool> ClCombineOffsetLabelsOnGEP(
182fe6060f1SDimitry Andric     "dfsan-combine-offset-labels-on-gep",
183fe6060f1SDimitry Andric     cl::desc(
184fe6060f1SDimitry Andric         "Combine the label of the offset with the label of the pointer when "
185fe6060f1SDimitry Andric         "doing pointer arithmetic."),
186fe6060f1SDimitry Andric     cl::Hidden, cl::init(true));
187fe6060f1SDimitry Andric 
18881ad6265SDimitry Andric static cl::list<std::string> ClCombineTaintLookupTables(
18981ad6265SDimitry Andric     "dfsan-combine-taint-lookup-table",
19081ad6265SDimitry Andric     cl::desc(
19181ad6265SDimitry Andric         "When dfsan-combine-offset-labels-on-gep and/or "
19281ad6265SDimitry Andric         "dfsan-combine-pointer-labels-on-load are false, this flag can "
19381ad6265SDimitry Andric         "be used to re-enable combining offset and/or pointer taint when "
19481ad6265SDimitry Andric         "loading specific constant global variables (i.e. lookup tables)."),
19581ad6265SDimitry Andric     cl::Hidden);
19681ad6265SDimitry Andric 
1970b57cec5SDimitry Andric static cl::opt<bool> ClDebugNonzeroLabels(
1980b57cec5SDimitry Andric     "dfsan-debug-nonzero-labels",
1990b57cec5SDimitry Andric     cl::desc("Insert calls to __dfsan_nonzero_label on observing a parameter, "
2000b57cec5SDimitry Andric              "load or return with a nonzero label"),
2010b57cec5SDimitry Andric     cl::Hidden);
2020b57cec5SDimitry Andric 
2035ffd83dbSDimitry Andric // Experimental feature that inserts callbacks for certain data events.
2045ffd83dbSDimitry Andric // Currently callbacks are only inserted for loads, stores, memory transfers
2055ffd83dbSDimitry Andric // (i.e. memcpy and memmove), and comparisons.
2065ffd83dbSDimitry Andric //
2075ffd83dbSDimitry Andric // If this flag is set to true, the user must provide definitions for the
2085ffd83dbSDimitry Andric // following callback functions:
209e8d8bef9SDimitry Andric //   void __dfsan_load_callback(dfsan_label Label, void* addr);
210e8d8bef9SDimitry Andric //   void __dfsan_store_callback(dfsan_label Label, void* addr);
2115ffd83dbSDimitry Andric //   void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len);
2125ffd83dbSDimitry Andric //   void __dfsan_cmp_callback(dfsan_label CombinedLabel);
2135ffd83dbSDimitry Andric static cl::opt<bool> ClEventCallbacks(
2145ffd83dbSDimitry Andric     "dfsan-event-callbacks",
2155ffd83dbSDimitry Andric     cl::desc("Insert calls to __dfsan_*_callback functions on data events."),
2165ffd83dbSDimitry Andric     cl::Hidden, cl::init(false));
2175ffd83dbSDimitry Andric 
21804eeddc0SDimitry Andric // Experimental feature that inserts callbacks for conditionals, including:
21904eeddc0SDimitry Andric // conditional branch, switch, select.
22004eeddc0SDimitry Andric // This must be true for dfsan_set_conditional_callback() to have effect.
22104eeddc0SDimitry Andric static cl::opt<bool> ClConditionalCallbacks(
22204eeddc0SDimitry Andric     "dfsan-conditional-callbacks",
22304eeddc0SDimitry Andric     cl::desc("Insert calls to callback functions on conditionals."), cl::Hidden,
22404eeddc0SDimitry Andric     cl::init(false));
22504eeddc0SDimitry Andric 
226bdd1243dSDimitry Andric // Experimental feature that inserts callbacks for data reaching a function,
227bdd1243dSDimitry Andric // either via function arguments and loads.
228bdd1243dSDimitry Andric // This must be true for dfsan_set_reaches_function_callback() to have effect.
229bdd1243dSDimitry Andric static cl::opt<bool> ClReachesFunctionCallbacks(
230bdd1243dSDimitry Andric     "dfsan-reaches-function-callbacks",
231bdd1243dSDimitry Andric     cl::desc("Insert calls to callback functions on data reaching a function."),
232bdd1243dSDimitry Andric     cl::Hidden, cl::init(false));
233bdd1243dSDimitry Andric 
234e8d8bef9SDimitry Andric // Controls whether the pass tracks the control flow of select instructions.
235e8d8bef9SDimitry Andric static cl::opt<bool> ClTrackSelectControlFlow(
236e8d8bef9SDimitry Andric     "dfsan-track-select-control-flow",
237e8d8bef9SDimitry Andric     cl::desc("Propagate labels from condition values of select instructions "
238e8d8bef9SDimitry Andric              "to results."),
239e8d8bef9SDimitry Andric     cl::Hidden, cl::init(true));
240e8d8bef9SDimitry Andric 
241fe6060f1SDimitry Andric // TODO: This default value follows MSan. DFSan may use a different value.
242fe6060f1SDimitry Andric static cl::opt<int> ClInstrumentWithCallThreshold(
243fe6060f1SDimitry Andric     "dfsan-instrument-with-call-threshold",
244fe6060f1SDimitry Andric     cl::desc("If the function being instrumented requires more than "
245fe6060f1SDimitry Andric              "this number of origin stores, use callbacks instead of "
246fe6060f1SDimitry Andric              "inline checks (-1 means never use callbacks)."),
247fe6060f1SDimitry Andric     cl::Hidden, cl::init(3500));
248fe6060f1SDimitry Andric 
249fe6060f1SDimitry Andric // Controls how to track origins.
250fe6060f1SDimitry Andric // * 0: do not track origins.
251fe6060f1SDimitry Andric // * 1: track origins at memory store operations.
252fe6060f1SDimitry Andric // * 2: track origins at memory load and store operations.
253fe6060f1SDimitry Andric //      TODO: track callsites.
254fe6060f1SDimitry Andric static cl::opt<int> ClTrackOrigins("dfsan-track-origins",
255fe6060f1SDimitry Andric                                    cl::desc("Track origins of labels"),
256fe6060f1SDimitry Andric                                    cl::Hidden, cl::init(0));
257fe6060f1SDimitry Andric 
2580eae32dcSDimitry Andric static cl::opt<bool> ClIgnorePersonalityRoutine(
2590eae32dcSDimitry Andric     "dfsan-ignore-personality-routine",
2600eae32dcSDimitry Andric     cl::desc("If a personality routine is marked uninstrumented from the ABI "
2610eae32dcSDimitry Andric              "list, do not create a wrapper for it."),
2620eae32dcSDimitry Andric     cl::Hidden, cl::init(false));
2630eae32dcSDimitry Andric 
264fe6060f1SDimitry Andric static StringRef getGlobalTypeString(const GlobalValue &G) {
2650b57cec5SDimitry Andric   // Types of GlobalVariables are always pointer types.
2660b57cec5SDimitry Andric   Type *GType = G.getValueType();
2675ffd83dbSDimitry Andric   // For now we support excluding struct types only.
2680b57cec5SDimitry Andric   if (StructType *SGType = dyn_cast<StructType>(GType)) {
2690b57cec5SDimitry Andric     if (!SGType->isLiteral())
2700b57cec5SDimitry Andric       return SGType->getName();
2710b57cec5SDimitry Andric   }
2720b57cec5SDimitry Andric   return "<unknown type>";
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric namespace {
2760b57cec5SDimitry Andric 
277fe6060f1SDimitry Andric // Memory map parameters used in application-to-shadow address calculation.
278fe6060f1SDimitry Andric // Offset = (Addr & ~AndMask) ^ XorMask
279fe6060f1SDimitry Andric // Shadow = ShadowBase + Offset
280fe6060f1SDimitry Andric // Origin = (OriginBase + Offset) & ~3ULL
281fe6060f1SDimitry Andric struct MemoryMapParams {
282fe6060f1SDimitry Andric   uint64_t AndMask;
283fe6060f1SDimitry Andric   uint64_t XorMask;
284fe6060f1SDimitry Andric   uint64_t ShadowBase;
285fe6060f1SDimitry Andric   uint64_t OriginBase;
286fe6060f1SDimitry Andric };
287fe6060f1SDimitry Andric 
288fe6060f1SDimitry Andric } // end anonymous namespace
289fe6060f1SDimitry Andric 
290bdd1243dSDimitry Andric // NOLINTBEGIN(readability-identifier-naming)
291bdd1243dSDimitry Andric // aarch64 Linux
292bdd1243dSDimitry Andric const MemoryMapParams Linux_AArch64_MemoryMapParams = {
293bdd1243dSDimitry Andric     0,               // AndMask (not used)
294bdd1243dSDimitry Andric     0x0B00000000000, // XorMask
295bdd1243dSDimitry Andric     0,               // ShadowBase (not used)
296bdd1243dSDimitry Andric     0x0200000000000, // OriginBase
297bdd1243dSDimitry Andric };
298bdd1243dSDimitry Andric 
299fe6060f1SDimitry Andric // x86_64 Linux
300bdd1243dSDimitry Andric const MemoryMapParams Linux_X86_64_MemoryMapParams = {
301fe6060f1SDimitry Andric     0,              // AndMask (not used)
302fe6060f1SDimitry Andric     0x500000000000, // XorMask
303fe6060f1SDimitry Andric     0,              // ShadowBase (not used)
304fe6060f1SDimitry Andric     0x100000000000, // OriginBase
305fe6060f1SDimitry Andric };
306bdd1243dSDimitry Andric // NOLINTEND(readability-identifier-naming)
307fe6060f1SDimitry Andric 
30806c3fb27SDimitry Andric // loongarch64 Linux
30906c3fb27SDimitry Andric const MemoryMapParams Linux_LoongArch64_MemoryMapParams = {
31006c3fb27SDimitry Andric     0,              // AndMask (not used)
31106c3fb27SDimitry Andric     0x500000000000, // XorMask
31206c3fb27SDimitry Andric     0,              // ShadowBase (not used)
31306c3fb27SDimitry Andric     0x100000000000, // OriginBase
31406c3fb27SDimitry Andric };
31506c3fb27SDimitry Andric 
316fe6060f1SDimitry Andric namespace {
317fe6060f1SDimitry Andric 
3180b57cec5SDimitry Andric class DFSanABIList {
3190b57cec5SDimitry Andric   std::unique_ptr<SpecialCaseList> SCL;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric public:
3220b57cec5SDimitry Andric   DFSanABIList() = default;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   void set(std::unique_ptr<SpecialCaseList> List) { SCL = std::move(List); }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   /// Returns whether either this function or its source file are listed in the
3270b57cec5SDimitry Andric   /// given category.
3280b57cec5SDimitry Andric   bool isIn(const Function &F, StringRef Category) const {
3290b57cec5SDimitry Andric     return isIn(*F.getParent(), Category) ||
3300b57cec5SDimitry Andric            SCL->inSection("dataflow", "fun", F.getName(), Category);
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   /// Returns whether this global alias is listed in the given category.
3340b57cec5SDimitry Andric   ///
3350b57cec5SDimitry Andric   /// If GA aliases a function, the alias's name is matched as a function name
3360b57cec5SDimitry Andric   /// would be.  Similarly, aliases of globals are matched like globals.
3370b57cec5SDimitry Andric   bool isIn(const GlobalAlias &GA, StringRef Category) const {
3380b57cec5SDimitry Andric     if (isIn(*GA.getParent(), Category))
3390b57cec5SDimitry Andric       return true;
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     if (isa<FunctionType>(GA.getValueType()))
3420b57cec5SDimitry Andric       return SCL->inSection("dataflow", "fun", GA.getName(), Category);
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric     return SCL->inSection("dataflow", "global", GA.getName(), Category) ||
345fe6060f1SDimitry Andric            SCL->inSection("dataflow", "type", getGlobalTypeString(GA),
3460b57cec5SDimitry Andric                           Category);
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   /// Returns whether this module is listed in the given category.
3500b57cec5SDimitry Andric   bool isIn(const Module &M, StringRef Category) const {
3510b57cec5SDimitry Andric     return SCL->inSection("dataflow", "src", M.getModuleIdentifier(), Category);
3520b57cec5SDimitry Andric   }
3530b57cec5SDimitry Andric };
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric /// TransformedFunction is used to express the result of transforming one
3560b57cec5SDimitry Andric /// function type into another.  This struct is immutable.  It holds metadata
3570b57cec5SDimitry Andric /// useful for updating calls of the old function to the new type.
3580b57cec5SDimitry Andric struct TransformedFunction {
359fe6060f1SDimitry Andric   TransformedFunction(FunctionType *OriginalType, FunctionType *TransformedType,
360*0fca6ea1SDimitry Andric                       const std::vector<unsigned> &ArgumentIndexMapping)
361fe6060f1SDimitry Andric       : OriginalType(OriginalType), TransformedType(TransformedType),
3620b57cec5SDimitry Andric         ArgumentIndexMapping(ArgumentIndexMapping) {}
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   // Disallow copies.
3650b57cec5SDimitry Andric   TransformedFunction(const TransformedFunction &) = delete;
3660b57cec5SDimitry Andric   TransformedFunction &operator=(const TransformedFunction &) = delete;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   // Allow moves.
3690b57cec5SDimitry Andric   TransformedFunction(TransformedFunction &&) = default;
3700b57cec5SDimitry Andric   TransformedFunction &operator=(TransformedFunction &&) = default;
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   /// Type of the function before the transformation.
3730b57cec5SDimitry Andric   FunctionType *OriginalType;
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   /// Type of the function after the transformation.
3760b57cec5SDimitry Andric   FunctionType *TransformedType;
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   /// Transforming a function may change the position of arguments.  This
3790b57cec5SDimitry Andric   /// member records the mapping from each argument's old position to its new
3800b57cec5SDimitry Andric   /// position.  Argument positions are zero-indexed.  If the transformation
3810b57cec5SDimitry Andric   /// from F to F' made the first argument of F into the third argument of F',
3820b57cec5SDimitry Andric   /// then ArgumentIndexMapping[0] will equal 2.
3830b57cec5SDimitry Andric   std::vector<unsigned> ArgumentIndexMapping;
3840b57cec5SDimitry Andric };
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric /// Given function attributes from a call site for the original function,
3870b57cec5SDimitry Andric /// return function attributes appropriate for a call to the transformed
3880b57cec5SDimitry Andric /// function.
389fe6060f1SDimitry Andric AttributeList
390fe6060f1SDimitry Andric transformFunctionAttributes(const TransformedFunction &TransformedFunction,
3910b57cec5SDimitry Andric                             LLVMContext &Ctx, AttributeList CallSiteAttrs) {
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   // Construct a vector of AttributeSet for each function argument.
3940b57cec5SDimitry Andric   std::vector<llvm::AttributeSet> ArgumentAttributes(
3950b57cec5SDimitry Andric       TransformedFunction.TransformedType->getNumParams());
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   // Copy attributes from the parameter of the original function to the
3980b57cec5SDimitry Andric   // transformed version.  'ArgumentIndexMapping' holds the mapping from
3990b57cec5SDimitry Andric   // old argument position to new.
400fe6060f1SDimitry Andric   for (unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
401fe6060f1SDimitry Andric        I < IE; ++I) {
402fe6060f1SDimitry Andric     unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[I];
403349cc55cSDimitry Andric     ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttrs(I);
4040b57cec5SDimitry Andric   }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   // Copy annotations on varargs arguments.
407fe6060f1SDimitry Andric   for (unsigned I = TransformedFunction.OriginalType->getNumParams(),
408fe6060f1SDimitry Andric                 IE = CallSiteAttrs.getNumAttrSets();
409fe6060f1SDimitry Andric        I < IE; ++I) {
410349cc55cSDimitry Andric     ArgumentAttributes.push_back(CallSiteAttrs.getParamAttrs(I));
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric 
413349cc55cSDimitry Andric   return AttributeList::get(Ctx, CallSiteAttrs.getFnAttrs(),
414349cc55cSDimitry Andric                             CallSiteAttrs.getRetAttrs(),
415bdd1243dSDimitry Andric                             llvm::ArrayRef(ArgumentAttributes));
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
418e8d8bef9SDimitry Andric class DataFlowSanitizer {
4190b57cec5SDimitry Andric   friend struct DFSanFunction;
4200b57cec5SDimitry Andric   friend class DFSanVisitor;
4210b57cec5SDimitry Andric 
422fe6060f1SDimitry Andric   enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
423fe6060f1SDimitry Andric 
424fe6060f1SDimitry Andric   enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   /// How should calls to uninstrumented functions be handled?
4270b57cec5SDimitry Andric   enum WrapperKind {
4280b57cec5SDimitry Andric     /// This function is present in an uninstrumented form but we don't know
4290b57cec5SDimitry Andric     /// how it should be handled.  Print a warning and call the function anyway.
4300b57cec5SDimitry Andric     /// Don't label the return value.
4310b57cec5SDimitry Andric     WK_Warning,
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric     /// This function does not write to (user-accessible) memory, and its return
4340b57cec5SDimitry Andric     /// value is unlabelled.
4350b57cec5SDimitry Andric     WK_Discard,
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric     /// This function does not write to (user-accessible) memory, and the label
4380b57cec5SDimitry Andric     /// of its return value is the union of the label of its arguments.
4390b57cec5SDimitry Andric     WK_Functional,
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric     /// Instead of calling the function, a custom wrapper __dfsw_F is called,
4420b57cec5SDimitry Andric     /// where F is the name of the function.  This function may wrap the
443349cc55cSDimitry Andric     /// original function or provide its own implementation. WK_Custom uses an
4440b57cec5SDimitry Andric     /// extra pointer argument to return the shadow.  This allows the wrapped
4450b57cec5SDimitry Andric     /// form of the function type to be expressed in C.
4460b57cec5SDimitry Andric     WK_Custom
4470b57cec5SDimitry Andric   };
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   Module *Mod;
4500b57cec5SDimitry Andric   LLVMContext *Ctx;
451e8d8bef9SDimitry Andric   Type *Int8Ptr;
452fe6060f1SDimitry Andric   IntegerType *OriginTy;
453fe6060f1SDimitry Andric   PointerType *OriginPtrTy;
454fe6060f1SDimitry Andric   ConstantInt *ZeroOrigin;
455e8d8bef9SDimitry Andric   /// The shadow type for all primitive types and vector types.
456e8d8bef9SDimitry Andric   IntegerType *PrimitiveShadowTy;
457e8d8bef9SDimitry Andric   PointerType *PrimitiveShadowPtrTy;
4580b57cec5SDimitry Andric   IntegerType *IntptrTy;
459e8d8bef9SDimitry Andric   ConstantInt *ZeroPrimitiveShadow;
4600b57cec5SDimitry Andric   Constant *ArgTLS;
461fe6060f1SDimitry Andric   ArrayType *ArgOriginTLSTy;
462fe6060f1SDimitry Andric   Constant *ArgOriginTLS;
4630b57cec5SDimitry Andric   Constant *RetvalTLS;
464fe6060f1SDimitry Andric   Constant *RetvalOriginTLS;
4650b57cec5SDimitry Andric   FunctionType *DFSanUnionLoadFnTy;
466fe6060f1SDimitry Andric   FunctionType *DFSanLoadLabelAndOriginFnTy;
4670b57cec5SDimitry Andric   FunctionType *DFSanUnimplementedFnTy;
46881ad6265SDimitry Andric   FunctionType *DFSanWrapperExternWeakNullFnTy;
4690b57cec5SDimitry Andric   FunctionType *DFSanSetLabelFnTy;
4700b57cec5SDimitry Andric   FunctionType *DFSanNonzeroLabelFnTy;
4710b57cec5SDimitry Andric   FunctionType *DFSanVarargWrapperFnTy;
47204eeddc0SDimitry Andric   FunctionType *DFSanConditionalCallbackFnTy;
47304eeddc0SDimitry Andric   FunctionType *DFSanConditionalCallbackOriginFnTy;
474bdd1243dSDimitry Andric   FunctionType *DFSanReachesFunctionCallbackFnTy;
475bdd1243dSDimitry Andric   FunctionType *DFSanReachesFunctionCallbackOriginFnTy;
476e8d8bef9SDimitry Andric   FunctionType *DFSanCmpCallbackFnTy;
477e8d8bef9SDimitry Andric   FunctionType *DFSanLoadStoreCallbackFnTy;
4785ffd83dbSDimitry Andric   FunctionType *DFSanMemTransferCallbackFnTy;
479fe6060f1SDimitry Andric   FunctionType *DFSanChainOriginFnTy;
480fe6060f1SDimitry Andric   FunctionType *DFSanChainOriginIfTaintedFnTy;
481fe6060f1SDimitry Andric   FunctionType *DFSanMemOriginTransferFnTy;
482bdd1243dSDimitry Andric   FunctionType *DFSanMemShadowOriginTransferFnTy;
483bdd1243dSDimitry Andric   FunctionType *DFSanMemShadowOriginConditionalExchangeFnTy;
484fe6060f1SDimitry Andric   FunctionType *DFSanMaybeStoreOriginFnTy;
4850b57cec5SDimitry Andric   FunctionCallee DFSanUnionLoadFn;
486fe6060f1SDimitry Andric   FunctionCallee DFSanLoadLabelAndOriginFn;
4870b57cec5SDimitry Andric   FunctionCallee DFSanUnimplementedFn;
48881ad6265SDimitry Andric   FunctionCallee DFSanWrapperExternWeakNullFn;
4890b57cec5SDimitry Andric   FunctionCallee DFSanSetLabelFn;
4900b57cec5SDimitry Andric   FunctionCallee DFSanNonzeroLabelFn;
4910b57cec5SDimitry Andric   FunctionCallee DFSanVarargWrapperFn;
4925ffd83dbSDimitry Andric   FunctionCallee DFSanLoadCallbackFn;
4935ffd83dbSDimitry Andric   FunctionCallee DFSanStoreCallbackFn;
4945ffd83dbSDimitry Andric   FunctionCallee DFSanMemTransferCallbackFn;
49504eeddc0SDimitry Andric   FunctionCallee DFSanConditionalCallbackFn;
49604eeddc0SDimitry Andric   FunctionCallee DFSanConditionalCallbackOriginFn;
497bdd1243dSDimitry Andric   FunctionCallee DFSanReachesFunctionCallbackFn;
498bdd1243dSDimitry Andric   FunctionCallee DFSanReachesFunctionCallbackOriginFn;
4995ffd83dbSDimitry Andric   FunctionCallee DFSanCmpCallbackFn;
500fe6060f1SDimitry Andric   FunctionCallee DFSanChainOriginFn;
501fe6060f1SDimitry Andric   FunctionCallee DFSanChainOriginIfTaintedFn;
502fe6060f1SDimitry Andric   FunctionCallee DFSanMemOriginTransferFn;
503bdd1243dSDimitry Andric   FunctionCallee DFSanMemShadowOriginTransferFn;
504bdd1243dSDimitry Andric   FunctionCallee DFSanMemShadowOriginConditionalExchangeFn;
505fe6060f1SDimitry Andric   FunctionCallee DFSanMaybeStoreOriginFn;
506fe6060f1SDimitry Andric   SmallPtrSet<Value *, 16> DFSanRuntimeFunctions;
5070b57cec5SDimitry Andric   MDNode *ColdCallWeights;
508fe6060f1SDimitry Andric   MDNode *OriginStoreWeights;
5090b57cec5SDimitry Andric   DFSanABIList ABIList;
5100b57cec5SDimitry Andric   DenseMap<Value *, Function *> UnwrappedFnMap;
51104eeddc0SDimitry Andric   AttributeMask ReadOnlyNoneAttrs;
51281ad6265SDimitry Andric   StringSet<> CombineTaintLookupTableNames;
5130b57cec5SDimitry Andric 
514fe6060f1SDimitry Andric   /// Memory map parameters used in calculation mapping application addresses
515fe6060f1SDimitry Andric   /// to shadow addresses and origin addresses.
516fe6060f1SDimitry Andric   const MemoryMapParams *MapParams;
517fe6060f1SDimitry Andric 
518fe6060f1SDimitry Andric   Value *getShadowOffset(Value *Addr, IRBuilder<> &IRB);
519*0fca6ea1SDimitry Andric   Value *getShadowAddress(Value *Addr, BasicBlock::iterator Pos);
520*0fca6ea1SDimitry Andric   Value *getShadowAddress(Value *Addr, BasicBlock::iterator Pos,
521*0fca6ea1SDimitry Andric                           Value *ShadowOffset);
522*0fca6ea1SDimitry Andric   std::pair<Value *, Value *> getShadowOriginAddress(Value *Addr,
523*0fca6ea1SDimitry Andric                                                      Align InstAlignment,
524*0fca6ea1SDimitry Andric                                                      BasicBlock::iterator Pos);
5250b57cec5SDimitry Andric   bool isInstrumented(const Function *F);
5260b57cec5SDimitry Andric   bool isInstrumented(const GlobalAlias *GA);
527349cc55cSDimitry Andric   bool isForceZeroLabels(const Function *F);
5280b57cec5SDimitry Andric   TransformedFunction getCustomFunctionType(FunctionType *T);
5290b57cec5SDimitry Andric   WrapperKind getWrapperKind(Function *F);
530fe6060f1SDimitry Andric   void addGlobalNameSuffix(GlobalValue *GV);
53181ad6265SDimitry Andric   void buildExternWeakCheckIfNeeded(IRBuilder<> &IRB, Function *F);
5320b57cec5SDimitry Andric   Function *buildWrapperFunction(Function *F, StringRef NewFName,
5330b57cec5SDimitry Andric                                  GlobalValue::LinkageTypes NewFLink,
5340b57cec5SDimitry Andric                                  FunctionType *NewFT);
5355ffd83dbSDimitry Andric   void initializeCallbackFunctions(Module &M);
5365ffd83dbSDimitry Andric   void initializeRuntimeFunctions(Module &M);
537fe6060f1SDimitry Andric   bool initializeModule(Module &M);
5380b57cec5SDimitry Andric 
539fe6060f1SDimitry Andric   /// Advances \p OriginAddr to point to the next 32-bit origin and then loads
540fe6060f1SDimitry Andric   /// from it. Returns the origin's loaded value.
541*0fca6ea1SDimitry Andric   Value *loadNextOrigin(BasicBlock::iterator Pos, Align OriginAlign,
542fe6060f1SDimitry Andric                         Value **OriginAddr);
543fe6060f1SDimitry Andric 
544fe6060f1SDimitry Andric   /// Returns whether the given load byte size is amenable to inlined
545fe6060f1SDimitry Andric   /// optimization patterns.
546fe6060f1SDimitry Andric   bool hasLoadSizeForFastPath(uint64_t Size);
547fe6060f1SDimitry Andric 
548fe6060f1SDimitry Andric   /// Returns whether the pass tracks origins. Supports only TLS ABI mode.
549fe6060f1SDimitry Andric   bool shouldTrackOrigins();
550e8d8bef9SDimitry Andric 
551e8d8bef9SDimitry Andric   /// Returns a zero constant with the shadow type of OrigTy.
552e8d8bef9SDimitry Andric   ///
553e8d8bef9SDimitry Andric   /// getZeroShadow({T1,T2,...}) = {getZeroShadow(T1),getZeroShadow(T2,...}
554e8d8bef9SDimitry Andric   /// getZeroShadow([n x T]) = [n x getZeroShadow(T)]
555e8d8bef9SDimitry Andric   /// getZeroShadow(other type) = i16(0)
556e8d8bef9SDimitry Andric   Constant *getZeroShadow(Type *OrigTy);
557e8d8bef9SDimitry Andric   /// Returns a zero constant with the shadow type of V's type.
558e8d8bef9SDimitry Andric   Constant *getZeroShadow(Value *V);
559e8d8bef9SDimitry Andric 
560e8d8bef9SDimitry Andric   /// Checks if V is a zero shadow.
561e8d8bef9SDimitry Andric   bool isZeroShadow(Value *V);
562e8d8bef9SDimitry Andric 
563e8d8bef9SDimitry Andric   /// Returns the shadow type of OrigTy.
564e8d8bef9SDimitry Andric   ///
565e8d8bef9SDimitry Andric   /// getShadowTy({T1,T2,...}) = {getShadowTy(T1),getShadowTy(T2),...}
566e8d8bef9SDimitry Andric   /// getShadowTy([n x T]) = [n x getShadowTy(T)]
567e8d8bef9SDimitry Andric   /// getShadowTy(other type) = i16
568e8d8bef9SDimitry Andric   Type *getShadowTy(Type *OrigTy);
5695f757f3fSDimitry Andric   /// Returns the shadow type of V's type.
570e8d8bef9SDimitry Andric   Type *getShadowTy(Value *V);
571e8d8bef9SDimitry Andric 
572fe6060f1SDimitry Andric   const uint64_t NumOfElementsInArgOrgTLS = ArgTLSSize / OriginWidthBytes;
573fe6060f1SDimitry Andric 
5740b57cec5SDimitry Andric public:
575e8d8bef9SDimitry Andric   DataFlowSanitizer(const std::vector<std::string> &ABIListFiles);
5760b57cec5SDimitry Andric 
577bdd1243dSDimitry Andric   bool runImpl(Module &M,
578bdd1243dSDimitry Andric                llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI);
5790b57cec5SDimitry Andric };
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric struct DFSanFunction {
5820b57cec5SDimitry Andric   DataFlowSanitizer &DFS;
5830b57cec5SDimitry Andric   Function *F;
5840b57cec5SDimitry Andric   DominatorTree DT;
5850b57cec5SDimitry Andric   bool IsNativeABI;
586349cc55cSDimitry Andric   bool IsForceZeroLabels;
587bdd1243dSDimitry Andric   TargetLibraryInfo &TLI;
5880b57cec5SDimitry Andric   AllocaInst *LabelReturnAlloca = nullptr;
589fe6060f1SDimitry Andric   AllocaInst *OriginReturnAlloca = nullptr;
5900b57cec5SDimitry Andric   DenseMap<Value *, Value *> ValShadowMap;
591fe6060f1SDimitry Andric   DenseMap<Value *, Value *> ValOriginMap;
5920b57cec5SDimitry Andric   DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
593fe6060f1SDimitry Andric   DenseMap<AllocaInst *, AllocaInst *> AllocaOriginMap;
594fe6060f1SDimitry Andric 
595fe6060f1SDimitry Andric   struct PHIFixupElement {
596fe6060f1SDimitry Andric     PHINode *Phi;
597fe6060f1SDimitry Andric     PHINode *ShadowPhi;
598fe6060f1SDimitry Andric     PHINode *OriginPhi;
599fe6060f1SDimitry Andric   };
600fe6060f1SDimitry Andric   std::vector<PHIFixupElement> PHIFixups;
601fe6060f1SDimitry Andric 
6020b57cec5SDimitry Andric   DenseSet<Instruction *> SkipInsts;
6030b57cec5SDimitry Andric   std::vector<Value *> NonZeroChecks;
6040b57cec5SDimitry Andric 
605e8d8bef9SDimitry Andric   struct CachedShadow {
606e8d8bef9SDimitry Andric     BasicBlock *Block; // The block where Shadow is defined.
6070b57cec5SDimitry Andric     Value *Shadow;
6080b57cec5SDimitry Andric   };
609e8d8bef9SDimitry Andric   /// Maps a value to its latest shadow value in terms of domination tree.
610e8d8bef9SDimitry Andric   DenseMap<std::pair<Value *, Value *>, CachedShadow> CachedShadows;
611e8d8bef9SDimitry Andric   /// Maps a value to its latest collapsed shadow value it was converted to in
612e8d8bef9SDimitry Andric   /// terms of domination tree. When ClDebugNonzeroLabels is on, this cache is
613e8d8bef9SDimitry Andric   /// used at a post process where CFG blocks are split. So it does not cache
614e8d8bef9SDimitry Andric   /// BasicBlock like CachedShadows, but uses domination between values.
615e8d8bef9SDimitry Andric   DenseMap<Value *, Value *> CachedCollapsedShadows;
6160b57cec5SDimitry Andric   DenseMap<Value *, std::set<Value *>> ShadowElements;
6170b57cec5SDimitry Andric 
618349cc55cSDimitry Andric   DFSanFunction(DataFlowSanitizer &DFS, Function *F, bool IsNativeABI,
619bdd1243dSDimitry Andric                 bool IsForceZeroLabels, TargetLibraryInfo &TLI)
620349cc55cSDimitry Andric       : DFS(DFS), F(F), IsNativeABI(IsNativeABI),
621bdd1243dSDimitry Andric         IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
6220b57cec5SDimitry Andric     DT.recalculate(*F);
6230b57cec5SDimitry Andric   }
6240b57cec5SDimitry Andric 
625e8d8bef9SDimitry Andric   /// Computes the shadow address for a given function argument.
626e8d8bef9SDimitry Andric   ///
627e8d8bef9SDimitry Andric   /// Shadow = ArgTLS+ArgOffset.
628e8d8bef9SDimitry Andric   Value *getArgTLS(Type *T, unsigned ArgOffset, IRBuilder<> &IRB);
629e8d8bef9SDimitry Andric 
630fe6060f1SDimitry Andric   /// Computes the shadow address for a return value.
631e8d8bef9SDimitry Andric   Value *getRetvalTLS(Type *T, IRBuilder<> &IRB);
632e8d8bef9SDimitry Andric 
633fe6060f1SDimitry Andric   /// Computes the origin address for a given function argument.
634fe6060f1SDimitry Andric   ///
635fe6060f1SDimitry Andric   /// Origin = ArgOriginTLS[ArgNo].
636fe6060f1SDimitry Andric   Value *getArgOriginTLS(unsigned ArgNo, IRBuilder<> &IRB);
637fe6060f1SDimitry Andric 
638fe6060f1SDimitry Andric   /// Computes the origin address for a return value.
639fe6060f1SDimitry Andric   Value *getRetvalOriginTLS();
640fe6060f1SDimitry Andric 
641fe6060f1SDimitry Andric   Value *getOrigin(Value *V);
642fe6060f1SDimitry Andric   void setOrigin(Instruction *I, Value *Origin);
643fe6060f1SDimitry Andric   /// Generates IR to compute the origin of the last operand with a taint label.
644fe6060f1SDimitry Andric   Value *combineOperandOrigins(Instruction *Inst);
645fe6060f1SDimitry Andric   /// Before the instruction Pos, generates IR to compute the last origin with a
646fe6060f1SDimitry Andric   /// taint label. Labels and origins are from vectors Shadows and Origins
647fe6060f1SDimitry Andric   /// correspondingly. The generated IR is like
648fe6060f1SDimitry Andric   ///   Sn-1 != Zero ? On-1: ... S2 != Zero ? O2: S1 != Zero ? O1: O0
649fe6060f1SDimitry Andric   /// When Zero is nullptr, it uses ZeroPrimitiveShadow. Otherwise it can be
650fe6060f1SDimitry Andric   /// zeros with other bitwidths.
651fe6060f1SDimitry Andric   Value *combineOrigins(const std::vector<Value *> &Shadows,
652*0fca6ea1SDimitry Andric                         const std::vector<Value *> &Origins,
653*0fca6ea1SDimitry Andric                         BasicBlock::iterator Pos, ConstantInt *Zero = nullptr);
654fe6060f1SDimitry Andric 
6550b57cec5SDimitry Andric   Value *getShadow(Value *V);
6560b57cec5SDimitry Andric   void setShadow(Instruction *I, Value *Shadow);
657e8d8bef9SDimitry Andric   /// Generates IR to compute the union of the two given shadows, inserting it
658e8d8bef9SDimitry Andric   /// before Pos. The combined value is with primitive type.
659*0fca6ea1SDimitry Andric   Value *combineShadows(Value *V1, Value *V2, BasicBlock::iterator Pos);
660e8d8bef9SDimitry Andric   /// Combines the shadow values of V1 and V2, then converts the combined value
661e8d8bef9SDimitry Andric   /// with primitive type into a shadow value with the original type T.
662e8d8bef9SDimitry Andric   Value *combineShadowsThenConvert(Type *T, Value *V1, Value *V2,
663*0fca6ea1SDimitry Andric                                    BasicBlock::iterator Pos);
6640b57cec5SDimitry Andric   Value *combineOperandShadows(Instruction *Inst);
665fe6060f1SDimitry Andric 
666fe6060f1SDimitry Andric   /// Generates IR to load shadow and origin corresponding to bytes [\p
667fe6060f1SDimitry Andric   /// Addr, \p Addr + \p Size), where addr has alignment \p
668fe6060f1SDimitry Andric   /// InstAlignment, and take the union of each of those shadows. The returned
669fe6060f1SDimitry Andric   /// shadow always has primitive type.
670fe6060f1SDimitry Andric   ///
671fe6060f1SDimitry Andric   /// When tracking loads is enabled, the returned origin is a chain at the
672fe6060f1SDimitry Andric   /// current stack if the returned shadow is tainted.
673fe6060f1SDimitry Andric   std::pair<Value *, Value *> loadShadowOrigin(Value *Addr, uint64_t Size,
674fe6060f1SDimitry Andric                                                Align InstAlignment,
675*0fca6ea1SDimitry Andric                                                BasicBlock::iterator Pos);
676fe6060f1SDimitry Andric 
677fe6060f1SDimitry Andric   void storePrimitiveShadowOrigin(Value *Addr, uint64_t Size,
678fe6060f1SDimitry Andric                                   Align InstAlignment, Value *PrimitiveShadow,
679*0fca6ea1SDimitry Andric                                   Value *Origin, BasicBlock::iterator Pos);
680e8d8bef9SDimitry Andric   /// Applies PrimitiveShadow to all primitive subtypes of T, returning
681e8d8bef9SDimitry Andric   /// the expanded shadow value.
682e8d8bef9SDimitry Andric   ///
683e8d8bef9SDimitry Andric   /// EFP({T1,T2, ...}, PS) = {EFP(T1,PS),EFP(T2,PS),...}
684e8d8bef9SDimitry Andric   /// EFP([n x T], PS) = [n x EFP(T,PS)]
685e8d8bef9SDimitry Andric   /// EFP(other types, PS) = PS
686e8d8bef9SDimitry Andric   Value *expandFromPrimitiveShadow(Type *T, Value *PrimitiveShadow,
687*0fca6ea1SDimitry Andric                                    BasicBlock::iterator Pos);
688e8d8bef9SDimitry Andric   /// Collapses Shadow into a single primitive shadow value, unioning all
689e8d8bef9SDimitry Andric   /// primitive shadow values in the process. Returns the final primitive
690e8d8bef9SDimitry Andric   /// shadow value.
691e8d8bef9SDimitry Andric   ///
692e8d8bef9SDimitry Andric   /// CTP({V1,V2, ...}) = UNION(CFP(V1,PS),CFP(V2,PS),...)
693e8d8bef9SDimitry Andric   /// CTP([V1,V2,...]) = UNION(CFP(V1,PS),CFP(V2,PS),...)
694e8d8bef9SDimitry Andric   /// CTP(other types, PS) = PS
695*0fca6ea1SDimitry Andric   Value *collapseToPrimitiveShadow(Value *Shadow, BasicBlock::iterator Pos);
696e8d8bef9SDimitry Andric 
697fe6060f1SDimitry Andric   void storeZeroPrimitiveShadow(Value *Addr, uint64_t Size, Align ShadowAlign,
698*0fca6ea1SDimitry Andric                                 BasicBlock::iterator Pos);
699fe6060f1SDimitry Andric 
700fe6060f1SDimitry Andric   Align getShadowAlign(Align InstAlignment);
701fe6060f1SDimitry Andric 
70204eeddc0SDimitry Andric   // If ClConditionalCallbacks is enabled, insert a callback after a given
70304eeddc0SDimitry Andric   // branch instruction using the given conditional expression.
70404eeddc0SDimitry Andric   void addConditionalCallbacksIfEnabled(Instruction &I, Value *Condition);
70504eeddc0SDimitry Andric 
706bdd1243dSDimitry Andric   // If ClReachesFunctionCallbacks is enabled, insert a callback for each
707bdd1243dSDimitry Andric   // argument and load instruction.
708bdd1243dSDimitry Andric   void addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB, Instruction &I,
709bdd1243dSDimitry Andric                                             Value *Data);
710bdd1243dSDimitry Andric 
71181ad6265SDimitry Andric   bool isLookupTableConstant(Value *P);
71281ad6265SDimitry Andric 
713e8d8bef9SDimitry Andric private:
714e8d8bef9SDimitry Andric   /// Collapses the shadow with aggregate type into a single primitive shadow
715e8d8bef9SDimitry Andric   /// value.
716e8d8bef9SDimitry Andric   template <class AggregateType>
717e8d8bef9SDimitry Andric   Value *collapseAggregateShadow(AggregateType *AT, Value *Shadow,
718e8d8bef9SDimitry Andric                                  IRBuilder<> &IRB);
719e8d8bef9SDimitry Andric 
720e8d8bef9SDimitry Andric   Value *collapseToPrimitiveShadow(Value *Shadow, IRBuilder<> &IRB);
721e8d8bef9SDimitry Andric 
722e8d8bef9SDimitry Andric   /// Returns the shadow value of an argument A.
723e8d8bef9SDimitry Andric   Value *getShadowForTLSArgument(Argument *A);
724fe6060f1SDimitry Andric 
725fe6060f1SDimitry Andric   /// The fast path of loading shadows.
726fe6060f1SDimitry Andric   std::pair<Value *, Value *>
727fe6060f1SDimitry Andric   loadShadowFast(Value *ShadowAddr, Value *OriginAddr, uint64_t Size,
728fe6060f1SDimitry Andric                  Align ShadowAlign, Align OriginAlign, Value *FirstOrigin,
729*0fca6ea1SDimitry Andric                  BasicBlock::iterator Pos);
730fe6060f1SDimitry Andric 
731fe6060f1SDimitry Andric   Align getOriginAlign(Align InstAlignment);
732fe6060f1SDimitry Andric 
733fe6060f1SDimitry Andric   /// Because 4 contiguous bytes share one 4-byte origin, the most accurate load
734fe6060f1SDimitry Andric   /// is __dfsan_load_label_and_origin. This function returns the union of all
735fe6060f1SDimitry Andric   /// labels and the origin of the first taint label. However this is an
736fe6060f1SDimitry Andric   /// additional call with many instructions. To ensure common cases are fast,
737fe6060f1SDimitry Andric   /// checks if it is possible to load labels and origins without using the
738fe6060f1SDimitry Andric   /// callback function.
739fe6060f1SDimitry Andric   ///
740fe6060f1SDimitry Andric   /// When enabling tracking load instructions, we always use
741fe6060f1SDimitry Andric   /// __dfsan_load_label_and_origin to reduce code size.
742fe6060f1SDimitry Andric   bool useCallbackLoadLabelAndOrigin(uint64_t Size, Align InstAlignment);
743fe6060f1SDimitry Andric 
744fe6060f1SDimitry Andric   /// Returns a chain at the current stack with previous origin V.
745fe6060f1SDimitry Andric   Value *updateOrigin(Value *V, IRBuilder<> &IRB);
746fe6060f1SDimitry Andric 
747fe6060f1SDimitry Andric   /// Returns a chain at the current stack with previous origin V if Shadow is
748fe6060f1SDimitry Andric   /// tainted.
749fe6060f1SDimitry Andric   Value *updateOriginIfTainted(Value *Shadow, Value *Origin, IRBuilder<> &IRB);
750fe6060f1SDimitry Andric 
751fe6060f1SDimitry Andric   /// Creates an Intptr = Origin | Origin << 32 if Intptr's size is 64. Returns
752fe6060f1SDimitry Andric   /// Origin otherwise.
753fe6060f1SDimitry Andric   Value *originToIntptr(IRBuilder<> &IRB, Value *Origin);
754fe6060f1SDimitry Andric 
755fe6060f1SDimitry Andric   /// Stores Origin into the address range [StoreOriginAddr, StoreOriginAddr +
756fe6060f1SDimitry Andric   /// Size).
757fe6060f1SDimitry Andric   void paintOrigin(IRBuilder<> &IRB, Value *Origin, Value *StoreOriginAddr,
758fe6060f1SDimitry Andric                    uint64_t StoreOriginSize, Align Alignment);
759fe6060f1SDimitry Andric 
760fe6060f1SDimitry Andric   /// Stores Origin in terms of its Shadow value.
761fe6060f1SDimitry Andric   /// * Do not write origins for zero shadows because we do not trace origins
762fe6060f1SDimitry Andric   ///   for untainted sinks.
763fe6060f1SDimitry Andric   /// * Use __dfsan_maybe_store_origin if there are too many origin store
764fe6060f1SDimitry Andric   ///   instrumentations.
765*0fca6ea1SDimitry Andric   void storeOrigin(BasicBlock::iterator Pos, Value *Addr, uint64_t Size,
766*0fca6ea1SDimitry Andric                    Value *Shadow, Value *Origin, Value *StoreOriginAddr,
767*0fca6ea1SDimitry Andric                    Align InstAlignment);
768fe6060f1SDimitry Andric 
769fe6060f1SDimitry Andric   /// Convert a scalar value to an i1 by comparing with 0.
770fe6060f1SDimitry Andric   Value *convertToBool(Value *V, IRBuilder<> &IRB, const Twine &Name = "");
771fe6060f1SDimitry Andric 
772fe6060f1SDimitry Andric   bool shouldInstrumentWithCall();
773fe6060f1SDimitry Andric 
774fe6060f1SDimitry Andric   /// Generates IR to load shadow and origin corresponding to bytes [\p
775fe6060f1SDimitry Andric   /// Addr, \p Addr + \p Size), where addr has alignment \p
776fe6060f1SDimitry Andric   /// InstAlignment, and take the union of each of those shadows. The returned
777fe6060f1SDimitry Andric   /// shadow always has primitive type.
778fe6060f1SDimitry Andric   std::pair<Value *, Value *>
779fe6060f1SDimitry Andric   loadShadowOriginSansLoadTracking(Value *Addr, uint64_t Size,
780*0fca6ea1SDimitry Andric                                    Align InstAlignment,
781*0fca6ea1SDimitry Andric                                    BasicBlock::iterator Pos);
782fe6060f1SDimitry Andric   int NumOriginStores = 0;
7830b57cec5SDimitry Andric };
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric class DFSanVisitor : public InstVisitor<DFSanVisitor> {
7860b57cec5SDimitry Andric public:
7870b57cec5SDimitry Andric   DFSanFunction &DFSF;
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric   DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   const DataLayout &getDataLayout() const {
792*0fca6ea1SDimitry Andric     return DFSF.F->getDataLayout();
7930b57cec5SDimitry Andric   }
7940b57cec5SDimitry Andric 
795fe6060f1SDimitry Andric   // Combines shadow values and origins for all of I's operands.
796fe6060f1SDimitry Andric   void visitInstOperands(Instruction &I);
7975ffd83dbSDimitry Andric 
7980b57cec5SDimitry Andric   void visitUnaryOperator(UnaryOperator &UO);
7990b57cec5SDimitry Andric   void visitBinaryOperator(BinaryOperator &BO);
800fe6060f1SDimitry Andric   void visitBitCastInst(BitCastInst &BCI);
8010b57cec5SDimitry Andric   void visitCastInst(CastInst &CI);
8020b57cec5SDimitry Andric   void visitCmpInst(CmpInst &CI);
803fe6060f1SDimitry Andric   void visitLandingPadInst(LandingPadInst &LPI);
8040b57cec5SDimitry Andric   void visitGetElementPtrInst(GetElementPtrInst &GEPI);
8050b57cec5SDimitry Andric   void visitLoadInst(LoadInst &LI);
8060b57cec5SDimitry Andric   void visitStoreInst(StoreInst &SI);
807fe6060f1SDimitry Andric   void visitAtomicRMWInst(AtomicRMWInst &I);
808fe6060f1SDimitry Andric   void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);
8090b57cec5SDimitry Andric   void visitReturnInst(ReturnInst &RI);
810bdd1243dSDimitry Andric   void visitLibAtomicLoad(CallBase &CB);
811bdd1243dSDimitry Andric   void visitLibAtomicStore(CallBase &CB);
812bdd1243dSDimitry Andric   void visitLibAtomicExchange(CallBase &CB);
813bdd1243dSDimitry Andric   void visitLibAtomicCompareExchange(CallBase &CB);
8145ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB);
8150b57cec5SDimitry Andric   void visitPHINode(PHINode &PN);
8160b57cec5SDimitry Andric   void visitExtractElementInst(ExtractElementInst &I);
8170b57cec5SDimitry Andric   void visitInsertElementInst(InsertElementInst &I);
8180b57cec5SDimitry Andric   void visitShuffleVectorInst(ShuffleVectorInst &I);
8190b57cec5SDimitry Andric   void visitExtractValueInst(ExtractValueInst &I);
8200b57cec5SDimitry Andric   void visitInsertValueInst(InsertValueInst &I);
8210b57cec5SDimitry Andric   void visitAllocaInst(AllocaInst &I);
8220b57cec5SDimitry Andric   void visitSelectInst(SelectInst &I);
8230b57cec5SDimitry Andric   void visitMemSetInst(MemSetInst &I);
8240b57cec5SDimitry Andric   void visitMemTransferInst(MemTransferInst &I);
82504eeddc0SDimitry Andric   void visitBranchInst(BranchInst &BR);
82604eeddc0SDimitry Andric   void visitSwitchInst(SwitchInst &SW);
827fe6060f1SDimitry Andric 
828fe6060f1SDimitry Andric private:
829fe6060f1SDimitry Andric   void visitCASOrRMW(Align InstAlignment, Instruction &I);
830fe6060f1SDimitry Andric 
831fe6060f1SDimitry Andric   // Returns false when this is an invoke of a custom function.
832fe6060f1SDimitry Andric   bool visitWrappedCallBase(Function &F, CallBase &CB);
833fe6060f1SDimitry Andric 
834fe6060f1SDimitry Andric   // Combines origins for all of I's operands.
835fe6060f1SDimitry Andric   void visitInstOperandOrigins(Instruction &I);
836fe6060f1SDimitry Andric 
837fe6060f1SDimitry Andric   void addShadowArguments(Function &F, CallBase &CB, std::vector<Value *> &Args,
838fe6060f1SDimitry Andric                           IRBuilder<> &IRB);
839fe6060f1SDimitry Andric 
840fe6060f1SDimitry Andric   void addOriginArguments(Function &F, CallBase &CB, std::vector<Value *> &Args,
841fe6060f1SDimitry Andric                           IRBuilder<> &IRB);
842bdd1243dSDimitry Andric 
843bdd1243dSDimitry Andric   Value *makeAddAcquireOrderingTable(IRBuilder<> &IRB);
844bdd1243dSDimitry Andric   Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB);
8450b57cec5SDimitry Andric };
8460b57cec5SDimitry Andric 
847bdd1243dSDimitry Andric bool LibAtomicFunction(const Function &F) {
848bdd1243dSDimitry Andric   // This is a bit of a hack because TargetLibraryInfo is a function pass.
849bdd1243dSDimitry Andric   // The DFSan pass would need to be refactored to be function pass oriented
850bdd1243dSDimitry Andric   // (like MSan is) in order to fit together nicely with TargetLibraryInfo.
851bdd1243dSDimitry Andric   // We need this check to prevent them from being instrumented, or wrapped.
852bdd1243dSDimitry Andric   // Match on name and number of arguments.
853bdd1243dSDimitry Andric   if (!F.hasName() || F.isVarArg())
854bdd1243dSDimitry Andric     return false;
855bdd1243dSDimitry Andric   switch (F.arg_size()) {
856bdd1243dSDimitry Andric   case 4:
857bdd1243dSDimitry Andric     return F.getName() == "__atomic_load" || F.getName() == "__atomic_store";
858bdd1243dSDimitry Andric   case 5:
859bdd1243dSDimitry Andric     return F.getName() == "__atomic_exchange";
860bdd1243dSDimitry Andric   case 6:
861bdd1243dSDimitry Andric     return F.getName() == "__atomic_compare_exchange";
862bdd1243dSDimitry Andric   default:
863bdd1243dSDimitry Andric     return false;
864bdd1243dSDimitry Andric   }
865bdd1243dSDimitry Andric }
866bdd1243dSDimitry Andric 
8670b57cec5SDimitry Andric } // end anonymous namespace
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric DataFlowSanitizer::DataFlowSanitizer(
870e8d8bef9SDimitry Andric     const std::vector<std::string> &ABIListFiles) {
8710b57cec5SDimitry Andric   std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
872e8d8bef9SDimitry Andric   llvm::append_range(AllABIListFiles, ClABIListFiles);
873480093f4SDimitry Andric   // FIXME: should we propagate vfs::FileSystem to this constructor?
874480093f4SDimitry Andric   ABIList.set(
875480093f4SDimitry Andric       SpecialCaseList::createOrDie(AllABIListFiles, *vfs::getRealFileSystem()));
8760b57cec5SDimitry Andric 
87781ad6265SDimitry Andric   for (StringRef v : ClCombineTaintLookupTables)
87881ad6265SDimitry Andric     CombineTaintLookupTableNames.insert(v);
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
8820b57cec5SDimitry Andric   SmallVector<Type *, 4> ArgTypes;
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric   // Some parameters of the custom function being constructed are
8850b57cec5SDimitry Andric   // parameters of T.  Record the mapping from parameters of T to
8860b57cec5SDimitry Andric   // parameters of the custom function, so that parameter attributes
8870b57cec5SDimitry Andric   // at call sites can be updated.
8880b57cec5SDimitry Andric   std::vector<unsigned> ArgumentIndexMapping;
889fe6060f1SDimitry Andric   for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
890fe6060f1SDimitry Andric     Type *ParamType = T->getParamType(I);
8910b57cec5SDimitry Andric     ArgumentIndexMapping.push_back(ArgTypes.size());
892fe6060f1SDimitry Andric     ArgTypes.push_back(ParamType);
8930b57cec5SDimitry Andric   }
894fe6060f1SDimitry Andric   for (unsigned I = 0, E = T->getNumParams(); I != E; ++I)
895e8d8bef9SDimitry Andric     ArgTypes.push_back(PrimitiveShadowTy);
8960b57cec5SDimitry Andric   if (T->isVarArg())
897e8d8bef9SDimitry Andric     ArgTypes.push_back(PrimitiveShadowPtrTy);
8980b57cec5SDimitry Andric   Type *RetType = T->getReturnType();
8990b57cec5SDimitry Andric   if (!RetType->isVoidTy())
900e8d8bef9SDimitry Andric     ArgTypes.push_back(PrimitiveShadowPtrTy);
901fe6060f1SDimitry Andric 
902fe6060f1SDimitry Andric   if (shouldTrackOrigins()) {
903fe6060f1SDimitry Andric     for (unsigned I = 0, E = T->getNumParams(); I != E; ++I)
904fe6060f1SDimitry Andric       ArgTypes.push_back(OriginTy);
905fe6060f1SDimitry Andric     if (T->isVarArg())
906fe6060f1SDimitry Andric       ArgTypes.push_back(OriginPtrTy);
907fe6060f1SDimitry Andric     if (!RetType->isVoidTy())
908fe6060f1SDimitry Andric       ArgTypes.push_back(OriginPtrTy);
909fe6060f1SDimitry Andric   }
910fe6060f1SDimitry Andric 
9110b57cec5SDimitry Andric   return TransformedFunction(
9120b57cec5SDimitry Andric       T, FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()),
9130b57cec5SDimitry Andric       ArgumentIndexMapping);
9140b57cec5SDimitry Andric }
9150b57cec5SDimitry Andric 
916e8d8bef9SDimitry Andric bool DataFlowSanitizer::isZeroShadow(Value *V) {
917e8d8bef9SDimitry Andric   Type *T = V->getType();
918e8d8bef9SDimitry Andric   if (!isa<ArrayType>(T) && !isa<StructType>(T)) {
919e8d8bef9SDimitry Andric     if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
920e8d8bef9SDimitry Andric       return CI->isZero();
921e8d8bef9SDimitry Andric     return false;
922e8d8bef9SDimitry Andric   }
923e8d8bef9SDimitry Andric 
924e8d8bef9SDimitry Andric   return isa<ConstantAggregateZero>(V);
925e8d8bef9SDimitry Andric }
926e8d8bef9SDimitry Andric 
927fe6060f1SDimitry Andric bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t Size) {
928fe6060f1SDimitry Andric   uint64_t ShadowSize = Size * ShadowWidthBytes;
929fe6060f1SDimitry Andric   return ShadowSize % 8 == 0 || ShadowSize == 4;
930fe6060f1SDimitry Andric }
931fe6060f1SDimitry Andric 
932fe6060f1SDimitry Andric bool DataFlowSanitizer::shouldTrackOrigins() {
933349cc55cSDimitry Andric   static const bool ShouldTrackOrigins = ClTrackOrigins;
934fe6060f1SDimitry Andric   return ShouldTrackOrigins;
935fe6060f1SDimitry Andric }
936fe6060f1SDimitry Andric 
937e8d8bef9SDimitry Andric Constant *DataFlowSanitizer::getZeroShadow(Type *OrigTy) {
938e8d8bef9SDimitry Andric   if (!isa<ArrayType>(OrigTy) && !isa<StructType>(OrigTy))
939e8d8bef9SDimitry Andric     return ZeroPrimitiveShadow;
940e8d8bef9SDimitry Andric   Type *ShadowTy = getShadowTy(OrigTy);
941e8d8bef9SDimitry Andric   return ConstantAggregateZero::get(ShadowTy);
942e8d8bef9SDimitry Andric }
943e8d8bef9SDimitry Andric 
944e8d8bef9SDimitry Andric Constant *DataFlowSanitizer::getZeroShadow(Value *V) {
945e8d8bef9SDimitry Andric   return getZeroShadow(V->getType());
946e8d8bef9SDimitry Andric }
947e8d8bef9SDimitry Andric 
948e8d8bef9SDimitry Andric static Value *expandFromPrimitiveShadowRecursive(
949e8d8bef9SDimitry Andric     Value *Shadow, SmallVector<unsigned, 4> &Indices, Type *SubShadowTy,
950e8d8bef9SDimitry Andric     Value *PrimitiveShadow, IRBuilder<> &IRB) {
951e8d8bef9SDimitry Andric   if (!isa<ArrayType>(SubShadowTy) && !isa<StructType>(SubShadowTy))
952e8d8bef9SDimitry Andric     return IRB.CreateInsertValue(Shadow, PrimitiveShadow, Indices);
953e8d8bef9SDimitry Andric 
954e8d8bef9SDimitry Andric   if (ArrayType *AT = dyn_cast<ArrayType>(SubShadowTy)) {
955e8d8bef9SDimitry Andric     for (unsigned Idx = 0; Idx < AT->getNumElements(); Idx++) {
956e8d8bef9SDimitry Andric       Indices.push_back(Idx);
957e8d8bef9SDimitry Andric       Shadow = expandFromPrimitiveShadowRecursive(
958e8d8bef9SDimitry Andric           Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
959e8d8bef9SDimitry Andric       Indices.pop_back();
960e8d8bef9SDimitry Andric     }
961e8d8bef9SDimitry Andric     return Shadow;
962e8d8bef9SDimitry Andric   }
963e8d8bef9SDimitry Andric 
964e8d8bef9SDimitry Andric   if (StructType *ST = dyn_cast<StructType>(SubShadowTy)) {
965e8d8bef9SDimitry Andric     for (unsigned Idx = 0; Idx < ST->getNumElements(); Idx++) {
966e8d8bef9SDimitry Andric       Indices.push_back(Idx);
967e8d8bef9SDimitry Andric       Shadow = expandFromPrimitiveShadowRecursive(
968e8d8bef9SDimitry Andric           Shadow, Indices, ST->getElementType(Idx), PrimitiveShadow, IRB);
969e8d8bef9SDimitry Andric       Indices.pop_back();
970e8d8bef9SDimitry Andric     }
971e8d8bef9SDimitry Andric     return Shadow;
972e8d8bef9SDimitry Andric   }
973e8d8bef9SDimitry Andric   llvm_unreachable("Unexpected shadow type");
974e8d8bef9SDimitry Andric }
975e8d8bef9SDimitry Andric 
976fe6060f1SDimitry Andric bool DFSanFunction::shouldInstrumentWithCall() {
977fe6060f1SDimitry Andric   return ClInstrumentWithCallThreshold >= 0 &&
978fe6060f1SDimitry Andric          NumOriginStores >= ClInstrumentWithCallThreshold;
979fe6060f1SDimitry Andric }
980fe6060f1SDimitry Andric 
981e8d8bef9SDimitry Andric Value *DFSanFunction::expandFromPrimitiveShadow(Type *T, Value *PrimitiveShadow,
982*0fca6ea1SDimitry Andric                                                 BasicBlock::iterator Pos) {
983e8d8bef9SDimitry Andric   Type *ShadowTy = DFS.getShadowTy(T);
984e8d8bef9SDimitry Andric 
985e8d8bef9SDimitry Andric   if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
986e8d8bef9SDimitry Andric     return PrimitiveShadow;
987e8d8bef9SDimitry Andric 
988e8d8bef9SDimitry Andric   if (DFS.isZeroShadow(PrimitiveShadow))
989e8d8bef9SDimitry Andric     return DFS.getZeroShadow(ShadowTy);
990e8d8bef9SDimitry Andric 
991*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
992e8d8bef9SDimitry Andric   SmallVector<unsigned, 4> Indices;
993e8d8bef9SDimitry Andric   Value *Shadow = UndefValue::get(ShadowTy);
994e8d8bef9SDimitry Andric   Shadow = expandFromPrimitiveShadowRecursive(Shadow, Indices, ShadowTy,
995e8d8bef9SDimitry Andric                                               PrimitiveShadow, IRB);
996e8d8bef9SDimitry Andric 
997e8d8bef9SDimitry Andric   // Caches the primitive shadow value that built the shadow value.
998e8d8bef9SDimitry Andric   CachedCollapsedShadows[Shadow] = PrimitiveShadow;
999e8d8bef9SDimitry Andric   return Shadow;
1000e8d8bef9SDimitry Andric }
1001e8d8bef9SDimitry Andric 
1002e8d8bef9SDimitry Andric template <class AggregateType>
1003e8d8bef9SDimitry Andric Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT, Value *Shadow,
1004e8d8bef9SDimitry Andric                                               IRBuilder<> &IRB) {
1005e8d8bef9SDimitry Andric   if (!AT->getNumElements())
1006e8d8bef9SDimitry Andric     return DFS.ZeroPrimitiveShadow;
1007e8d8bef9SDimitry Andric 
1008e8d8bef9SDimitry Andric   Value *FirstItem = IRB.CreateExtractValue(Shadow, 0);
1009e8d8bef9SDimitry Andric   Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1010e8d8bef9SDimitry Andric 
1011e8d8bef9SDimitry Andric   for (unsigned Idx = 1; Idx < AT->getNumElements(); Idx++) {
1012e8d8bef9SDimitry Andric     Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx);
1013e8d8bef9SDimitry Andric     Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1014e8d8bef9SDimitry Andric     Aggregator = IRB.CreateOr(Aggregator, ShadowInner);
1015e8d8bef9SDimitry Andric   }
1016e8d8bef9SDimitry Andric   return Aggregator;
1017e8d8bef9SDimitry Andric }
1018e8d8bef9SDimitry Andric 
1019e8d8bef9SDimitry Andric Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
1020e8d8bef9SDimitry Andric                                                 IRBuilder<> &IRB) {
1021e8d8bef9SDimitry Andric   Type *ShadowTy = Shadow->getType();
1022e8d8bef9SDimitry Andric   if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1023e8d8bef9SDimitry Andric     return Shadow;
1024e8d8bef9SDimitry Andric   if (ArrayType *AT = dyn_cast<ArrayType>(ShadowTy))
1025e8d8bef9SDimitry Andric     return collapseAggregateShadow<>(AT, Shadow, IRB);
1026e8d8bef9SDimitry Andric   if (StructType *ST = dyn_cast<StructType>(ShadowTy))
1027e8d8bef9SDimitry Andric     return collapseAggregateShadow<>(ST, Shadow, IRB);
1028e8d8bef9SDimitry Andric   llvm_unreachable("Unexpected shadow type");
1029e8d8bef9SDimitry Andric }
1030e8d8bef9SDimitry Andric 
1031e8d8bef9SDimitry Andric Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
1032*0fca6ea1SDimitry Andric                                                 BasicBlock::iterator Pos) {
1033e8d8bef9SDimitry Andric   Type *ShadowTy = Shadow->getType();
1034e8d8bef9SDimitry Andric   if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1035e8d8bef9SDimitry Andric     return Shadow;
1036e8d8bef9SDimitry Andric 
1037e8d8bef9SDimitry Andric   // Checks if the cached collapsed shadow value dominates Pos.
1038e8d8bef9SDimitry Andric   Value *&CS = CachedCollapsedShadows[Shadow];
1039e8d8bef9SDimitry Andric   if (CS && DT.dominates(CS, Pos))
1040e8d8bef9SDimitry Andric     return CS;
1041e8d8bef9SDimitry Andric 
1042*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
1043e8d8bef9SDimitry Andric   Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1044e8d8bef9SDimitry Andric   // Caches the converted primitive shadow value.
1045e8d8bef9SDimitry Andric   CS = PrimitiveShadow;
1046e8d8bef9SDimitry Andric   return PrimitiveShadow;
1047e8d8bef9SDimitry Andric }
1048e8d8bef9SDimitry Andric 
104904eeddc0SDimitry Andric void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &I,
105004eeddc0SDimitry Andric                                                      Value *Condition) {
105104eeddc0SDimitry Andric   if (!ClConditionalCallbacks) {
105204eeddc0SDimitry Andric     return;
105304eeddc0SDimitry Andric   }
105404eeddc0SDimitry Andric   IRBuilder<> IRB(&I);
105504eeddc0SDimitry Andric   Value *CondShadow = getShadow(Condition);
1056bdd1243dSDimitry Andric   CallInst *CI;
105704eeddc0SDimitry Andric   if (DFS.shouldTrackOrigins()) {
105804eeddc0SDimitry Andric     Value *CondOrigin = getOrigin(Condition);
1059bdd1243dSDimitry Andric     CI = IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn,
106004eeddc0SDimitry Andric                         {CondShadow, CondOrigin});
106104eeddc0SDimitry Andric   } else {
1062bdd1243dSDimitry Andric     CI = IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
106304eeddc0SDimitry Andric   }
1064bdd1243dSDimitry Andric   CI->addParamAttr(0, Attribute::ZExt);
1065bdd1243dSDimitry Andric }
1066bdd1243dSDimitry Andric 
1067bdd1243dSDimitry Andric void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB,
1068bdd1243dSDimitry Andric                                                          Instruction &I,
1069bdd1243dSDimitry Andric                                                          Value *Data) {
1070bdd1243dSDimitry Andric   if (!ClReachesFunctionCallbacks) {
1071bdd1243dSDimitry Andric     return;
1072bdd1243dSDimitry Andric   }
1073bdd1243dSDimitry Andric   const DebugLoc &dbgloc = I.getDebugLoc();
1074bdd1243dSDimitry Andric   Value *DataShadow = collapseToPrimitiveShadow(getShadow(Data), IRB);
1075bdd1243dSDimitry Andric   ConstantInt *CILine;
1076bdd1243dSDimitry Andric   llvm::Value *FilePathPtr;
1077bdd1243dSDimitry Andric 
1078bdd1243dSDimitry Andric   if (dbgloc.get() == nullptr) {
1079bdd1243dSDimitry Andric     CILine = llvm::ConstantInt::get(I.getContext(), llvm::APInt(32, 0));
1080bdd1243dSDimitry Andric     FilePathPtr = IRB.CreateGlobalStringPtr(
1081bdd1243dSDimitry Andric         I.getFunction()->getParent()->getSourceFileName());
1082bdd1243dSDimitry Andric   } else {
1083bdd1243dSDimitry Andric     CILine = llvm::ConstantInt::get(I.getContext(),
1084bdd1243dSDimitry Andric                                     llvm::APInt(32, dbgloc.getLine()));
1085bdd1243dSDimitry Andric     FilePathPtr =
1086bdd1243dSDimitry Andric         IRB.CreateGlobalStringPtr(dbgloc->getFilename());
1087bdd1243dSDimitry Andric   }
1088bdd1243dSDimitry Andric 
1089bdd1243dSDimitry Andric   llvm::Value *FunctionNamePtr =
1090bdd1243dSDimitry Andric       IRB.CreateGlobalStringPtr(I.getFunction()->getName());
1091bdd1243dSDimitry Andric 
1092bdd1243dSDimitry Andric   CallInst *CB;
1093bdd1243dSDimitry Andric   std::vector<Value *> args;
1094bdd1243dSDimitry Andric 
1095bdd1243dSDimitry Andric   if (DFS.shouldTrackOrigins()) {
1096bdd1243dSDimitry Andric     Value *DataOrigin = getOrigin(Data);
1097bdd1243dSDimitry Andric     args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1098bdd1243dSDimitry Andric     CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn, args);
1099bdd1243dSDimitry Andric   } else {
1100bdd1243dSDimitry Andric     args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1101bdd1243dSDimitry Andric     CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackFn, args);
1102bdd1243dSDimitry Andric   }
1103bdd1243dSDimitry Andric   CB->addParamAttr(0, Attribute::ZExt);
1104bdd1243dSDimitry Andric   CB->setDebugLoc(dbgloc);
110504eeddc0SDimitry Andric }
110604eeddc0SDimitry Andric 
1107e8d8bef9SDimitry Andric Type *DataFlowSanitizer::getShadowTy(Type *OrigTy) {
1108e8d8bef9SDimitry Andric   if (!OrigTy->isSized())
1109e8d8bef9SDimitry Andric     return PrimitiveShadowTy;
1110e8d8bef9SDimitry Andric   if (isa<IntegerType>(OrigTy))
1111e8d8bef9SDimitry Andric     return PrimitiveShadowTy;
1112e8d8bef9SDimitry Andric   if (isa<VectorType>(OrigTy))
1113e8d8bef9SDimitry Andric     return PrimitiveShadowTy;
1114e8d8bef9SDimitry Andric   if (ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1115e8d8bef9SDimitry Andric     return ArrayType::get(getShadowTy(AT->getElementType()),
1116e8d8bef9SDimitry Andric                           AT->getNumElements());
1117e8d8bef9SDimitry Andric   if (StructType *ST = dyn_cast<StructType>(OrigTy)) {
1118e8d8bef9SDimitry Andric     SmallVector<Type *, 4> Elements;
1119e8d8bef9SDimitry Andric     for (unsigned I = 0, N = ST->getNumElements(); I < N; ++I)
1120e8d8bef9SDimitry Andric       Elements.push_back(getShadowTy(ST->getElementType(I)));
1121e8d8bef9SDimitry Andric     return StructType::get(*Ctx, Elements);
1122e8d8bef9SDimitry Andric   }
1123e8d8bef9SDimitry Andric   return PrimitiveShadowTy;
1124e8d8bef9SDimitry Andric }
1125e8d8bef9SDimitry Andric 
1126e8d8bef9SDimitry Andric Type *DataFlowSanitizer::getShadowTy(Value *V) {
1127e8d8bef9SDimitry Andric   return getShadowTy(V->getType());
1128e8d8bef9SDimitry Andric }
1129e8d8bef9SDimitry Andric 
1130fe6060f1SDimitry Andric bool DataFlowSanitizer::initializeModule(Module &M) {
11310b57cec5SDimitry Andric   Triple TargetTriple(M.getTargetTriple());
11320b57cec5SDimitry Andric   const DataLayout &DL = M.getDataLayout();
11330b57cec5SDimitry Andric 
1134fe6060f1SDimitry Andric   if (TargetTriple.getOS() != Triple::Linux)
1135fe6060f1SDimitry Andric     report_fatal_error("unsupported operating system");
1136bdd1243dSDimitry Andric   switch (TargetTriple.getArch()) {
1137bdd1243dSDimitry Andric   case Triple::aarch64:
1138bdd1243dSDimitry Andric     MapParams = &Linux_AArch64_MemoryMapParams;
1139bdd1243dSDimitry Andric     break;
1140bdd1243dSDimitry Andric   case Triple::x86_64:
1141fe6060f1SDimitry Andric     MapParams = &Linux_X86_64_MemoryMapParams;
1142bdd1243dSDimitry Andric     break;
114306c3fb27SDimitry Andric   case Triple::loongarch64:
114406c3fb27SDimitry Andric     MapParams = &Linux_LoongArch64_MemoryMapParams;
114506c3fb27SDimitry Andric     break;
1146bdd1243dSDimitry Andric   default:
1147bdd1243dSDimitry Andric     report_fatal_error("unsupported architecture");
1148bdd1243dSDimitry Andric   }
1149fe6060f1SDimitry Andric 
11500b57cec5SDimitry Andric   Mod = &M;
11510b57cec5SDimitry Andric   Ctx = &M.getContext();
11525f757f3fSDimitry Andric   Int8Ptr = PointerType::getUnqual(*Ctx);
1153fe6060f1SDimitry Andric   OriginTy = IntegerType::get(*Ctx, OriginWidthBits);
1154fe6060f1SDimitry Andric   OriginPtrTy = PointerType::getUnqual(OriginTy);
1155e8d8bef9SDimitry Andric   PrimitiveShadowTy = IntegerType::get(*Ctx, ShadowWidthBits);
1156e8d8bef9SDimitry Andric   PrimitiveShadowPtrTy = PointerType::getUnqual(PrimitiveShadowTy);
11570b57cec5SDimitry Andric   IntptrTy = DL.getIntPtrType(*Ctx);
1158e8d8bef9SDimitry Andric   ZeroPrimitiveShadow = ConstantInt::getSigned(PrimitiveShadowTy, 0);
1159fe6060f1SDimitry Andric   ZeroOrigin = ConstantInt::getSigned(OriginTy, 0);
11600b57cec5SDimitry Andric 
1161e8d8bef9SDimitry Andric   Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1162e8d8bef9SDimitry Andric   DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1163e8d8bef9SDimitry Andric                                          /*isVarArg=*/false);
1164fe6060f1SDimitry Andric   Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1165fe6060f1SDimitry Andric   DFSanLoadLabelAndOriginFnTy =
1166fe6060f1SDimitry Andric       FunctionType::get(IntegerType::get(*Ctx, 64), DFSanLoadLabelAndOriginArgs,
1167fe6060f1SDimitry Andric                         /*isVarArg=*/false);
11680b57cec5SDimitry Andric   DFSanUnimplementedFnTy = FunctionType::get(
11695f757f3fSDimitry Andric       Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx), /*isVarArg=*/false);
117081ad6265SDimitry Andric   Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
117181ad6265SDimitry Andric   DFSanWrapperExternWeakNullFnTy =
117281ad6265SDimitry Andric       FunctionType::get(Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
117381ad6265SDimitry Andric                         /*isVarArg=*/false);
1174fe6060f1SDimitry Andric   Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
11755f757f3fSDimitry Andric                                 PointerType::getUnqual(*Ctx), IntptrTy};
11760b57cec5SDimitry Andric   DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
11770b57cec5SDimitry Andric                                         DFSanSetLabelArgs, /*isVarArg=*/false);
1178bdd1243dSDimitry Andric   DFSanNonzeroLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx), std::nullopt,
1179bdd1243dSDimitry Andric                                             /*isVarArg=*/false);
11800b57cec5SDimitry Andric   DFSanVarargWrapperFnTy = FunctionType::get(
11815f757f3fSDimitry Andric       Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx), /*isVarArg=*/false);
118204eeddc0SDimitry Andric   DFSanConditionalCallbackFnTy =
118304eeddc0SDimitry Andric       FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
118404eeddc0SDimitry Andric                         /*isVarArg=*/false);
118504eeddc0SDimitry Andric   Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
118604eeddc0SDimitry Andric   DFSanConditionalCallbackOriginFnTy = FunctionType::get(
118704eeddc0SDimitry Andric       Type::getVoidTy(*Ctx), DFSanConditionalCallbackOriginArgs,
118804eeddc0SDimitry Andric       /*isVarArg=*/false);
1189bdd1243dSDimitry Andric   Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1190bdd1243dSDimitry Andric                                                OriginTy, Int8Ptr};
1191bdd1243dSDimitry Andric   DFSanReachesFunctionCallbackFnTy =
1192bdd1243dSDimitry Andric       FunctionType::get(Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1193bdd1243dSDimitry Andric                         /*isVarArg=*/false);
1194bdd1243dSDimitry Andric   Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1195bdd1243dSDimitry Andric       PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1196bdd1243dSDimitry Andric   DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1197bdd1243dSDimitry Andric       Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackOriginArgs,
1198bdd1243dSDimitry Andric       /*isVarArg=*/false);
1199e8d8bef9SDimitry Andric   DFSanCmpCallbackFnTy =
1200e8d8bef9SDimitry Andric       FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1201e8d8bef9SDimitry Andric                         /*isVarArg=*/false);
1202fe6060f1SDimitry Andric   DFSanChainOriginFnTy =
1203fe6060f1SDimitry Andric       FunctionType::get(OriginTy, OriginTy, /*isVarArg=*/false);
1204fe6060f1SDimitry Andric   Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1205fe6060f1SDimitry Andric   DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1206fe6060f1SDimitry Andric       OriginTy, DFSanChainOriginIfTaintedArgs, /*isVarArg=*/false);
1207fe6060f1SDimitry Andric   Type *DFSanMaybeStoreOriginArgs[4] = {IntegerType::get(*Ctx, ShadowWidthBits),
1208fe6060f1SDimitry Andric                                         Int8Ptr, IntptrTy, OriginTy};
1209fe6060f1SDimitry Andric   DFSanMaybeStoreOriginFnTy = FunctionType::get(
1210fe6060f1SDimitry Andric       Type::getVoidTy(*Ctx), DFSanMaybeStoreOriginArgs, /*isVarArg=*/false);
1211fe6060f1SDimitry Andric   Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1212fe6060f1SDimitry Andric   DFSanMemOriginTransferFnTy = FunctionType::get(
1213fe6060f1SDimitry Andric       Type::getVoidTy(*Ctx), DFSanMemOriginTransferArgs, /*isVarArg=*/false);
1214bdd1243dSDimitry Andric   Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1215bdd1243dSDimitry Andric   DFSanMemShadowOriginTransferFnTy =
1216bdd1243dSDimitry Andric       FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1217bdd1243dSDimitry Andric                         /*isVarArg=*/false);
1218bdd1243dSDimitry Andric   Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1219bdd1243dSDimitry Andric       IntegerType::get(*Ctx, 8), Int8Ptr, Int8Ptr, Int8Ptr, IntptrTy};
1220bdd1243dSDimitry Andric   DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1221bdd1243dSDimitry Andric       Type::getVoidTy(*Ctx), DFSanMemShadowOriginConditionalExchangeArgs,
1222bdd1243dSDimitry Andric       /*isVarArg=*/false);
1223e8d8bef9SDimitry Andric   Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1224e8d8bef9SDimitry Andric   DFSanLoadStoreCallbackFnTy =
1225e8d8bef9SDimitry Andric       FunctionType::get(Type::getVoidTy(*Ctx), DFSanLoadStoreCallbackArgs,
1226e8d8bef9SDimitry Andric                         /*isVarArg=*/false);
1227e8d8bef9SDimitry Andric   Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
12285ffd83dbSDimitry Andric   DFSanMemTransferCallbackFnTy =
12295ffd83dbSDimitry Andric       FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
12305ffd83dbSDimitry Andric                         /*isVarArg=*/false);
12310b57cec5SDimitry Andric 
1232*0fca6ea1SDimitry Andric   ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1233*0fca6ea1SDimitry Andric   OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
12340b57cec5SDimitry Andric   return true;
12350b57cec5SDimitry Andric }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric bool DataFlowSanitizer::isInstrumented(const Function *F) {
12380b57cec5SDimitry Andric   return !ABIList.isIn(*F, "uninstrumented");
12390b57cec5SDimitry Andric }
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric bool DataFlowSanitizer::isInstrumented(const GlobalAlias *GA) {
12420b57cec5SDimitry Andric   return !ABIList.isIn(*GA, "uninstrumented");
12430b57cec5SDimitry Andric }
12440b57cec5SDimitry Andric 
1245349cc55cSDimitry Andric bool DataFlowSanitizer::isForceZeroLabels(const Function *F) {
1246349cc55cSDimitry Andric   return ABIList.isIn(*F, "force_zero_labels");
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(Function *F) {
12500b57cec5SDimitry Andric   if (ABIList.isIn(*F, "functional"))
12510b57cec5SDimitry Andric     return WK_Functional;
12520b57cec5SDimitry Andric   if (ABIList.isIn(*F, "discard"))
12530b57cec5SDimitry Andric     return WK_Discard;
12540b57cec5SDimitry Andric   if (ABIList.isIn(*F, "custom"))
12550b57cec5SDimitry Andric     return WK_Custom;
12560b57cec5SDimitry Andric 
12570b57cec5SDimitry Andric   return WK_Warning;
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
1260fe6060f1SDimitry Andric void DataFlowSanitizer::addGlobalNameSuffix(GlobalValue *GV) {
1261fe6060f1SDimitry Andric   std::string GVName = std::string(GV->getName()), Suffix = ".dfsan";
1262fe6060f1SDimitry Andric   GV->setName(GVName + Suffix);
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric   // Try to change the name of the function in module inline asm.  We only do
12650b57cec5SDimitry Andric   // this for specific asm directives, currently only ".symver", to try to avoid
12660b57cec5SDimitry Andric   // corrupting asm which happens to contain the symbol name as a substring.
12670b57cec5SDimitry Andric   // Note that the substitution for .symver assumes that the versioned symbol
12680b57cec5SDimitry Andric   // also has an instrumented name.
12690b57cec5SDimitry Andric   std::string Asm = GV->getParent()->getModuleInlineAsm();
12700b57cec5SDimitry Andric   std::string SearchStr = ".symver " + GVName + ",";
12710b57cec5SDimitry Andric   size_t Pos = Asm.find(SearchStr);
12720b57cec5SDimitry Andric   if (Pos != std::string::npos) {
1273fe6060f1SDimitry Andric     Asm.replace(Pos, SearchStr.size(), ".symver " + GVName + Suffix + ",");
127406c3fb27SDimitry Andric     Pos = Asm.find('@');
1275fe6060f1SDimitry Andric 
1276fe6060f1SDimitry Andric     if (Pos == std::string::npos)
1277349cc55cSDimitry Andric       report_fatal_error(Twine("unsupported .symver: ", Asm));
1278fe6060f1SDimitry Andric 
1279fe6060f1SDimitry Andric     Asm.replace(Pos, 1, Suffix + "@");
12800b57cec5SDimitry Andric     GV->getParent()->setModuleInlineAsm(Asm);
12810b57cec5SDimitry Andric   }
12820b57cec5SDimitry Andric }
12830b57cec5SDimitry Andric 
128481ad6265SDimitry Andric void DataFlowSanitizer::buildExternWeakCheckIfNeeded(IRBuilder<> &IRB,
128581ad6265SDimitry Andric                                                      Function *F) {
128681ad6265SDimitry Andric   // If the function we are wrapping was ExternWeak, it may be null.
128781ad6265SDimitry Andric   // The original code before calling this wrapper may have checked for null,
128881ad6265SDimitry Andric   // but replacing with a known-to-not-be-null wrapper can break this check.
128981ad6265SDimitry Andric   // When replacing uses of the extern weak function with the wrapper we try
129081ad6265SDimitry Andric   // to avoid replacing uses in conditionals, but this is not perfect.
1291bdd1243dSDimitry Andric   // In the case where we fail, and accidentally optimize out a null check
129281ad6265SDimitry Andric   // for a extern weak function, add a check here to help identify the issue.
129381ad6265SDimitry Andric   if (GlobalValue::isExternalWeakLinkage(F->getLinkage())) {
129481ad6265SDimitry Andric     std::vector<Value *> Args;
12955f757f3fSDimitry Andric     Args.push_back(F);
129681ad6265SDimitry Andric     Args.push_back(IRB.CreateGlobalStringPtr(F->getName()));
129781ad6265SDimitry Andric     IRB.CreateCall(DFSanWrapperExternWeakNullFn, Args);
129881ad6265SDimitry Andric   }
129981ad6265SDimitry Andric }
130081ad6265SDimitry Andric 
13010b57cec5SDimitry Andric Function *
13020b57cec5SDimitry Andric DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName,
13030b57cec5SDimitry Andric                                         GlobalValue::LinkageTypes NewFLink,
13040b57cec5SDimitry Andric                                         FunctionType *NewFT) {
13050b57cec5SDimitry Andric   FunctionType *FT = F->getFunctionType();
13060b57cec5SDimitry Andric   Function *NewF = Function::Create(NewFT, NewFLink, F->getAddressSpace(),
13070b57cec5SDimitry Andric                                     NewFName, F->getParent());
13080b57cec5SDimitry Andric   NewF->copyAttributesFrom(F);
1309349cc55cSDimitry Andric   NewF->removeRetAttrs(
13100b57cec5SDimitry Andric       AttributeFuncs::typeIncompatible(NewFT->getReturnType()));
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric   BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", NewF);
13130b57cec5SDimitry Andric   if (F->isVarArg()) {
13140eae32dcSDimitry Andric     NewF->removeFnAttr("split-stack");
13150b57cec5SDimitry Andric     CallInst::Create(DFSanVarargWrapperFn,
13160b57cec5SDimitry Andric                      IRBuilder<>(BB).CreateGlobalStringPtr(F->getName()), "",
13170b57cec5SDimitry Andric                      BB);
13180b57cec5SDimitry Andric     new UnreachableInst(*Ctx, BB);
13190b57cec5SDimitry Andric   } else {
1320fe6060f1SDimitry Andric     auto ArgIt = pointer_iterator<Argument *>(NewF->arg_begin());
1321fe6060f1SDimitry Andric     std::vector<Value *> Args(ArgIt, ArgIt + FT->getNumParams());
1322fe6060f1SDimitry Andric 
13230b57cec5SDimitry Andric     CallInst *CI = CallInst::Create(F, Args, "", BB);
13240b57cec5SDimitry Andric     if (FT->getReturnType()->isVoidTy())
13250b57cec5SDimitry Andric       ReturnInst::Create(*Ctx, BB);
13260b57cec5SDimitry Andric     else
13270b57cec5SDimitry Andric       ReturnInst::Create(*Ctx, CI, BB);
13280b57cec5SDimitry Andric   }
13290b57cec5SDimitry Andric 
13300b57cec5SDimitry Andric   return NewF;
13310b57cec5SDimitry Andric }
13320b57cec5SDimitry Andric 
13335ffd83dbSDimitry Andric // Initialize DataFlowSanitizer runtime functions and declare them in the module
13345ffd83dbSDimitry Andric void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
1335bdd1243dSDimitry Andric   LLVMContext &C = M.getContext();
13360b57cec5SDimitry Andric   {
13370b57cec5SDimitry Andric     AttributeList AL;
1338bdd1243dSDimitry Andric     AL = AL.addFnAttribute(C, Attribute::NoUnwind);
1339bdd1243dSDimitry Andric     AL = AL.addFnAttribute(
1340bdd1243dSDimitry Andric         C, Attribute::getWithMemoryEffects(C, MemoryEffects::readOnly()));
1341bdd1243dSDimitry Andric     AL = AL.addRetAttribute(C, Attribute::ZExt);
13420b57cec5SDimitry Andric     DFSanUnionLoadFn =
13430b57cec5SDimitry Andric         Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy, AL);
13440b57cec5SDimitry Andric   }
1345e8d8bef9SDimitry Andric   {
1346e8d8bef9SDimitry Andric     AttributeList AL;
1347bdd1243dSDimitry Andric     AL = AL.addFnAttribute(C, Attribute::NoUnwind);
1348bdd1243dSDimitry Andric     AL = AL.addFnAttribute(
1349bdd1243dSDimitry Andric         C, Attribute::getWithMemoryEffects(C, MemoryEffects::readOnly()));
1350bdd1243dSDimitry Andric     AL = AL.addRetAttribute(C, Attribute::ZExt);
1351fe6060f1SDimitry Andric     DFSanLoadLabelAndOriginFn = Mod->getOrInsertFunction(
1352fe6060f1SDimitry Andric         "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1353e8d8bef9SDimitry Andric   }
13540b57cec5SDimitry Andric   DFSanUnimplementedFn =
13550b57cec5SDimitry Andric       Mod->getOrInsertFunction("__dfsan_unimplemented", DFSanUnimplementedFnTy);
135681ad6265SDimitry Andric   DFSanWrapperExternWeakNullFn = Mod->getOrInsertFunction(
135781ad6265SDimitry Andric       "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
13580b57cec5SDimitry Andric   {
13590b57cec5SDimitry Andric     AttributeList AL;
13600b57cec5SDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1361fe6060f1SDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
13620b57cec5SDimitry Andric     DFSanSetLabelFn =
13630b57cec5SDimitry Andric         Mod->getOrInsertFunction("__dfsan_set_label", DFSanSetLabelFnTy, AL);
13640b57cec5SDimitry Andric   }
13650b57cec5SDimitry Andric   DFSanNonzeroLabelFn =
13660b57cec5SDimitry Andric       Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
13670b57cec5SDimitry Andric   DFSanVarargWrapperFn = Mod->getOrInsertFunction("__dfsan_vararg_wrapper",
13680b57cec5SDimitry Andric                                                   DFSanVarargWrapperFnTy);
1369fe6060f1SDimitry Andric   {
1370fe6060f1SDimitry Andric     AttributeList AL;
1371fe6060f1SDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1372349cc55cSDimitry Andric     AL = AL.addRetAttribute(M.getContext(), Attribute::ZExt);
1373fe6060f1SDimitry Andric     DFSanChainOriginFn = Mod->getOrInsertFunction("__dfsan_chain_origin",
1374fe6060f1SDimitry Andric                                                   DFSanChainOriginFnTy, AL);
1375fe6060f1SDimitry Andric   }
1376fe6060f1SDimitry Andric   {
1377fe6060f1SDimitry Andric     AttributeList AL;
1378fe6060f1SDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1379fe6060f1SDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
1380349cc55cSDimitry Andric     AL = AL.addRetAttribute(M.getContext(), Attribute::ZExt);
1381fe6060f1SDimitry Andric     DFSanChainOriginIfTaintedFn = Mod->getOrInsertFunction(
1382fe6060f1SDimitry Andric         "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1383fe6060f1SDimitry Andric   }
1384fe6060f1SDimitry Andric   DFSanMemOriginTransferFn = Mod->getOrInsertFunction(
1385fe6060f1SDimitry Andric       "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1386fe6060f1SDimitry Andric 
1387bdd1243dSDimitry Andric   DFSanMemShadowOriginTransferFn = Mod->getOrInsertFunction(
1388bdd1243dSDimitry Andric       "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1389bdd1243dSDimitry Andric 
1390bdd1243dSDimitry Andric   DFSanMemShadowOriginConditionalExchangeFn =
1391bdd1243dSDimitry Andric       Mod->getOrInsertFunction("__dfsan_mem_shadow_origin_conditional_exchange",
1392bdd1243dSDimitry Andric                                DFSanMemShadowOriginConditionalExchangeFnTy);
1393bdd1243dSDimitry Andric 
1394fe6060f1SDimitry Andric   {
1395fe6060f1SDimitry Andric     AttributeList AL;
1396fe6060f1SDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1397fe6060f1SDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 3, Attribute::ZExt);
1398fe6060f1SDimitry Andric     DFSanMaybeStoreOriginFn = Mod->getOrInsertFunction(
1399fe6060f1SDimitry Andric         "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1400fe6060f1SDimitry Andric   }
1401fe6060f1SDimitry Andric 
1402fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1403fe6060f1SDimitry Andric       DFSanUnionLoadFn.getCallee()->stripPointerCasts());
1404fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1405fe6060f1SDimitry Andric       DFSanLoadLabelAndOriginFn.getCallee()->stripPointerCasts());
1406fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1407fe6060f1SDimitry Andric       DFSanUnimplementedFn.getCallee()->stripPointerCasts());
1408fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
140981ad6265SDimitry Andric       DFSanWrapperExternWeakNullFn.getCallee()->stripPointerCasts());
141081ad6265SDimitry Andric   DFSanRuntimeFunctions.insert(
1411fe6060f1SDimitry Andric       DFSanSetLabelFn.getCallee()->stripPointerCasts());
1412fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1413fe6060f1SDimitry Andric       DFSanNonzeroLabelFn.getCallee()->stripPointerCasts());
1414fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1415fe6060f1SDimitry Andric       DFSanVarargWrapperFn.getCallee()->stripPointerCasts());
1416fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1417fe6060f1SDimitry Andric       DFSanLoadCallbackFn.getCallee()->stripPointerCasts());
1418fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1419fe6060f1SDimitry Andric       DFSanStoreCallbackFn.getCallee()->stripPointerCasts());
1420fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1421fe6060f1SDimitry Andric       DFSanMemTransferCallbackFn.getCallee()->stripPointerCasts());
1422fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
142304eeddc0SDimitry Andric       DFSanConditionalCallbackFn.getCallee()->stripPointerCasts());
142404eeddc0SDimitry Andric   DFSanRuntimeFunctions.insert(
142504eeddc0SDimitry Andric       DFSanConditionalCallbackOriginFn.getCallee()->stripPointerCasts());
142604eeddc0SDimitry Andric   DFSanRuntimeFunctions.insert(
1427bdd1243dSDimitry Andric       DFSanReachesFunctionCallbackFn.getCallee()->stripPointerCasts());
1428bdd1243dSDimitry Andric   DFSanRuntimeFunctions.insert(
1429bdd1243dSDimitry Andric       DFSanReachesFunctionCallbackOriginFn.getCallee()->stripPointerCasts());
1430bdd1243dSDimitry Andric   DFSanRuntimeFunctions.insert(
1431fe6060f1SDimitry Andric       DFSanCmpCallbackFn.getCallee()->stripPointerCasts());
1432fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1433fe6060f1SDimitry Andric       DFSanChainOriginFn.getCallee()->stripPointerCasts());
1434fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1435fe6060f1SDimitry Andric       DFSanChainOriginIfTaintedFn.getCallee()->stripPointerCasts());
1436fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1437fe6060f1SDimitry Andric       DFSanMemOriginTransferFn.getCallee()->stripPointerCasts());
1438fe6060f1SDimitry Andric   DFSanRuntimeFunctions.insert(
1439bdd1243dSDimitry Andric       DFSanMemShadowOriginTransferFn.getCallee()->stripPointerCasts());
1440bdd1243dSDimitry Andric   DFSanRuntimeFunctions.insert(
1441bdd1243dSDimitry Andric       DFSanMemShadowOriginConditionalExchangeFn.getCallee()
1442bdd1243dSDimitry Andric           ->stripPointerCasts());
1443bdd1243dSDimitry Andric   DFSanRuntimeFunctions.insert(
1444fe6060f1SDimitry Andric       DFSanMaybeStoreOriginFn.getCallee()->stripPointerCasts());
14455ffd83dbSDimitry Andric }
14465ffd83dbSDimitry Andric 
14475ffd83dbSDimitry Andric // Initializes event callback functions and declare them in the module
14485ffd83dbSDimitry Andric void DataFlowSanitizer::initializeCallbackFunctions(Module &M) {
1449bdd1243dSDimitry Andric   {
1450bdd1243dSDimitry Andric     AttributeList AL;
1451bdd1243dSDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1452bdd1243dSDimitry Andric     DFSanLoadCallbackFn = Mod->getOrInsertFunction(
1453bdd1243dSDimitry Andric         "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1454bdd1243dSDimitry Andric   }
1455bdd1243dSDimitry Andric   {
1456bdd1243dSDimitry Andric     AttributeList AL;
1457bdd1243dSDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1458bdd1243dSDimitry Andric     DFSanStoreCallbackFn = Mod->getOrInsertFunction(
1459bdd1243dSDimitry Andric         "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1460bdd1243dSDimitry Andric   }
14615ffd83dbSDimitry Andric   DFSanMemTransferCallbackFn = Mod->getOrInsertFunction(
14625ffd83dbSDimitry Andric       "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1463bdd1243dSDimitry Andric   {
1464bdd1243dSDimitry Andric     AttributeList AL;
1465bdd1243dSDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1466bdd1243dSDimitry Andric     DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback",
1467bdd1243dSDimitry Andric                                                   DFSanCmpCallbackFnTy, AL);
1468bdd1243dSDimitry Andric   }
1469bdd1243dSDimitry Andric   {
1470bdd1243dSDimitry Andric     AttributeList AL;
1471bdd1243dSDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
147204eeddc0SDimitry Andric     DFSanConditionalCallbackFn = Mod->getOrInsertFunction(
1473bdd1243dSDimitry Andric         "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1474bdd1243dSDimitry Andric   }
1475bdd1243dSDimitry Andric   {
1476bdd1243dSDimitry Andric     AttributeList AL;
1477bdd1243dSDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
147804eeddc0SDimitry Andric     DFSanConditionalCallbackOriginFn =
147904eeddc0SDimitry Andric         Mod->getOrInsertFunction("__dfsan_conditional_callback_origin",
1480bdd1243dSDimitry Andric                                  DFSanConditionalCallbackOriginFnTy, AL);
1481bdd1243dSDimitry Andric   }
1482bdd1243dSDimitry Andric   {
1483bdd1243dSDimitry Andric     AttributeList AL;
1484bdd1243dSDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1485bdd1243dSDimitry Andric     DFSanReachesFunctionCallbackFn =
1486bdd1243dSDimitry Andric         Mod->getOrInsertFunction("__dfsan_reaches_function_callback",
1487bdd1243dSDimitry Andric                                  DFSanReachesFunctionCallbackFnTy, AL);
1488bdd1243dSDimitry Andric   }
1489bdd1243dSDimitry Andric   {
1490bdd1243dSDimitry Andric     AttributeList AL;
1491bdd1243dSDimitry Andric     AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1492bdd1243dSDimitry Andric     DFSanReachesFunctionCallbackOriginFn =
1493bdd1243dSDimitry Andric         Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin",
1494bdd1243dSDimitry Andric                                  DFSanReachesFunctionCallbackOriginFnTy, AL);
1495bdd1243dSDimitry Andric   }
14965ffd83dbSDimitry Andric }
14975ffd83dbSDimitry Andric 
1498bdd1243dSDimitry Andric bool DataFlowSanitizer::runImpl(
1499bdd1243dSDimitry Andric     Module &M, llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1500fe6060f1SDimitry Andric   initializeModule(M);
1501e8d8bef9SDimitry Andric 
15025ffd83dbSDimitry Andric   if (ABIList.isIn(M, "skip"))
15035ffd83dbSDimitry Andric     return false;
15045ffd83dbSDimitry Andric 
15055ffd83dbSDimitry Andric   const unsigned InitialGlobalSize = M.global_size();
15065ffd83dbSDimitry Andric   const unsigned InitialModuleSize = M.size();
15075ffd83dbSDimitry Andric 
15085ffd83dbSDimitry Andric   bool Changed = false;
15095ffd83dbSDimitry Andric 
1510fe6060f1SDimitry Andric   auto GetOrInsertGlobal = [this, &Changed](StringRef Name,
1511fe6060f1SDimitry Andric                                             Type *Ty) -> Constant * {
1512fe6060f1SDimitry Andric     Constant *C = Mod->getOrInsertGlobal(Name, Ty);
1513fe6060f1SDimitry Andric     if (GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
15145ffd83dbSDimitry Andric       Changed |= G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
15155ffd83dbSDimitry Andric       G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
15165ffd83dbSDimitry Andric     }
1517fe6060f1SDimitry Andric     return C;
1518fe6060f1SDimitry Andric   };
15195ffd83dbSDimitry Andric 
1520fe6060f1SDimitry Andric   // These globals must be kept in sync with the ones in dfsan.cpp.
1521fe6060f1SDimitry Andric   ArgTLS =
1522fe6060f1SDimitry Andric       GetOrInsertGlobal("__dfsan_arg_tls",
1523fe6060f1SDimitry Andric                         ArrayType::get(Type::getInt64Ty(*Ctx), ArgTLSSize / 8));
1524fe6060f1SDimitry Andric   RetvalTLS = GetOrInsertGlobal(
1525fe6060f1SDimitry Andric       "__dfsan_retval_tls",
1526fe6060f1SDimitry Andric       ArrayType::get(Type::getInt64Ty(*Ctx), RetvalTLSSize / 8));
1527fe6060f1SDimitry Andric   ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1528fe6060f1SDimitry Andric   ArgOriginTLS = GetOrInsertGlobal("__dfsan_arg_origin_tls", ArgOriginTLSTy);
1529fe6060f1SDimitry Andric   RetvalOriginTLS = GetOrInsertGlobal("__dfsan_retval_origin_tls", OriginTy);
1530fe6060f1SDimitry Andric 
1531fe6060f1SDimitry Andric   (void)Mod->getOrInsertGlobal("__dfsan_track_origins", OriginTy, [&] {
1532fe6060f1SDimitry Andric     Changed = true;
1533fe6060f1SDimitry Andric     return new GlobalVariable(
1534fe6060f1SDimitry Andric         M, OriginTy, true, GlobalValue::WeakODRLinkage,
1535fe6060f1SDimitry Andric         ConstantInt::getSigned(OriginTy,
1536fe6060f1SDimitry Andric                                shouldTrackOrigins() ? ClTrackOrigins : 0),
1537fe6060f1SDimitry Andric         "__dfsan_track_origins");
1538fe6060f1SDimitry Andric   });
1539fe6060f1SDimitry Andric 
15405ffd83dbSDimitry Andric   initializeCallbackFunctions(M);
15415ffd83dbSDimitry Andric   initializeRuntimeFunctions(M);
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric   std::vector<Function *> FnsToInstrument;
15440b57cec5SDimitry Andric   SmallPtrSet<Function *, 2> FnsWithNativeABI;
1545349cc55cSDimitry Andric   SmallPtrSet<Function *, 2> FnsWithForceZeroLabel;
15460eae32dcSDimitry Andric   SmallPtrSet<Constant *, 1> PersonalityFns;
1547fe6060f1SDimitry Andric   for (Function &F : M)
1548bdd1243dSDimitry Andric     if (!F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F) &&
1549*0fca6ea1SDimitry Andric         !LibAtomicFunction(F) &&
1550*0fca6ea1SDimitry Andric         !F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1551fe6060f1SDimitry Andric       FnsToInstrument.push_back(&F);
15520eae32dcSDimitry Andric       if (F.hasPersonalityFn())
15530eae32dcSDimitry Andric         PersonalityFns.insert(F.getPersonalityFn()->stripPointerCasts());
15540eae32dcSDimitry Andric     }
15550eae32dcSDimitry Andric 
15560eae32dcSDimitry Andric   if (ClIgnorePersonalityRoutine) {
15570eae32dcSDimitry Andric     for (auto *C : PersonalityFns) {
15580eae32dcSDimitry Andric       assert(isa<Function>(C) && "Personality routine is not a function!");
15590eae32dcSDimitry Andric       Function *F = cast<Function>(C);
15600eae32dcSDimitry Andric       if (!isInstrumented(F))
15615f757f3fSDimitry Andric         llvm::erase(FnsToInstrument, F);
15620eae32dcSDimitry Andric     }
15630eae32dcSDimitry Andric   }
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric   // Give function aliases prefixes when necessary, and build wrappers where the
15660b57cec5SDimitry Andric   // instrumentedness is inconsistent.
1567349cc55cSDimitry Andric   for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) {
15680b57cec5SDimitry Andric     // Don't stop on weak.  We assume people aren't playing games with the
15690b57cec5SDimitry Andric     // instrumentedness of overridden weak aliases.
1570349cc55cSDimitry Andric     auto *F = dyn_cast<Function>(GA.getAliaseeObject());
1571fe6060f1SDimitry Andric     if (!F)
1572fe6060f1SDimitry Andric       continue;
1573fe6060f1SDimitry Andric 
1574349cc55cSDimitry Andric     bool GAInst = isInstrumented(&GA), FInst = isInstrumented(F);
15750b57cec5SDimitry Andric     if (GAInst && FInst) {
1576349cc55cSDimitry Andric       addGlobalNameSuffix(&GA);
15770b57cec5SDimitry Andric     } else if (GAInst != FInst) {
15780b57cec5SDimitry Andric       // Non-instrumented alias of an instrumented function, or vice versa.
15790b57cec5SDimitry Andric       // Replace the alias with a native-ABI wrapper of the aliasee.  The pass
15800b57cec5SDimitry Andric       // below will take care of instrumenting it.
15810b57cec5SDimitry Andric       Function *NewF =
1582349cc55cSDimitry Andric           buildWrapperFunction(F, "", GA.getLinkage(), F->getFunctionType());
15835f757f3fSDimitry Andric       GA.replaceAllUsesWith(NewF);
1584349cc55cSDimitry Andric       NewF->takeName(&GA);
1585349cc55cSDimitry Andric       GA.eraseFromParent();
15860b57cec5SDimitry Andric       FnsToInstrument.push_back(NewF);
15870b57cec5SDimitry Andric     }
15880b57cec5SDimitry Andric   }
15890b57cec5SDimitry Andric 
1590bdd1243dSDimitry Andric   // TODO: This could be more precise.
1591bdd1243dSDimitry Andric   ReadOnlyNoneAttrs.addAttribute(Attribute::Memory);
15920b57cec5SDimitry Andric 
15930b57cec5SDimitry Andric   // First, change the ABI of every function in the module.  ABI-listed
15940b57cec5SDimitry Andric   // functions keep their original ABI and get a wrapper function.
1595fe6060f1SDimitry Andric   for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1596fe6060f1SDimitry Andric                                          FE = FnsToInstrument.end();
1597fe6060f1SDimitry Andric        FI != FE; ++FI) {
1598fe6060f1SDimitry Andric     Function &F = **FI;
15990b57cec5SDimitry Andric     FunctionType *FT = F.getFunctionType();
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric     bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
16020b57cec5SDimitry Andric                               FT->getReturnType()->isVoidTy());
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric     if (isInstrumented(&F)) {
1605349cc55cSDimitry Andric       if (isForceZeroLabels(&F))
1606349cc55cSDimitry Andric         FnsWithForceZeroLabel.insert(&F);
1607349cc55cSDimitry Andric 
1608fe6060f1SDimitry Andric       // Instrumented functions get a '.dfsan' suffix.  This allows us to more
1609fe6060f1SDimitry Andric       // easily identify cases of mismatching ABIs. This naming scheme is
1610fe6060f1SDimitry Andric       // mangling-compatible (see Itanium ABI), using a vendor-specific suffix.
1611fe6060f1SDimitry Andric       addGlobalNameSuffix(&F);
16120b57cec5SDimitry Andric     } else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
16130b57cec5SDimitry Andric       // Build a wrapper function for F.  The wrapper simply calls F, and is
16140b57cec5SDimitry Andric       // added to FnsToInstrument so that any instrumentation according to its
16150b57cec5SDimitry Andric       // WrapperKind is done in the second pass below.
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric       // If the function being wrapped has local linkage, then preserve the
16180b57cec5SDimitry Andric       // function's linkage in the wrapper function.
1619fe6060f1SDimitry Andric       GlobalValue::LinkageTypes WrapperLinkage =
1620fe6060f1SDimitry Andric           F.hasLocalLinkage() ? F.getLinkage()
16210b57cec5SDimitry Andric                               : GlobalValue::LinkOnceODRLinkage;
16220b57cec5SDimitry Andric 
16230b57cec5SDimitry Andric       Function *NewF = buildWrapperFunction(
1624fe6060f1SDimitry Andric           &F,
1625fe6060f1SDimitry Andric           (shouldTrackOrigins() ? std::string("dfso$") : std::string("dfsw$")) +
1626fe6060f1SDimitry Andric               std::string(F.getName()),
1627349cc55cSDimitry Andric           WrapperLinkage, FT);
1628349cc55cSDimitry Andric       NewF->removeFnAttrs(ReadOnlyNoneAttrs);
16290b57cec5SDimitry Andric 
163081ad6265SDimitry Andric       // Extern weak functions can sometimes be null at execution time.
163181ad6265SDimitry Andric       // Code will sometimes check if an extern weak function is null.
163281ad6265SDimitry Andric       // This could look something like:
163381ad6265SDimitry Andric       //   declare extern_weak i8 @my_func(i8)
163481ad6265SDimitry Andric       //   br i1 icmp ne (i8 (i8)* @my_func, i8 (i8)* null), label %use_my_func,
163581ad6265SDimitry Andric       //   label %avoid_my_func
163681ad6265SDimitry Andric       // The @"dfsw$my_func" wrapper is never null, so if we replace this use
1637bdd1243dSDimitry Andric       // in the comparison, the icmp will simplify to false and we have
1638bdd1243dSDimitry Andric       // accidentally optimized away a null check that is necessary.
163981ad6265SDimitry Andric       // This can lead to a crash when the null extern_weak my_func is called.
164081ad6265SDimitry Andric       //
164181ad6265SDimitry Andric       // To prevent (the most common pattern of) this problem,
164281ad6265SDimitry Andric       // do not replace uses in comparisons with the wrapper.
164381ad6265SDimitry Andric       // We definitely want to replace uses in call instructions.
164481ad6265SDimitry Andric       // Other uses (e.g. store the function address somewhere) might be
164581ad6265SDimitry Andric       // called or compared or both - this case may not be handled correctly.
164681ad6265SDimitry Andric       // We will default to replacing with wrapper in cases we are unsure.
164781ad6265SDimitry Andric       auto IsNotCmpUse = [](Use &U) -> bool {
164881ad6265SDimitry Andric         User *Usr = U.getUser();
164981ad6265SDimitry Andric         if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
165081ad6265SDimitry Andric           // This is the most common case for icmp ne null
165181ad6265SDimitry Andric           if (CE->getOpcode() == Instruction::ICmp) {
165281ad6265SDimitry Andric             return false;
165381ad6265SDimitry Andric           }
165481ad6265SDimitry Andric         }
165581ad6265SDimitry Andric         if (Instruction *I = dyn_cast<Instruction>(Usr)) {
165681ad6265SDimitry Andric           if (I->getOpcode() == Instruction::ICmp) {
165781ad6265SDimitry Andric             return false;
165881ad6265SDimitry Andric           }
165981ad6265SDimitry Andric         }
166081ad6265SDimitry Andric         return true;
166181ad6265SDimitry Andric       };
16625f757f3fSDimitry Andric       F.replaceUsesWithIf(NewF, IsNotCmpUse);
16630b57cec5SDimitry Andric 
16645f757f3fSDimitry Andric       UnwrappedFnMap[NewF] = &F;
1665fe6060f1SDimitry Andric       *FI = NewF;
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric       if (!F.isDeclaration()) {
16680b57cec5SDimitry Andric         // This function is probably defining an interposition of an
16690b57cec5SDimitry Andric         // uninstrumented function and hence needs to keep the original ABI.
16700b57cec5SDimitry Andric         // But any functions it may call need to use the instrumented ABI, so
16710b57cec5SDimitry Andric         // we instrument it in a mode which preserves the original ABI.
16720b57cec5SDimitry Andric         FnsWithNativeABI.insert(&F);
16730b57cec5SDimitry Andric 
16740b57cec5SDimitry Andric         // This code needs to rebuild the iterators, as they may be invalidated
16750b57cec5SDimitry Andric         // by the push_back, taking care that the new range does not include
16760b57cec5SDimitry Andric         // any functions added by this code.
1677fe6060f1SDimitry Andric         size_t N = FI - FnsToInstrument.begin(),
1678fe6060f1SDimitry Andric                Count = FE - FnsToInstrument.begin();
16790b57cec5SDimitry Andric         FnsToInstrument.push_back(&F);
1680fe6060f1SDimitry Andric         FI = FnsToInstrument.begin() + N;
1681fe6060f1SDimitry Andric         FE = FnsToInstrument.begin() + Count;
16820b57cec5SDimitry Andric       }
16830b57cec5SDimitry Andric       // Hopefully, nobody will try to indirectly call a vararg
16840b57cec5SDimitry Andric       // function... yet.
16850b57cec5SDimitry Andric     } else if (FT->isVarArg()) {
16860b57cec5SDimitry Andric       UnwrappedFnMap[&F] = &F;
1687fe6060f1SDimitry Andric       *FI = nullptr;
16880b57cec5SDimitry Andric     }
16890b57cec5SDimitry Andric   }
16900b57cec5SDimitry Andric 
1691fe6060f1SDimitry Andric   for (Function *F : FnsToInstrument) {
1692fe6060f1SDimitry Andric     if (!F || F->isDeclaration())
16930b57cec5SDimitry Andric       continue;
16940b57cec5SDimitry Andric 
1695fe6060f1SDimitry Andric     removeUnreachableBlocks(*F);
16960b57cec5SDimitry Andric 
1697349cc55cSDimitry Andric     DFSanFunction DFSF(*this, F, FnsWithNativeABI.count(F),
1698bdd1243dSDimitry Andric                        FnsWithForceZeroLabel.count(F), GetTLI(*F));
1699bdd1243dSDimitry Andric 
1700bdd1243dSDimitry Andric     if (ClReachesFunctionCallbacks) {
1701bdd1243dSDimitry Andric       // Add callback for arguments reaching this function.
1702bdd1243dSDimitry Andric       for (auto &FArg : F->args()) {
1703bdd1243dSDimitry Andric         Instruction *Next = &F->getEntryBlock().front();
1704bdd1243dSDimitry Andric         Value *FArgShadow = DFSF.getShadow(&FArg);
1705bdd1243dSDimitry Andric         if (isZeroShadow(FArgShadow))
1706bdd1243dSDimitry Andric           continue;
1707bdd1243dSDimitry Andric         if (Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1708bdd1243dSDimitry Andric           Next = FArgShadowInst->getNextNode();
1709bdd1243dSDimitry Andric         }
1710bdd1243dSDimitry Andric         if (shouldTrackOrigins()) {
1711bdd1243dSDimitry Andric           if (Instruction *Origin =
1712bdd1243dSDimitry Andric                   dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1713bdd1243dSDimitry Andric             // Ensure IRB insertion point is after loads for shadow and origin.
1714bdd1243dSDimitry Andric             Instruction *OriginNext = Origin->getNextNode();
1715bdd1243dSDimitry Andric             if (Next->comesBefore(OriginNext)) {
1716bdd1243dSDimitry Andric               Next = OriginNext;
1717bdd1243dSDimitry Andric             }
1718bdd1243dSDimitry Andric           }
1719bdd1243dSDimitry Andric         }
1720bdd1243dSDimitry Andric         IRBuilder<> IRB(Next);
1721bdd1243dSDimitry Andric         DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1722bdd1243dSDimitry Andric       }
1723bdd1243dSDimitry Andric     }
17240b57cec5SDimitry Andric 
17250b57cec5SDimitry Andric     // DFSanVisitor may create new basic blocks, which confuses df_iterator.
17260b57cec5SDimitry Andric     // Build a copy of the list before iterating over it.
1727fe6060f1SDimitry Andric     SmallVector<BasicBlock *, 4> BBList(depth_first(&F->getEntryBlock()));
17280b57cec5SDimitry Andric 
1729fe6060f1SDimitry Andric     for (BasicBlock *BB : BBList) {
1730fe6060f1SDimitry Andric       Instruction *Inst = &BB->front();
17310b57cec5SDimitry Andric       while (true) {
17320b57cec5SDimitry Andric         // DFSanVisitor may split the current basic block, changing the current
17330b57cec5SDimitry Andric         // instruction's next pointer and moving the next instruction to the
17340b57cec5SDimitry Andric         // tail block from which we should continue.
17350b57cec5SDimitry Andric         Instruction *Next = Inst->getNextNode();
17360b57cec5SDimitry Andric         // DFSanVisitor may delete Inst, so keep track of whether it was a
17370b57cec5SDimitry Andric         // terminator.
17380b57cec5SDimitry Andric         bool IsTerminator = Inst->isTerminator();
17390b57cec5SDimitry Andric         if (!DFSF.SkipInsts.count(Inst))
17400b57cec5SDimitry Andric           DFSanVisitor(DFSF).visit(Inst);
17410b57cec5SDimitry Andric         if (IsTerminator)
17420b57cec5SDimitry Andric           break;
17430b57cec5SDimitry Andric         Inst = Next;
17440b57cec5SDimitry Andric       }
17450b57cec5SDimitry Andric     }
17460b57cec5SDimitry Andric 
17470b57cec5SDimitry Andric     // We will not necessarily be able to compute the shadow for every phi node
17480b57cec5SDimitry Andric     // until we have visited every block.  Therefore, the code that handles phi
17490b57cec5SDimitry Andric     // nodes adds them to the PHIFixups list so that they can be properly
17500b57cec5SDimitry Andric     // handled here.
1751fe6060f1SDimitry Andric     for (DFSanFunction::PHIFixupElement &P : DFSF.PHIFixups) {
1752fe6060f1SDimitry Andric       for (unsigned Val = 0, N = P.Phi->getNumIncomingValues(); Val != N;
1753fe6060f1SDimitry Andric            ++Val) {
1754fe6060f1SDimitry Andric         P.ShadowPhi->setIncomingValue(
1755fe6060f1SDimitry Andric             Val, DFSF.getShadow(P.Phi->getIncomingValue(Val)));
1756fe6060f1SDimitry Andric         if (P.OriginPhi)
1757fe6060f1SDimitry Andric           P.OriginPhi->setIncomingValue(
1758fe6060f1SDimitry Andric               Val, DFSF.getOrigin(P.Phi->getIncomingValue(Val)));
17590b57cec5SDimitry Andric       }
17600b57cec5SDimitry Andric     }
17610b57cec5SDimitry Andric 
17620b57cec5SDimitry Andric     // -dfsan-debug-nonzero-labels will split the CFG in all kinds of crazy
17630b57cec5SDimitry Andric     // places (i.e. instructions in basic blocks we haven't even begun visiting
17640b57cec5SDimitry Andric     // yet).  To make our life easier, do this work in a pass after the main
17650b57cec5SDimitry Andric     // instrumentation.
17660b57cec5SDimitry Andric     if (ClDebugNonzeroLabels) {
17670b57cec5SDimitry Andric       for (Value *V : DFSF.NonZeroChecks) {
1768*0fca6ea1SDimitry Andric         BasicBlock::iterator Pos;
17690b57cec5SDimitry Andric         if (Instruction *I = dyn_cast<Instruction>(V))
1770*0fca6ea1SDimitry Andric           Pos = std::next(I->getIterator());
17710b57cec5SDimitry Andric         else
1772*0fca6ea1SDimitry Andric           Pos = DFSF.F->getEntryBlock().begin();
17730b57cec5SDimitry Andric         while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1774*0fca6ea1SDimitry Andric           Pos = std::next(Pos->getIterator());
1775*0fca6ea1SDimitry Andric         IRBuilder<> IRB(Pos->getParent(), Pos);
1776e8d8bef9SDimitry Andric         Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1777e8d8bef9SDimitry Andric         Value *Ne =
1778e8d8bef9SDimitry Andric             IRB.CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
17790b57cec5SDimitry Andric         BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen(
17800b57cec5SDimitry Andric             Ne, Pos, /*Unreachable=*/false, ColdCallWeights));
17810b57cec5SDimitry Andric         IRBuilder<> ThenIRB(BI);
17820b57cec5SDimitry Andric         ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
17830b57cec5SDimitry Andric       }
17840b57cec5SDimitry Andric     }
17850b57cec5SDimitry Andric   }
17860b57cec5SDimitry Andric 
17875ffd83dbSDimitry Andric   return Changed || !FnsToInstrument.empty() ||
17885ffd83dbSDimitry Andric          M.global_size() != InitialGlobalSize || M.size() != InitialModuleSize;
17890b57cec5SDimitry Andric }
17900b57cec5SDimitry Andric 
1791e8d8bef9SDimitry Andric Value *DFSanFunction::getArgTLS(Type *T, unsigned ArgOffset, IRBuilder<> &IRB) {
1792e8d8bef9SDimitry Andric   Value *Base = IRB.CreatePointerCast(DFS.ArgTLS, DFS.IntptrTy);
1793e8d8bef9SDimitry Andric   if (ArgOffset)
1794e8d8bef9SDimitry Andric     Base = IRB.CreateAdd(Base, ConstantInt::get(DFS.IntptrTy, ArgOffset));
1795e8d8bef9SDimitry Andric   return IRB.CreateIntToPtr(Base, PointerType::get(DFS.getShadowTy(T), 0),
1796e8d8bef9SDimitry Andric                             "_dfsarg");
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric 
1799e8d8bef9SDimitry Andric Value *DFSanFunction::getRetvalTLS(Type *T, IRBuilder<> &IRB) {
1800e8d8bef9SDimitry Andric   return IRB.CreatePointerCast(
1801e8d8bef9SDimitry Andric       DFS.RetvalTLS, PointerType::get(DFS.getShadowTy(T), 0), "_dfsret");
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric 
1804fe6060f1SDimitry Andric Value *DFSanFunction::getRetvalOriginTLS() { return DFS.RetvalOriginTLS; }
1805fe6060f1SDimitry Andric 
1806fe6060f1SDimitry Andric Value *DFSanFunction::getArgOriginTLS(unsigned ArgNo, IRBuilder<> &IRB) {
1807*0fca6ea1SDimitry Andric   return IRB.CreateConstInBoundsGEP2_64(DFS.ArgOriginTLSTy, DFS.ArgOriginTLS, 0,
1808*0fca6ea1SDimitry Andric                                         ArgNo, "_dfsarg_o");
1809fe6060f1SDimitry Andric }
1810fe6060f1SDimitry Andric 
1811fe6060f1SDimitry Andric Value *DFSanFunction::getOrigin(Value *V) {
1812fe6060f1SDimitry Andric   assert(DFS.shouldTrackOrigins());
1813fe6060f1SDimitry Andric   if (!isa<Argument>(V) && !isa<Instruction>(V))
1814fe6060f1SDimitry Andric     return DFS.ZeroOrigin;
1815fe6060f1SDimitry Andric   Value *&Origin = ValOriginMap[V];
1816fe6060f1SDimitry Andric   if (!Origin) {
1817fe6060f1SDimitry Andric     if (Argument *A = dyn_cast<Argument>(V)) {
1818fe6060f1SDimitry Andric       if (IsNativeABI)
1819fe6060f1SDimitry Andric         return DFS.ZeroOrigin;
1820fe6060f1SDimitry Andric       if (A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1821fe6060f1SDimitry Andric         Instruction *ArgOriginTLSPos = &*F->getEntryBlock().begin();
1822fe6060f1SDimitry Andric         IRBuilder<> IRB(ArgOriginTLSPos);
1823fe6060f1SDimitry Andric         Value *ArgOriginPtr = getArgOriginTLS(A->getArgNo(), IRB);
1824fe6060f1SDimitry Andric         Origin = IRB.CreateLoad(DFS.OriginTy, ArgOriginPtr);
1825fe6060f1SDimitry Andric       } else {
1826fe6060f1SDimitry Andric         // Overflow
1827fe6060f1SDimitry Andric         Origin = DFS.ZeroOrigin;
1828fe6060f1SDimitry Andric       }
1829fe6060f1SDimitry Andric     } else {
1830fe6060f1SDimitry Andric       Origin = DFS.ZeroOrigin;
1831fe6060f1SDimitry Andric     }
1832fe6060f1SDimitry Andric   }
1833fe6060f1SDimitry Andric   return Origin;
1834fe6060f1SDimitry Andric }
1835fe6060f1SDimitry Andric 
1836fe6060f1SDimitry Andric void DFSanFunction::setOrigin(Instruction *I, Value *Origin) {
1837fe6060f1SDimitry Andric   if (!DFS.shouldTrackOrigins())
1838fe6060f1SDimitry Andric     return;
1839fe6060f1SDimitry Andric   assert(!ValOriginMap.count(I));
1840fe6060f1SDimitry Andric   assert(Origin->getType() == DFS.OriginTy);
1841fe6060f1SDimitry Andric   ValOriginMap[I] = Origin;
1842fe6060f1SDimitry Andric }
1843fe6060f1SDimitry Andric 
1844e8d8bef9SDimitry Andric Value *DFSanFunction::getShadowForTLSArgument(Argument *A) {
1845e8d8bef9SDimitry Andric   unsigned ArgOffset = 0;
1846*0fca6ea1SDimitry Andric   const DataLayout &DL = F->getDataLayout();
1847e8d8bef9SDimitry Andric   for (auto &FArg : F->args()) {
1848e8d8bef9SDimitry Andric     if (!FArg.getType()->isSized()) {
1849e8d8bef9SDimitry Andric       if (A == &FArg)
1850e8d8bef9SDimitry Andric         break;
1851e8d8bef9SDimitry Andric       continue;
1852e8d8bef9SDimitry Andric     }
1853e8d8bef9SDimitry Andric 
1854e8d8bef9SDimitry Andric     unsigned Size = DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1855e8d8bef9SDimitry Andric     if (A != &FArg) {
1856fe6060f1SDimitry Andric       ArgOffset += alignTo(Size, ShadowTLSAlignment);
1857fe6060f1SDimitry Andric       if (ArgOffset > ArgTLSSize)
1858e8d8bef9SDimitry Andric         break; // ArgTLS overflows, uses a zero shadow.
1859e8d8bef9SDimitry Andric       continue;
1860e8d8bef9SDimitry Andric     }
1861e8d8bef9SDimitry Andric 
1862fe6060f1SDimitry Andric     if (ArgOffset + Size > ArgTLSSize)
1863e8d8bef9SDimitry Andric       break; // ArgTLS overflows, uses a zero shadow.
1864e8d8bef9SDimitry Andric 
1865e8d8bef9SDimitry Andric     Instruction *ArgTLSPos = &*F->getEntryBlock().begin();
1866e8d8bef9SDimitry Andric     IRBuilder<> IRB(ArgTLSPos);
1867e8d8bef9SDimitry Andric     Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1868e8d8bef9SDimitry Andric     return IRB.CreateAlignedLoad(DFS.getShadowTy(&FArg), ArgShadowPtr,
1869fe6060f1SDimitry Andric                                  ShadowTLSAlignment);
1870e8d8bef9SDimitry Andric   }
1871e8d8bef9SDimitry Andric 
1872e8d8bef9SDimitry Andric   return DFS.getZeroShadow(A);
18730b57cec5SDimitry Andric }
18740b57cec5SDimitry Andric 
18750b57cec5SDimitry Andric Value *DFSanFunction::getShadow(Value *V) {
18760b57cec5SDimitry Andric   if (!isa<Argument>(V) && !isa<Instruction>(V))
1877e8d8bef9SDimitry Andric     return DFS.getZeroShadow(V);
1878349cc55cSDimitry Andric   if (IsForceZeroLabels)
1879349cc55cSDimitry Andric     return DFS.getZeroShadow(V);
18800b57cec5SDimitry Andric   Value *&Shadow = ValShadowMap[V];
18810b57cec5SDimitry Andric   if (!Shadow) {
18820b57cec5SDimitry Andric     if (Argument *A = dyn_cast<Argument>(V)) {
18830b57cec5SDimitry Andric       if (IsNativeABI)
1884e8d8bef9SDimitry Andric         return DFS.getZeroShadow(V);
1885e8d8bef9SDimitry Andric       Shadow = getShadowForTLSArgument(A);
18860b57cec5SDimitry Andric       NonZeroChecks.push_back(Shadow);
18870b57cec5SDimitry Andric     } else {
1888e8d8bef9SDimitry Andric       Shadow = DFS.getZeroShadow(V);
18890b57cec5SDimitry Andric     }
18900b57cec5SDimitry Andric   }
18910b57cec5SDimitry Andric   return Shadow;
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric void DFSanFunction::setShadow(Instruction *I, Value *Shadow) {
18950b57cec5SDimitry Andric   assert(!ValShadowMap.count(I));
18960b57cec5SDimitry Andric   ValShadowMap[I] = Shadow;
18970b57cec5SDimitry Andric }
18980b57cec5SDimitry Andric 
1899fe6060f1SDimitry Andric /// Compute the integer shadow offset that corresponds to a given
1900fe6060f1SDimitry Andric /// application address.
1901fe6060f1SDimitry Andric ///
1902fe6060f1SDimitry Andric /// Offset = (Addr & ~AndMask) ^ XorMask
1903fe6060f1SDimitry Andric Value *DataFlowSanitizer::getShadowOffset(Value *Addr, IRBuilder<> &IRB) {
19040b57cec5SDimitry Andric   assert(Addr != RetvalTLS && "Reinstrumenting?");
1905fe6060f1SDimitry Andric   Value *OffsetLong = IRB.CreatePointerCast(Addr, IntptrTy);
1906fe6060f1SDimitry Andric 
1907fe6060f1SDimitry Andric   uint64_t AndMask = MapParams->AndMask;
1908fe6060f1SDimitry Andric   if (AndMask)
1909fe6060f1SDimitry Andric     OffsetLong =
1910fe6060f1SDimitry Andric         IRB.CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1911fe6060f1SDimitry Andric 
1912fe6060f1SDimitry Andric   uint64_t XorMask = MapParams->XorMask;
1913fe6060f1SDimitry Andric   if (XorMask)
1914fe6060f1SDimitry Andric     OffsetLong = IRB.CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1915fe6060f1SDimitry Andric   return OffsetLong;
1916fe6060f1SDimitry Andric }
1917fe6060f1SDimitry Andric 
1918fe6060f1SDimitry Andric std::pair<Value *, Value *>
1919fe6060f1SDimitry Andric DataFlowSanitizer::getShadowOriginAddress(Value *Addr, Align InstAlignment,
1920*0fca6ea1SDimitry Andric                                           BasicBlock::iterator Pos) {
1921fe6060f1SDimitry Andric   // Returns ((Addr & shadow_mask) + origin_base - shadow_base) & ~4UL
1922*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
1923fe6060f1SDimitry Andric   Value *ShadowOffset = getShadowOffset(Addr, IRB);
1924fe6060f1SDimitry Andric   Value *ShadowLong = ShadowOffset;
1925fe6060f1SDimitry Andric   uint64_t ShadowBase = MapParams->ShadowBase;
1926fe6060f1SDimitry Andric   if (ShadowBase != 0) {
1927fe6060f1SDimitry Andric     ShadowLong =
1928fe6060f1SDimitry Andric         IRB.CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1929fe6060f1SDimitry Andric   }
1930fe6060f1SDimitry Andric   IntegerType *ShadowTy = IntegerType::get(*Ctx, ShadowWidthBits);
1931fe6060f1SDimitry Andric   Value *ShadowPtr =
1932fe6060f1SDimitry Andric       IRB.CreateIntToPtr(ShadowLong, PointerType::get(ShadowTy, 0));
1933fe6060f1SDimitry Andric   Value *OriginPtr = nullptr;
1934fe6060f1SDimitry Andric   if (shouldTrackOrigins()) {
1935fe6060f1SDimitry Andric     Value *OriginLong = ShadowOffset;
1936fe6060f1SDimitry Andric     uint64_t OriginBase = MapParams->OriginBase;
1937fe6060f1SDimitry Andric     if (OriginBase != 0)
1938fe6060f1SDimitry Andric       OriginLong =
1939fe6060f1SDimitry Andric           IRB.CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1940fe6060f1SDimitry Andric     const Align Alignment = llvm::assumeAligned(InstAlignment.value());
1941fe6060f1SDimitry Andric     // When alignment is >= 4, Addr must be aligned to 4, otherwise it is UB.
1942fe6060f1SDimitry Andric     // So Mask is unnecessary.
1943fe6060f1SDimitry Andric     if (Alignment < MinOriginAlignment) {
1944fe6060f1SDimitry Andric       uint64_t Mask = MinOriginAlignment.value() - 1;
1945fe6060f1SDimitry Andric       OriginLong = IRB.CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1946fe6060f1SDimitry Andric     }
1947fe6060f1SDimitry Andric     OriginPtr = IRB.CreateIntToPtr(OriginLong, OriginPtrTy);
1948fe6060f1SDimitry Andric   }
1949fe6060f1SDimitry Andric   return std::make_pair(ShadowPtr, OriginPtr);
1950fe6060f1SDimitry Andric }
1951fe6060f1SDimitry Andric 
1952*0fca6ea1SDimitry Andric Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
1953*0fca6ea1SDimitry Andric                                            BasicBlock::iterator Pos,
1954fe6060f1SDimitry Andric                                            Value *ShadowOffset) {
1955*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
1956fe6060f1SDimitry Andric   return IRB.CreateIntToPtr(ShadowOffset, PrimitiveShadowPtrTy);
1957fe6060f1SDimitry Andric }
1958fe6060f1SDimitry Andric 
1959*0fca6ea1SDimitry Andric Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
1960*0fca6ea1SDimitry Andric                                            BasicBlock::iterator Pos) {
1961*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
1962fe6060f1SDimitry Andric   Value *ShadowOffset = getShadowOffset(Addr, IRB);
1963fe6060f1SDimitry Andric   return getShadowAddress(Addr, Pos, ShadowOffset);
1964e8d8bef9SDimitry Andric }
1965e8d8bef9SDimitry Andric 
1966e8d8bef9SDimitry Andric Value *DFSanFunction::combineShadowsThenConvert(Type *T, Value *V1, Value *V2,
1967*0fca6ea1SDimitry Andric                                                 BasicBlock::iterator Pos) {
1968e8d8bef9SDimitry Andric   Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1969e8d8bef9SDimitry Andric   return expandFromPrimitiveShadow(T, PrimitiveValue, Pos);
19700b57cec5SDimitry Andric }
19710b57cec5SDimitry Andric 
19720b57cec5SDimitry Andric // Generates IR to compute the union of the two given shadows, inserting it
1973e8d8bef9SDimitry Andric // before Pos. The combined value is with primitive type.
1974*0fca6ea1SDimitry Andric Value *DFSanFunction::combineShadows(Value *V1, Value *V2,
1975*0fca6ea1SDimitry Andric                                      BasicBlock::iterator Pos) {
1976e8d8bef9SDimitry Andric   if (DFS.isZeroShadow(V1))
1977e8d8bef9SDimitry Andric     return collapseToPrimitiveShadow(V2, Pos);
1978e8d8bef9SDimitry Andric   if (DFS.isZeroShadow(V2))
1979e8d8bef9SDimitry Andric     return collapseToPrimitiveShadow(V1, Pos);
19800b57cec5SDimitry Andric   if (V1 == V2)
1981e8d8bef9SDimitry Andric     return collapseToPrimitiveShadow(V1, Pos);
19820b57cec5SDimitry Andric 
19830b57cec5SDimitry Andric   auto V1Elems = ShadowElements.find(V1);
19840b57cec5SDimitry Andric   auto V2Elems = ShadowElements.find(V2);
19850b57cec5SDimitry Andric   if (V1Elems != ShadowElements.end() && V2Elems != ShadowElements.end()) {
19860b57cec5SDimitry Andric     if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
19870b57cec5SDimitry Andric                       V2Elems->second.begin(), V2Elems->second.end())) {
1988e8d8bef9SDimitry Andric       return collapseToPrimitiveShadow(V1, Pos);
1989fe6060f1SDimitry Andric     }
1990fe6060f1SDimitry Andric     if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
19910b57cec5SDimitry Andric                       V1Elems->second.begin(), V1Elems->second.end())) {
1992e8d8bef9SDimitry Andric       return collapseToPrimitiveShadow(V2, Pos);
19930b57cec5SDimitry Andric     }
19940b57cec5SDimitry Andric   } else if (V1Elems != ShadowElements.end()) {
19950b57cec5SDimitry Andric     if (V1Elems->second.count(V2))
1996e8d8bef9SDimitry Andric       return collapseToPrimitiveShadow(V1, Pos);
19970b57cec5SDimitry Andric   } else if (V2Elems != ShadowElements.end()) {
19980b57cec5SDimitry Andric     if (V2Elems->second.count(V1))
1999e8d8bef9SDimitry Andric       return collapseToPrimitiveShadow(V2, Pos);
20000b57cec5SDimitry Andric   }
20010b57cec5SDimitry Andric 
20020b57cec5SDimitry Andric   auto Key = std::make_pair(V1, V2);
20030b57cec5SDimitry Andric   if (V1 > V2)
20040b57cec5SDimitry Andric     std::swap(Key.first, Key.second);
2005e8d8bef9SDimitry Andric   CachedShadow &CCS = CachedShadows[Key];
20060b57cec5SDimitry Andric   if (CCS.Block && DT.dominates(CCS.Block, Pos->getParent()))
20070b57cec5SDimitry Andric     return CCS.Shadow;
20080b57cec5SDimitry Andric 
2009e8d8bef9SDimitry Andric   // Converts inputs shadows to shadows with primitive types.
2010e8d8bef9SDimitry Andric   Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2011e8d8bef9SDimitry Andric   Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2012e8d8bef9SDimitry Andric 
2013*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
2014e8d8bef9SDimitry Andric   CCS.Block = Pos->getParent();
2015e8d8bef9SDimitry Andric   CCS.Shadow = IRB.CreateOr(PV1, PV2);
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric   std::set<Value *> UnionElems;
20180b57cec5SDimitry Andric   if (V1Elems != ShadowElements.end()) {
20190b57cec5SDimitry Andric     UnionElems = V1Elems->second;
20200b57cec5SDimitry Andric   } else {
20210b57cec5SDimitry Andric     UnionElems.insert(V1);
20220b57cec5SDimitry Andric   }
20230b57cec5SDimitry Andric   if (V2Elems != ShadowElements.end()) {
20240b57cec5SDimitry Andric     UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
20250b57cec5SDimitry Andric   } else {
20260b57cec5SDimitry Andric     UnionElems.insert(V2);
20270b57cec5SDimitry Andric   }
20280b57cec5SDimitry Andric   ShadowElements[CCS.Shadow] = std::move(UnionElems);
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric   return CCS.Shadow;
20310b57cec5SDimitry Andric }
20320b57cec5SDimitry Andric 
20330b57cec5SDimitry Andric // A convenience function which folds the shadows of each of the operands
20340b57cec5SDimitry Andric // of the provided instruction Inst, inserting the IR before Inst.  Returns
20350b57cec5SDimitry Andric // the computed union Value.
20360b57cec5SDimitry Andric Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
20370b57cec5SDimitry Andric   if (Inst->getNumOperands() == 0)
2038e8d8bef9SDimitry Andric     return DFS.getZeroShadow(Inst);
20390b57cec5SDimitry Andric 
20400b57cec5SDimitry Andric   Value *Shadow = getShadow(Inst->getOperand(0));
2041fe6060f1SDimitry Andric   for (unsigned I = 1, N = Inst->getNumOperands(); I < N; ++I)
2042*0fca6ea1SDimitry Andric     Shadow = combineShadows(Shadow, getShadow(Inst->getOperand(I)),
2043*0fca6ea1SDimitry Andric                             Inst->getIterator());
2044fe6060f1SDimitry Andric 
2045*0fca6ea1SDimitry Andric   return expandFromPrimitiveShadow(Inst->getType(), Shadow,
2046*0fca6ea1SDimitry Andric                                    Inst->getIterator());
20470b57cec5SDimitry Andric }
20480b57cec5SDimitry Andric 
2049fe6060f1SDimitry Andric void DFSanVisitor::visitInstOperands(Instruction &I) {
20500b57cec5SDimitry Andric   Value *CombinedShadow = DFSF.combineOperandShadows(&I);
20510b57cec5SDimitry Andric   DFSF.setShadow(&I, CombinedShadow);
2052fe6060f1SDimitry Andric   visitInstOperandOrigins(I);
20530b57cec5SDimitry Andric }
20540b57cec5SDimitry Andric 
2055fe6060f1SDimitry Andric Value *DFSanFunction::combineOrigins(const std::vector<Value *> &Shadows,
2056fe6060f1SDimitry Andric                                      const std::vector<Value *> &Origins,
2057*0fca6ea1SDimitry Andric                                      BasicBlock::iterator Pos,
2058*0fca6ea1SDimitry Andric                                      ConstantInt *Zero) {
2059fe6060f1SDimitry Andric   assert(Shadows.size() == Origins.size());
2060fe6060f1SDimitry Andric   size_t Size = Origins.size();
2061fe6060f1SDimitry Andric   if (Size == 0)
2062fe6060f1SDimitry Andric     return DFS.ZeroOrigin;
2063fe6060f1SDimitry Andric   Value *Origin = nullptr;
2064fe6060f1SDimitry Andric   if (!Zero)
2065fe6060f1SDimitry Andric     Zero = DFS.ZeroPrimitiveShadow;
2066fe6060f1SDimitry Andric   for (size_t I = 0; I != Size; ++I) {
2067fe6060f1SDimitry Andric     Value *OpOrigin = Origins[I];
2068fe6060f1SDimitry Andric     Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2069fe6060f1SDimitry Andric     if (ConstOpOrigin && ConstOpOrigin->isNullValue())
2070fe6060f1SDimitry Andric       continue;
2071fe6060f1SDimitry Andric     if (!Origin) {
2072fe6060f1SDimitry Andric       Origin = OpOrigin;
2073fe6060f1SDimitry Andric       continue;
2074fe6060f1SDimitry Andric     }
2075fe6060f1SDimitry Andric     Value *OpShadow = Shadows[I];
2076fe6060f1SDimitry Andric     Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2077*0fca6ea1SDimitry Andric     IRBuilder<> IRB(Pos->getParent(), Pos);
2078fe6060f1SDimitry Andric     Value *Cond = IRB.CreateICmpNE(PrimitiveShadow, Zero);
2079fe6060f1SDimitry Andric     Origin = IRB.CreateSelect(Cond, OpOrigin, Origin);
2080fe6060f1SDimitry Andric   }
2081fe6060f1SDimitry Andric   return Origin ? Origin : DFS.ZeroOrigin;
2082fe6060f1SDimitry Andric }
2083fe6060f1SDimitry Andric 
2084fe6060f1SDimitry Andric Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) {
2085fe6060f1SDimitry Andric   size_t Size = Inst->getNumOperands();
2086fe6060f1SDimitry Andric   std::vector<Value *> Shadows(Size);
2087fe6060f1SDimitry Andric   std::vector<Value *> Origins(Size);
2088fe6060f1SDimitry Andric   for (unsigned I = 0; I != Size; ++I) {
2089fe6060f1SDimitry Andric     Shadows[I] = getShadow(Inst->getOperand(I));
2090fe6060f1SDimitry Andric     Origins[I] = getOrigin(Inst->getOperand(I));
2091fe6060f1SDimitry Andric   }
2092*0fca6ea1SDimitry Andric   return combineOrigins(Shadows, Origins, Inst->getIterator());
2093fe6060f1SDimitry Andric }
2094fe6060f1SDimitry Andric 
2095fe6060f1SDimitry Andric void DFSanVisitor::visitInstOperandOrigins(Instruction &I) {
2096fe6060f1SDimitry Andric   if (!DFSF.DFS.shouldTrackOrigins())
2097fe6060f1SDimitry Andric     return;
2098fe6060f1SDimitry Andric   Value *CombinedOrigin = DFSF.combineOperandOrigins(&I);
2099fe6060f1SDimitry Andric   DFSF.setOrigin(&I, CombinedOrigin);
2100fe6060f1SDimitry Andric }
2101fe6060f1SDimitry Andric 
2102fe6060f1SDimitry Andric Align DFSanFunction::getShadowAlign(Align InstAlignment) {
2103fe6060f1SDimitry Andric   const Align Alignment = ClPreserveAlignment ? InstAlignment : Align(1);
2104fe6060f1SDimitry Andric   return Align(Alignment.value() * DFS.ShadowWidthBytes);
2105fe6060f1SDimitry Andric }
2106fe6060f1SDimitry Andric 
2107fe6060f1SDimitry Andric Align DFSanFunction::getOriginAlign(Align InstAlignment) {
2108fe6060f1SDimitry Andric   const Align Alignment = llvm::assumeAligned(InstAlignment.value());
2109fe6060f1SDimitry Andric   return Align(std::max(MinOriginAlignment, Alignment));
2110fe6060f1SDimitry Andric }
2111fe6060f1SDimitry Andric 
211281ad6265SDimitry Andric bool DFSanFunction::isLookupTableConstant(Value *P) {
211381ad6265SDimitry Andric   if (GlobalVariable *GV = dyn_cast<GlobalVariable>(P->stripPointerCasts()))
211481ad6265SDimitry Andric     if (GV->isConstant() && GV->hasName())
211581ad6265SDimitry Andric       return DFS.CombineTaintLookupTableNames.count(GV->getName());
211681ad6265SDimitry Andric 
211781ad6265SDimitry Andric   return false;
211881ad6265SDimitry Andric }
211981ad6265SDimitry Andric 
2120fe6060f1SDimitry Andric bool DFSanFunction::useCallbackLoadLabelAndOrigin(uint64_t Size,
2121fe6060f1SDimitry Andric                                                   Align InstAlignment) {
2122fe6060f1SDimitry Andric   // When enabling tracking load instructions, we always use
2123fe6060f1SDimitry Andric   // __dfsan_load_label_and_origin to reduce code size.
2124fe6060f1SDimitry Andric   if (ClTrackOrigins == 2)
2125fe6060f1SDimitry Andric     return true;
2126fe6060f1SDimitry Andric 
2127fe6060f1SDimitry Andric   assert(Size != 0);
2128fe6060f1SDimitry Andric   // * if Size == 1, it is sufficient to load its origin aligned at 4.
2129fe6060f1SDimitry Andric   // * if Size == 2, we assume most cases Addr % 2 == 0, so it is sufficient to
2130fe6060f1SDimitry Andric   //   load its origin aligned at 4. If not, although origins may be lost, it
2131fe6060f1SDimitry Andric   //   should not happen very often.
2132fe6060f1SDimitry Andric   // * if align >= 4, Addr must be aligned to 4, otherwise it is UB. When
2133fe6060f1SDimitry Andric   //   Size % 4 == 0, it is more efficient to load origins without callbacks.
2134fe6060f1SDimitry Andric   // * Otherwise we use __dfsan_load_label_and_origin.
2135fe6060f1SDimitry Andric   // This should ensure that common cases run efficiently.
2136fe6060f1SDimitry Andric   if (Size <= 2)
2137fe6060f1SDimitry Andric     return false;
2138fe6060f1SDimitry Andric 
2139fe6060f1SDimitry Andric   const Align Alignment = llvm::assumeAligned(InstAlignment.value());
2140fe6060f1SDimitry Andric   return Alignment < MinOriginAlignment || !DFS.hasLoadSizeForFastPath(Size);
2141fe6060f1SDimitry Andric }
2142fe6060f1SDimitry Andric 
2143*0fca6ea1SDimitry Andric Value *DataFlowSanitizer::loadNextOrigin(BasicBlock::iterator Pos,
2144*0fca6ea1SDimitry Andric                                          Align OriginAlign,
2145fe6060f1SDimitry Andric                                          Value **OriginAddr) {
2146*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
2147fe6060f1SDimitry Andric   *OriginAddr =
2148fe6060f1SDimitry Andric       IRB.CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2149fe6060f1SDimitry Andric   return IRB.CreateAlignedLoad(OriginTy, *OriginAddr, OriginAlign);
2150fe6060f1SDimitry Andric }
2151fe6060f1SDimitry Andric 
2152fe6060f1SDimitry Andric std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2153fe6060f1SDimitry Andric     Value *ShadowAddr, Value *OriginAddr, uint64_t Size, Align ShadowAlign,
2154*0fca6ea1SDimitry Andric     Align OriginAlign, Value *FirstOrigin, BasicBlock::iterator Pos) {
2155fe6060f1SDimitry Andric   const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2156fe6060f1SDimitry Andric   const uint64_t ShadowSize = Size * DFS.ShadowWidthBytes;
2157fe6060f1SDimitry Andric 
2158fe6060f1SDimitry Andric   assert(Size >= 4 && "Not large enough load size for fast path!");
2159fe6060f1SDimitry Andric 
2160fe6060f1SDimitry Andric   // Used for origin tracking.
2161fe6060f1SDimitry Andric   std::vector<Value *> Shadows;
2162fe6060f1SDimitry Andric   std::vector<Value *> Origins;
2163fe6060f1SDimitry Andric 
2164fe6060f1SDimitry Andric   // Load instructions in LLVM can have arbitrary byte sizes (e.g., 3, 12, 20)
2165fe6060f1SDimitry Andric   // but this function is only used in a subset of cases that make it possible
2166fe6060f1SDimitry Andric   // to optimize the instrumentation.
2167fe6060f1SDimitry Andric   //
2168fe6060f1SDimitry Andric   // Specifically, when the shadow size in bytes (i.e., loaded bytes x shadow
2169fe6060f1SDimitry Andric   // per byte) is either:
2170fe6060f1SDimitry Andric   // - a multiple of 8  (common)
2171fe6060f1SDimitry Andric   // - equal to 4       (only for load32)
2172fe6060f1SDimitry Andric   //
2173fe6060f1SDimitry Andric   // For the second case, we can fit the wide shadow in a 32-bit integer. In all
2174fe6060f1SDimitry Andric   // other cases, we use a 64-bit integer to hold the wide shadow.
2175fe6060f1SDimitry Andric   Type *WideShadowTy =
2176fe6060f1SDimitry Andric       ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) : Type::getInt64Ty(*DFS.Ctx);
2177fe6060f1SDimitry Andric 
2178*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
2179fe6060f1SDimitry Andric   Value *CombinedWideShadow =
218006c3fb27SDimitry Andric       IRB.CreateAlignedLoad(WideShadowTy, ShadowAddr, ShadowAlign);
2181fe6060f1SDimitry Andric 
2182fe6060f1SDimitry Andric   unsigned WideShadowBitWidth = WideShadowTy->getIntegerBitWidth();
2183fe6060f1SDimitry Andric   const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2184fe6060f1SDimitry Andric 
2185fe6060f1SDimitry Andric   auto AppendWideShadowAndOrigin = [&](Value *WideShadow, Value *Origin) {
2186fe6060f1SDimitry Andric     if (BytesPerWideShadow > 4) {
2187fe6060f1SDimitry Andric       assert(BytesPerWideShadow == 8);
2188fe6060f1SDimitry Andric       // The wide shadow relates to two origin pointers: one for the first four
2189fe6060f1SDimitry Andric       // application bytes, and one for the latest four. We use a left shift to
2190fe6060f1SDimitry Andric       // get just the shadow bytes that correspond to the first origin pointer,
2191fe6060f1SDimitry Andric       // and then the entire shadow for the second origin pointer (which will be
2192fe6060f1SDimitry Andric       // chosen by combineOrigins() iff the least-significant half of the wide
2193fe6060f1SDimitry Andric       // shadow was empty but the other half was not).
2194fe6060f1SDimitry Andric       Value *WideShadowLo = IRB.CreateShl(
2195fe6060f1SDimitry Andric           WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2196fe6060f1SDimitry Andric       Shadows.push_back(WideShadow);
2197fe6060f1SDimitry Andric       Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2198fe6060f1SDimitry Andric 
2199fe6060f1SDimitry Andric       Shadows.push_back(WideShadowLo);
2200fe6060f1SDimitry Andric       Origins.push_back(Origin);
2201fe6060f1SDimitry Andric     } else {
2202fe6060f1SDimitry Andric       Shadows.push_back(WideShadow);
2203fe6060f1SDimitry Andric       Origins.push_back(Origin);
2204fe6060f1SDimitry Andric     }
2205fe6060f1SDimitry Andric   };
2206fe6060f1SDimitry Andric 
2207fe6060f1SDimitry Andric   if (ShouldTrackOrigins)
2208fe6060f1SDimitry Andric     AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2209fe6060f1SDimitry Andric 
2210fe6060f1SDimitry Andric   // First OR all the WideShadows (i.e., 64bit or 32bit shadow chunks) linearly;
2211fe6060f1SDimitry Andric   // then OR individual shadows within the combined WideShadow by binary ORing.
2212fe6060f1SDimitry Andric   // This is fewer instructions than ORing shadows individually, since it
2213fe6060f1SDimitry Andric   // needs logN shift/or instructions (N being the bytes of the combined wide
2214fe6060f1SDimitry Andric   // shadow).
2215fe6060f1SDimitry Andric   for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs < Size;
2216fe6060f1SDimitry Andric        ByteOfs += BytesPerWideShadow) {
221706c3fb27SDimitry Andric     ShadowAddr = IRB.CreateGEP(WideShadowTy, ShadowAddr,
2218fe6060f1SDimitry Andric                                ConstantInt::get(DFS.IntptrTy, 1));
2219fe6060f1SDimitry Andric     Value *NextWideShadow =
222006c3fb27SDimitry Andric         IRB.CreateAlignedLoad(WideShadowTy, ShadowAddr, ShadowAlign);
2221fe6060f1SDimitry Andric     CombinedWideShadow = IRB.CreateOr(CombinedWideShadow, NextWideShadow);
2222fe6060f1SDimitry Andric     if (ShouldTrackOrigins) {
2223fe6060f1SDimitry Andric       Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2224fe6060f1SDimitry Andric       AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2225fe6060f1SDimitry Andric     }
2226fe6060f1SDimitry Andric   }
2227fe6060f1SDimitry Andric   for (unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2228fe6060f1SDimitry Andric        Width >>= 1) {
2229fe6060f1SDimitry Andric     Value *ShrShadow = IRB.CreateLShr(CombinedWideShadow, Width);
2230fe6060f1SDimitry Andric     CombinedWideShadow = IRB.CreateOr(CombinedWideShadow, ShrShadow);
2231fe6060f1SDimitry Andric   }
2232fe6060f1SDimitry Andric   return {IRB.CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2233fe6060f1SDimitry Andric           ShouldTrackOrigins
2234fe6060f1SDimitry Andric               ? combineOrigins(Shadows, Origins, Pos,
2235fe6060f1SDimitry Andric                                ConstantInt::getSigned(IRB.getInt64Ty(), 0))
2236fe6060f1SDimitry Andric               : DFS.ZeroOrigin};
2237fe6060f1SDimitry Andric }
2238fe6060f1SDimitry Andric 
2239fe6060f1SDimitry Andric std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2240*0fca6ea1SDimitry Andric     Value *Addr, uint64_t Size, Align InstAlignment, BasicBlock::iterator Pos) {
2241fe6060f1SDimitry Andric   const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2242fe6060f1SDimitry Andric 
2243fe6060f1SDimitry Andric   // Non-escaped loads.
2244fe6060f1SDimitry Andric   if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
2245fe6060f1SDimitry Andric     const auto SI = AllocaShadowMap.find(AI);
2246fe6060f1SDimitry Andric     if (SI != AllocaShadowMap.end()) {
2247*0fca6ea1SDimitry Andric       IRBuilder<> IRB(Pos->getParent(), Pos);
2248fe6060f1SDimitry Andric       Value *ShadowLI = IRB.CreateLoad(DFS.PrimitiveShadowTy, SI->second);
2249fe6060f1SDimitry Andric       const auto OI = AllocaOriginMap.find(AI);
2250fe6060f1SDimitry Andric       assert(!ShouldTrackOrigins || OI != AllocaOriginMap.end());
2251fe6060f1SDimitry Andric       return {ShadowLI, ShouldTrackOrigins
2252fe6060f1SDimitry Andric                             ? IRB.CreateLoad(DFS.OriginTy, OI->second)
2253fe6060f1SDimitry Andric                             : nullptr};
22540b57cec5SDimitry Andric     }
22550b57cec5SDimitry Andric   }
22560b57cec5SDimitry Andric 
2257fe6060f1SDimitry Andric   // Load from constant addresses.
22580b57cec5SDimitry Andric   SmallVector<const Value *, 2> Objs;
2259e8d8bef9SDimitry Andric   getUnderlyingObjects(Addr, Objs);
22600b57cec5SDimitry Andric   bool AllConstants = true;
22610b57cec5SDimitry Andric   for (const Value *Obj : Objs) {
22620b57cec5SDimitry Andric     if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
22630b57cec5SDimitry Andric       continue;
22640b57cec5SDimitry Andric     if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->isConstant())
22650b57cec5SDimitry Andric       continue;
22660b57cec5SDimitry Andric 
22670b57cec5SDimitry Andric     AllConstants = false;
22680b57cec5SDimitry Andric     break;
22690b57cec5SDimitry Andric   }
22700b57cec5SDimitry Andric   if (AllConstants)
2271fe6060f1SDimitry Andric     return {DFS.ZeroPrimitiveShadow,
2272fe6060f1SDimitry Andric             ShouldTrackOrigins ? DFS.ZeroOrigin : nullptr};
22730b57cec5SDimitry Andric 
2274fe6060f1SDimitry Andric   if (Size == 0)
2275fe6060f1SDimitry Andric     return {DFS.ZeroPrimitiveShadow,
2276fe6060f1SDimitry Andric             ShouldTrackOrigins ? DFS.ZeroOrigin : nullptr};
2277fe6060f1SDimitry Andric 
2278fe6060f1SDimitry Andric   // Use callback to load if this is not an optimizable case for origin
2279fe6060f1SDimitry Andric   // tracking.
2280fe6060f1SDimitry Andric   if (ShouldTrackOrigins &&
2281fe6060f1SDimitry Andric       useCallbackLoadLabelAndOrigin(Size, InstAlignment)) {
2282*0fca6ea1SDimitry Andric     IRBuilder<> IRB(Pos->getParent(), Pos);
2283fe6060f1SDimitry Andric     CallInst *Call =
2284fe6060f1SDimitry Andric         IRB.CreateCall(DFS.DFSanLoadLabelAndOriginFn,
22855f757f3fSDimitry Andric                        {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2286349cc55cSDimitry Andric     Call->addRetAttr(Attribute::ZExt);
2287fe6060f1SDimitry Andric     return {IRB.CreateTrunc(IRB.CreateLShr(Call, DFS.OriginWidthBits),
2288fe6060f1SDimitry Andric                             DFS.PrimitiveShadowTy),
2289fe6060f1SDimitry Andric             IRB.CreateTrunc(Call, DFS.OriginTy)};
2290fe6060f1SDimitry Andric   }
2291fe6060f1SDimitry Andric 
2292fe6060f1SDimitry Andric   // Other cases that support loading shadows or origins in a fast way.
2293fe6060f1SDimitry Andric   Value *ShadowAddr, *OriginAddr;
2294fe6060f1SDimitry Andric   std::tie(ShadowAddr, OriginAddr) =
2295fe6060f1SDimitry Andric       DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2296fe6060f1SDimitry Andric 
2297fe6060f1SDimitry Andric   const Align ShadowAlign = getShadowAlign(InstAlignment);
2298fe6060f1SDimitry Andric   const Align OriginAlign = getOriginAlign(InstAlignment);
2299fe6060f1SDimitry Andric   Value *Origin = nullptr;
2300fe6060f1SDimitry Andric   if (ShouldTrackOrigins) {
2301*0fca6ea1SDimitry Andric     IRBuilder<> IRB(Pos->getParent(), Pos);
2302fe6060f1SDimitry Andric     Origin = IRB.CreateAlignedLoad(DFS.OriginTy, OriginAddr, OriginAlign);
2303fe6060f1SDimitry Andric   }
2304fe6060f1SDimitry Andric 
2305fe6060f1SDimitry Andric   // When the byte size is small enough, we can load the shadow directly with
2306fe6060f1SDimitry Andric   // just a few instructions.
23070b57cec5SDimitry Andric   switch (Size) {
23080b57cec5SDimitry Andric   case 1: {
2309e8d8bef9SDimitry Andric     LoadInst *LI = new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr, "", Pos);
23105ffd83dbSDimitry Andric     LI->setAlignment(ShadowAlign);
2311fe6060f1SDimitry Andric     return {LI, Origin};
23120b57cec5SDimitry Andric   }
23130b57cec5SDimitry Andric   case 2: {
2314*0fca6ea1SDimitry Andric     IRBuilder<> IRB(Pos->getParent(), Pos);
2315e8d8bef9SDimitry Andric     Value *ShadowAddr1 = IRB.CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
23160b57cec5SDimitry Andric                                        ConstantInt::get(DFS.IntptrTy, 1));
2317fe6060f1SDimitry Andric     Value *Load =
2318fe6060f1SDimitry Andric         IRB.CreateAlignedLoad(DFS.PrimitiveShadowTy, ShadowAddr, ShadowAlign);
2319fe6060f1SDimitry Andric     Value *Load1 =
2320fe6060f1SDimitry Andric         IRB.CreateAlignedLoad(DFS.PrimitiveShadowTy, ShadowAddr1, ShadowAlign);
2321fe6060f1SDimitry Andric     return {combineShadows(Load, Load1, Pos), Origin};
23220b57cec5SDimitry Andric   }
23230b57cec5SDimitry Andric   }
2324fe6060f1SDimitry Andric   bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(Size);
2325e8d8bef9SDimitry Andric 
2326fe6060f1SDimitry Andric   if (HasSizeForFastPath)
2327fe6060f1SDimitry Andric     return loadShadowFast(ShadowAddr, OriginAddr, Size, ShadowAlign,
2328fe6060f1SDimitry Andric                           OriginAlign, Origin, Pos);
23290b57cec5SDimitry Andric 
2330*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
23310b57cec5SDimitry Andric   CallInst *FallbackCall = IRB.CreateCall(
2332fe6060f1SDimitry Andric       DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2333349cc55cSDimitry Andric   FallbackCall->addRetAttr(Attribute::ZExt);
2334fe6060f1SDimitry Andric   return {FallbackCall, Origin};
2335fe6060f1SDimitry Andric }
2336fe6060f1SDimitry Andric 
2337*0fca6ea1SDimitry Andric std::pair<Value *, Value *>
2338*0fca6ea1SDimitry Andric DFSanFunction::loadShadowOrigin(Value *Addr, uint64_t Size, Align InstAlignment,
2339*0fca6ea1SDimitry Andric                                 BasicBlock::iterator Pos) {
2340fe6060f1SDimitry Andric   Value *PrimitiveShadow, *Origin;
2341fe6060f1SDimitry Andric   std::tie(PrimitiveShadow, Origin) =
2342fe6060f1SDimitry Andric       loadShadowOriginSansLoadTracking(Addr, Size, InstAlignment, Pos);
2343fe6060f1SDimitry Andric   if (DFS.shouldTrackOrigins()) {
2344fe6060f1SDimitry Andric     if (ClTrackOrigins == 2) {
2345*0fca6ea1SDimitry Andric       IRBuilder<> IRB(Pos->getParent(), Pos);
2346fe6060f1SDimitry Andric       auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2347fe6060f1SDimitry Andric       if (!ConstantShadow || !ConstantShadow->isZeroValue())
2348fe6060f1SDimitry Andric         Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2349fe6060f1SDimitry Andric     }
2350fe6060f1SDimitry Andric   }
2351fe6060f1SDimitry Andric   return {PrimitiveShadow, Origin};
2352fe6060f1SDimitry Andric }
2353fe6060f1SDimitry Andric 
2354fe6060f1SDimitry Andric static AtomicOrdering addAcquireOrdering(AtomicOrdering AO) {
2355fe6060f1SDimitry Andric   switch (AO) {
2356fe6060f1SDimitry Andric   case AtomicOrdering::NotAtomic:
2357fe6060f1SDimitry Andric     return AtomicOrdering::NotAtomic;
2358fe6060f1SDimitry Andric   case AtomicOrdering::Unordered:
2359fe6060f1SDimitry Andric   case AtomicOrdering::Monotonic:
2360fe6060f1SDimitry Andric   case AtomicOrdering::Acquire:
2361fe6060f1SDimitry Andric     return AtomicOrdering::Acquire;
2362fe6060f1SDimitry Andric   case AtomicOrdering::Release:
2363fe6060f1SDimitry Andric   case AtomicOrdering::AcquireRelease:
2364fe6060f1SDimitry Andric     return AtomicOrdering::AcquireRelease;
2365fe6060f1SDimitry Andric   case AtomicOrdering::SequentiallyConsistent:
2366fe6060f1SDimitry Andric     return AtomicOrdering::SequentiallyConsistent;
2367fe6060f1SDimitry Andric   }
2368fe6060f1SDimitry Andric   llvm_unreachable("Unknown ordering");
23690b57cec5SDimitry Andric }
23700b57cec5SDimitry Andric 
237181ad6265SDimitry Andric Value *StripPointerGEPsAndCasts(Value *V) {
237281ad6265SDimitry Andric   if (!V->getType()->isPointerTy())
237381ad6265SDimitry Andric     return V;
237481ad6265SDimitry Andric 
237581ad6265SDimitry Andric   // DFSan pass should be running on valid IR, but we'll
237681ad6265SDimitry Andric   // keep a seen set to ensure there are no issues.
237781ad6265SDimitry Andric   SmallPtrSet<const Value *, 4> Visited;
237881ad6265SDimitry Andric   Visited.insert(V);
237981ad6265SDimitry Andric   do {
238081ad6265SDimitry Andric     if (auto *GEP = dyn_cast<GEPOperator>(V)) {
238181ad6265SDimitry Andric       V = GEP->getPointerOperand();
238281ad6265SDimitry Andric     } else if (Operator::getOpcode(V) == Instruction::BitCast) {
238381ad6265SDimitry Andric       V = cast<Operator>(V)->getOperand(0);
238481ad6265SDimitry Andric       if (!V->getType()->isPointerTy())
238581ad6265SDimitry Andric         return V;
238681ad6265SDimitry Andric     } else if (isa<GlobalAlias>(V)) {
238781ad6265SDimitry Andric       V = cast<GlobalAlias>(V)->getAliasee();
238881ad6265SDimitry Andric     }
238981ad6265SDimitry Andric   } while (Visited.insert(V).second);
239081ad6265SDimitry Andric 
239181ad6265SDimitry Andric   return V;
239281ad6265SDimitry Andric }
239381ad6265SDimitry Andric 
23940b57cec5SDimitry Andric void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2395*0fca6ea1SDimitry Andric   auto &DL = LI.getDataLayout();
23960b57cec5SDimitry Andric   uint64_t Size = DL.getTypeStoreSize(LI.getType());
23970b57cec5SDimitry Andric   if (Size == 0) {
2398e8d8bef9SDimitry Andric     DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2399fe6060f1SDimitry Andric     DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
24000b57cec5SDimitry Andric     return;
24010b57cec5SDimitry Andric   }
24020b57cec5SDimitry Andric 
2403fe6060f1SDimitry Andric   // When an application load is atomic, increase atomic ordering between
2404fe6060f1SDimitry Andric   // atomic application loads and stores to ensure happen-before order; load
2405fe6060f1SDimitry Andric   // shadow data after application data; store zero shadow data before
2406fe6060f1SDimitry Andric   // application data. This ensure shadow loads return either labels of the
2407fe6060f1SDimitry Andric   // initial application data or zeros.
2408fe6060f1SDimitry Andric   if (LI.isAtomic())
2409fe6060f1SDimitry Andric     LI.setOrdering(addAcquireOrdering(LI.getOrdering()));
2410fe6060f1SDimitry Andric 
2411*0fca6ea1SDimitry Andric   BasicBlock::iterator AfterLi = std::next(LI.getIterator());
2412*0fca6ea1SDimitry Andric   BasicBlock::iterator Pos = LI.getIterator();
2413*0fca6ea1SDimitry Andric   if (LI.isAtomic())
2414*0fca6ea1SDimitry Andric     Pos = std::next(Pos);
2415*0fca6ea1SDimitry Andric 
2416fe6060f1SDimitry Andric   std::vector<Value *> Shadows;
2417fe6060f1SDimitry Andric   std::vector<Value *> Origins;
2418fe6060f1SDimitry Andric   Value *PrimitiveShadow, *Origin;
2419fe6060f1SDimitry Andric   std::tie(PrimitiveShadow, Origin) =
2420fe6060f1SDimitry Andric       DFSF.loadShadowOrigin(LI.getPointerOperand(), Size, LI.getAlign(), Pos);
2421fe6060f1SDimitry Andric   const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2422fe6060f1SDimitry Andric   if (ShouldTrackOrigins) {
2423fe6060f1SDimitry Andric     Shadows.push_back(PrimitiveShadow);
2424fe6060f1SDimitry Andric     Origins.push_back(Origin);
2425fe6060f1SDimitry Andric   }
242681ad6265SDimitry Andric   if (ClCombinePointerLabelsOnLoad ||
242781ad6265SDimitry Andric       DFSF.isLookupTableConstant(
242881ad6265SDimitry Andric           StripPointerGEPsAndCasts(LI.getPointerOperand()))) {
24290b57cec5SDimitry Andric     Value *PtrShadow = DFSF.getShadow(LI.getPointerOperand());
2430fe6060f1SDimitry Andric     PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2431fe6060f1SDimitry Andric     if (ShouldTrackOrigins) {
2432fe6060f1SDimitry Andric       Shadows.push_back(PtrShadow);
2433fe6060f1SDimitry Andric       Origins.push_back(DFSF.getOrigin(LI.getPointerOperand()));
2434fe6060f1SDimitry Andric     }
24350b57cec5SDimitry Andric   }
2436e8d8bef9SDimitry Andric   if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2437e8d8bef9SDimitry Andric     DFSF.NonZeroChecks.push_back(PrimitiveShadow);
24380b57cec5SDimitry Andric 
2439e8d8bef9SDimitry Andric   Value *Shadow =
2440fe6060f1SDimitry Andric       DFSF.expandFromPrimitiveShadow(LI.getType(), PrimitiveShadow, Pos);
24410b57cec5SDimitry Andric   DFSF.setShadow(&LI, Shadow);
2442fe6060f1SDimitry Andric 
2443fe6060f1SDimitry Andric   if (ShouldTrackOrigins) {
2444fe6060f1SDimitry Andric     DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2445fe6060f1SDimitry Andric   }
2446fe6060f1SDimitry Andric 
24475ffd83dbSDimitry Andric   if (ClEventCallbacks) {
2448*0fca6ea1SDimitry Andric     IRBuilder<> IRB(Pos->getParent(), Pos);
24495f757f3fSDimitry Andric     Value *Addr = LI.getPointerOperand();
2450bdd1243dSDimitry Andric     CallInst *CI =
24515f757f3fSDimitry Andric         IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2452bdd1243dSDimitry Andric     CI->addParamAttr(0, Attribute::ZExt);
24535ffd83dbSDimitry Andric   }
2454bdd1243dSDimitry Andric 
2455*0fca6ea1SDimitry Andric   IRBuilder<> IRB(AfterLi->getParent(), AfterLi);
2456bdd1243dSDimitry Andric   DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
24570b57cec5SDimitry Andric }
24580b57cec5SDimitry Andric 
2459fe6060f1SDimitry Andric Value *DFSanFunction::updateOriginIfTainted(Value *Shadow, Value *Origin,
2460fe6060f1SDimitry Andric                                             IRBuilder<> &IRB) {
2461fe6060f1SDimitry Andric   assert(DFS.shouldTrackOrigins());
2462fe6060f1SDimitry Andric   return IRB.CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2463fe6060f1SDimitry Andric }
2464fe6060f1SDimitry Andric 
2465fe6060f1SDimitry Andric Value *DFSanFunction::updateOrigin(Value *V, IRBuilder<> &IRB) {
2466fe6060f1SDimitry Andric   if (!DFS.shouldTrackOrigins())
2467fe6060f1SDimitry Andric     return V;
2468fe6060f1SDimitry Andric   return IRB.CreateCall(DFS.DFSanChainOriginFn, V);
2469fe6060f1SDimitry Andric }
2470fe6060f1SDimitry Andric 
2471fe6060f1SDimitry Andric Value *DFSanFunction::originToIntptr(IRBuilder<> &IRB, Value *Origin) {
2472fe6060f1SDimitry Andric   const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2473*0fca6ea1SDimitry Andric   const DataLayout &DL = F->getDataLayout();
2474fe6060f1SDimitry Andric   unsigned IntptrSize = DL.getTypeStoreSize(DFS.IntptrTy);
2475fe6060f1SDimitry Andric   if (IntptrSize == OriginSize)
2476fe6060f1SDimitry Andric     return Origin;
2477fe6060f1SDimitry Andric   assert(IntptrSize == OriginSize * 2);
2478fe6060f1SDimitry Andric   Origin = IRB.CreateIntCast(Origin, DFS.IntptrTy, /* isSigned */ false);
2479fe6060f1SDimitry Andric   return IRB.CreateOr(Origin, IRB.CreateShl(Origin, OriginSize * 8));
2480fe6060f1SDimitry Andric }
2481fe6060f1SDimitry Andric 
2482fe6060f1SDimitry Andric void DFSanFunction::paintOrigin(IRBuilder<> &IRB, Value *Origin,
2483fe6060f1SDimitry Andric                                 Value *StoreOriginAddr,
2484fe6060f1SDimitry Andric                                 uint64_t StoreOriginSize, Align Alignment) {
2485fe6060f1SDimitry Andric   const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2486*0fca6ea1SDimitry Andric   const DataLayout &DL = F->getDataLayout();
2487fe6060f1SDimitry Andric   const Align IntptrAlignment = DL.getABITypeAlign(DFS.IntptrTy);
2488fe6060f1SDimitry Andric   unsigned IntptrSize = DL.getTypeStoreSize(DFS.IntptrTy);
2489fe6060f1SDimitry Andric   assert(IntptrAlignment >= MinOriginAlignment);
2490fe6060f1SDimitry Andric   assert(IntptrSize >= OriginSize);
2491fe6060f1SDimitry Andric 
2492fe6060f1SDimitry Andric   unsigned Ofs = 0;
2493fe6060f1SDimitry Andric   Align CurrentAlignment = Alignment;
2494fe6060f1SDimitry Andric   if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2495fe6060f1SDimitry Andric     Value *IntptrOrigin = originToIntptr(IRB, Origin);
2496fe6060f1SDimitry Andric     Value *IntptrStoreOriginPtr = IRB.CreatePointerCast(
2497fe6060f1SDimitry Andric         StoreOriginAddr, PointerType::get(DFS.IntptrTy, 0));
2498fe6060f1SDimitry Andric     for (unsigned I = 0; I < StoreOriginSize / IntptrSize; ++I) {
2499fe6060f1SDimitry Andric       Value *Ptr =
2500fe6060f1SDimitry Andric           I ? IRB.CreateConstGEP1_32(DFS.IntptrTy, IntptrStoreOriginPtr, I)
2501fe6060f1SDimitry Andric             : IntptrStoreOriginPtr;
2502fe6060f1SDimitry Andric       IRB.CreateAlignedStore(IntptrOrigin, Ptr, CurrentAlignment);
2503fe6060f1SDimitry Andric       Ofs += IntptrSize / OriginSize;
2504fe6060f1SDimitry Andric       CurrentAlignment = IntptrAlignment;
25050b57cec5SDimitry Andric     }
25060b57cec5SDimitry Andric   }
25070b57cec5SDimitry Andric 
2508fe6060f1SDimitry Andric   for (unsigned I = Ofs; I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2509fe6060f1SDimitry Andric        ++I) {
2510fe6060f1SDimitry Andric     Value *GEP = I ? IRB.CreateConstGEP1_32(DFS.OriginTy, StoreOriginAddr, I)
2511fe6060f1SDimitry Andric                    : StoreOriginAddr;
2512fe6060f1SDimitry Andric     IRB.CreateAlignedStore(Origin, GEP, CurrentAlignment);
2513fe6060f1SDimitry Andric     CurrentAlignment = MinOriginAlignment;
2514fe6060f1SDimitry Andric   }
2515fe6060f1SDimitry Andric }
2516fe6060f1SDimitry Andric 
2517fe6060f1SDimitry Andric Value *DFSanFunction::convertToBool(Value *V, IRBuilder<> &IRB,
2518fe6060f1SDimitry Andric                                     const Twine &Name) {
2519fe6060f1SDimitry Andric   Type *VTy = V->getType();
2520fe6060f1SDimitry Andric   assert(VTy->isIntegerTy());
2521fe6060f1SDimitry Andric   if (VTy->getIntegerBitWidth() == 1)
2522fe6060f1SDimitry Andric     // Just converting a bool to a bool, so do nothing.
2523fe6060f1SDimitry Andric     return V;
2524fe6060f1SDimitry Andric   return IRB.CreateICmpNE(V, ConstantInt::get(VTy, 0), Name);
2525fe6060f1SDimitry Andric }
2526fe6060f1SDimitry Andric 
2527*0fca6ea1SDimitry Andric void DFSanFunction::storeOrigin(BasicBlock::iterator Pos, Value *Addr,
2528*0fca6ea1SDimitry Andric                                 uint64_t Size, Value *Shadow, Value *Origin,
2529fe6060f1SDimitry Andric                                 Value *StoreOriginAddr, Align InstAlignment) {
2530fe6060f1SDimitry Andric   // Do not write origins for zero shadows because we do not trace origins for
2531fe6060f1SDimitry Andric   // untainted sinks.
2532fe6060f1SDimitry Andric   const Align OriginAlignment = getOriginAlign(InstAlignment);
2533fe6060f1SDimitry Andric   Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2534*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
2535fe6060f1SDimitry Andric   if (auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2536fe6060f1SDimitry Andric     if (!ConstantShadow->isZeroValue())
2537fe6060f1SDimitry Andric       paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr, Size,
2538fe6060f1SDimitry Andric                   OriginAlignment);
2539fe6060f1SDimitry Andric     return;
2540fe6060f1SDimitry Andric   }
2541fe6060f1SDimitry Andric 
2542fe6060f1SDimitry Andric   if (shouldInstrumentWithCall()) {
25435f757f3fSDimitry Andric     IRB.CreateCall(
25445f757f3fSDimitry Andric         DFS.DFSanMaybeStoreOriginFn,
25455f757f3fSDimitry Andric         {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2546fe6060f1SDimitry Andric   } else {
2547fe6060f1SDimitry Andric     Value *Cmp = convertToBool(CollapsedShadow, IRB, "_dfscmp");
254806c3fb27SDimitry Andric     DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2549fe6060f1SDimitry Andric     Instruction *CheckTerm = SplitBlockAndInsertIfThen(
255006c3fb27SDimitry Andric         Cmp, &*IRB.GetInsertPoint(), false, DFS.OriginStoreWeights, &DTU);
2551fe6060f1SDimitry Andric     IRBuilder<> IRBNew(CheckTerm);
2552fe6060f1SDimitry Andric     paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr, Size,
2553fe6060f1SDimitry Andric                 OriginAlignment);
2554fe6060f1SDimitry Andric     ++NumOriginStores;
2555fe6060f1SDimitry Andric   }
2556fe6060f1SDimitry Andric }
2557fe6060f1SDimitry Andric 
2558fe6060f1SDimitry Andric void DFSanFunction::storeZeroPrimitiveShadow(Value *Addr, uint64_t Size,
2559fe6060f1SDimitry Andric                                              Align ShadowAlign,
2560*0fca6ea1SDimitry Andric                                              BasicBlock::iterator Pos) {
2561*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
25625ffd83dbSDimitry Andric   IntegerType *ShadowTy =
25635ffd83dbSDimitry Andric       IntegerType::get(*DFS.Ctx, Size * DFS.ShadowWidthBits);
25640b57cec5SDimitry Andric   Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2565fe6060f1SDimitry Andric   Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
25665f757f3fSDimitry Andric   IRB.CreateAlignedStore(ExtZeroShadow, ShadowAddr, ShadowAlign);
2567fe6060f1SDimitry Andric   // Do not write origins for 0 shadows because we do not trace origins for
2568fe6060f1SDimitry Andric   // untainted sinks.
2569fe6060f1SDimitry Andric }
2570fe6060f1SDimitry Andric 
2571fe6060f1SDimitry Andric void DFSanFunction::storePrimitiveShadowOrigin(Value *Addr, uint64_t Size,
2572fe6060f1SDimitry Andric                                                Align InstAlignment,
2573fe6060f1SDimitry Andric                                                Value *PrimitiveShadow,
2574fe6060f1SDimitry Andric                                                Value *Origin,
2575*0fca6ea1SDimitry Andric                                                BasicBlock::iterator Pos) {
2576fe6060f1SDimitry Andric   const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2577fe6060f1SDimitry Andric 
2578fe6060f1SDimitry Andric   if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
2579fe6060f1SDimitry Andric     const auto SI = AllocaShadowMap.find(AI);
2580fe6060f1SDimitry Andric     if (SI != AllocaShadowMap.end()) {
2581*0fca6ea1SDimitry Andric       IRBuilder<> IRB(Pos->getParent(), Pos);
2582fe6060f1SDimitry Andric       IRB.CreateStore(PrimitiveShadow, SI->second);
2583fe6060f1SDimitry Andric 
2584fe6060f1SDimitry Andric       // Do not write origins for 0 shadows because we do not trace origins for
2585fe6060f1SDimitry Andric       // untainted sinks.
2586fe6060f1SDimitry Andric       if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2587fe6060f1SDimitry Andric         const auto OI = AllocaOriginMap.find(AI);
2588fe6060f1SDimitry Andric         assert(OI != AllocaOriginMap.end() && Origin);
2589fe6060f1SDimitry Andric         IRB.CreateStore(Origin, OI->second);
2590fe6060f1SDimitry Andric       }
2591fe6060f1SDimitry Andric       return;
2592fe6060f1SDimitry Andric     }
2593fe6060f1SDimitry Andric   }
2594fe6060f1SDimitry Andric 
2595fe6060f1SDimitry Andric   const Align ShadowAlign = getShadowAlign(InstAlignment);
2596fe6060f1SDimitry Andric   if (DFS.isZeroShadow(PrimitiveShadow)) {
2597fe6060f1SDimitry Andric     storeZeroPrimitiveShadow(Addr, Size, ShadowAlign, Pos);
25980b57cec5SDimitry Andric     return;
25990b57cec5SDimitry Andric   }
26000b57cec5SDimitry Andric 
2601*0fca6ea1SDimitry Andric   IRBuilder<> IRB(Pos->getParent(), Pos);
2602fe6060f1SDimitry Andric   Value *ShadowAddr, *OriginAddr;
2603fe6060f1SDimitry Andric   std::tie(ShadowAddr, OriginAddr) =
2604fe6060f1SDimitry Andric       DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2605fe6060f1SDimitry Andric 
2606fe6060f1SDimitry Andric   const unsigned ShadowVecSize = 8;
2607fe6060f1SDimitry Andric   assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2608fe6060f1SDimitry Andric          "Shadow vector is too large!");
2609fe6060f1SDimitry Andric 
26100b57cec5SDimitry Andric   uint64_t Offset = 0;
2611fe6060f1SDimitry Andric   uint64_t LeftSize = Size;
2612fe6060f1SDimitry Andric   if (LeftSize >= ShadowVecSize) {
2613e8d8bef9SDimitry Andric     auto *ShadowVecTy =
2614e8d8bef9SDimitry Andric         FixedVectorType::get(DFS.PrimitiveShadowTy, ShadowVecSize);
2615bdd1243dSDimitry Andric     Value *ShadowVec = PoisonValue::get(ShadowVecTy);
2616fe6060f1SDimitry Andric     for (unsigned I = 0; I != ShadowVecSize; ++I) {
26170b57cec5SDimitry Andric       ShadowVec = IRB.CreateInsertElement(
2618e8d8bef9SDimitry Andric           ShadowVec, PrimitiveShadow,
2619fe6060f1SDimitry Andric           ConstantInt::get(Type::getInt32Ty(*DFS.Ctx), I));
26200b57cec5SDimitry Andric     }
26210b57cec5SDimitry Andric     do {
26220b57cec5SDimitry Andric       Value *CurShadowVecAddr =
26235f757f3fSDimitry Andric           IRB.CreateConstGEP1_32(ShadowVecTy, ShadowAddr, Offset);
26240b57cec5SDimitry Andric       IRB.CreateAlignedStore(ShadowVec, CurShadowVecAddr, ShadowAlign);
2625fe6060f1SDimitry Andric       LeftSize -= ShadowVecSize;
26260b57cec5SDimitry Andric       ++Offset;
2627fe6060f1SDimitry Andric     } while (LeftSize >= ShadowVecSize);
26280b57cec5SDimitry Andric     Offset *= ShadowVecSize;
26290b57cec5SDimitry Andric   }
2630fe6060f1SDimitry Andric   while (LeftSize > 0) {
26310b57cec5SDimitry Andric     Value *CurShadowAddr =
2632e8d8bef9SDimitry Andric         IRB.CreateConstGEP1_32(DFS.PrimitiveShadowTy, ShadowAddr, Offset);
2633e8d8bef9SDimitry Andric     IRB.CreateAlignedStore(PrimitiveShadow, CurShadowAddr, ShadowAlign);
2634fe6060f1SDimitry Andric     --LeftSize;
26350b57cec5SDimitry Andric     ++Offset;
26360b57cec5SDimitry Andric   }
2637fe6060f1SDimitry Andric 
2638fe6060f1SDimitry Andric   if (ShouldTrackOrigins) {
2639fe6060f1SDimitry Andric     storeOrigin(Pos, Addr, Size, PrimitiveShadow, Origin, OriginAddr,
2640fe6060f1SDimitry Andric                 InstAlignment);
2641fe6060f1SDimitry Andric   }
2642fe6060f1SDimitry Andric }
2643fe6060f1SDimitry Andric 
2644fe6060f1SDimitry Andric static AtomicOrdering addReleaseOrdering(AtomicOrdering AO) {
2645fe6060f1SDimitry Andric   switch (AO) {
2646fe6060f1SDimitry Andric   case AtomicOrdering::NotAtomic:
2647fe6060f1SDimitry Andric     return AtomicOrdering::NotAtomic;
2648fe6060f1SDimitry Andric   case AtomicOrdering::Unordered:
2649fe6060f1SDimitry Andric   case AtomicOrdering::Monotonic:
2650fe6060f1SDimitry Andric   case AtomicOrdering::Release:
2651fe6060f1SDimitry Andric     return AtomicOrdering::Release;
2652fe6060f1SDimitry Andric   case AtomicOrdering::Acquire:
2653fe6060f1SDimitry Andric   case AtomicOrdering::AcquireRelease:
2654fe6060f1SDimitry Andric     return AtomicOrdering::AcquireRelease;
2655fe6060f1SDimitry Andric   case AtomicOrdering::SequentiallyConsistent:
2656fe6060f1SDimitry Andric     return AtomicOrdering::SequentiallyConsistent;
2657fe6060f1SDimitry Andric   }
2658fe6060f1SDimitry Andric   llvm_unreachable("Unknown ordering");
26590b57cec5SDimitry Andric }
26600b57cec5SDimitry Andric 
26610b57cec5SDimitry Andric void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2662*0fca6ea1SDimitry Andric   auto &DL = SI.getDataLayout();
2663fe6060f1SDimitry Andric   Value *Val = SI.getValueOperand();
2664fe6060f1SDimitry Andric   uint64_t Size = DL.getTypeStoreSize(Val->getType());
26650b57cec5SDimitry Andric   if (Size == 0)
26660b57cec5SDimitry Andric     return;
26670b57cec5SDimitry Andric 
2668fe6060f1SDimitry Andric   // When an application store is atomic, increase atomic ordering between
2669fe6060f1SDimitry Andric   // atomic application loads and stores to ensure happen-before order; load
2670fe6060f1SDimitry Andric   // shadow data after application data; store zero shadow data before
2671fe6060f1SDimitry Andric   // application data. This ensure shadow loads return either labels of the
2672fe6060f1SDimitry Andric   // initial application data or zeros.
2673fe6060f1SDimitry Andric   if (SI.isAtomic())
2674fe6060f1SDimitry Andric     SI.setOrdering(addReleaseOrdering(SI.getOrdering()));
26750b57cec5SDimitry Andric 
2676fe6060f1SDimitry Andric   const bool ShouldTrackOrigins =
2677fe6060f1SDimitry Andric       DFSF.DFS.shouldTrackOrigins() && !SI.isAtomic();
2678fe6060f1SDimitry Andric   std::vector<Value *> Shadows;
2679fe6060f1SDimitry Andric   std::vector<Value *> Origins;
2680fe6060f1SDimitry Andric 
2681fe6060f1SDimitry Andric   Value *Shadow =
2682fe6060f1SDimitry Andric       SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2683fe6060f1SDimitry Andric 
2684fe6060f1SDimitry Andric   if (ShouldTrackOrigins) {
2685fe6060f1SDimitry Andric     Shadows.push_back(Shadow);
2686fe6060f1SDimitry Andric     Origins.push_back(DFSF.getOrigin(Val));
2687fe6060f1SDimitry Andric   }
2688fe6060f1SDimitry Andric 
2689e8d8bef9SDimitry Andric   Value *PrimitiveShadow;
26900b57cec5SDimitry Andric   if (ClCombinePointerLabelsOnStore) {
26910b57cec5SDimitry Andric     Value *PtrShadow = DFSF.getShadow(SI.getPointerOperand());
2692fe6060f1SDimitry Andric     if (ShouldTrackOrigins) {
2693fe6060f1SDimitry Andric       Shadows.push_back(PtrShadow);
2694fe6060f1SDimitry Andric       Origins.push_back(DFSF.getOrigin(SI.getPointerOperand()));
2695fe6060f1SDimitry Andric     }
2696*0fca6ea1SDimitry Andric     PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow, SI.getIterator());
2697e8d8bef9SDimitry Andric   } else {
2698*0fca6ea1SDimitry Andric     PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow, SI.getIterator());
26990b57cec5SDimitry Andric   }
2700fe6060f1SDimitry Andric   Value *Origin = nullptr;
2701fe6060f1SDimitry Andric   if (ShouldTrackOrigins)
2702*0fca6ea1SDimitry Andric     Origin = DFSF.combineOrigins(Shadows, Origins, SI.getIterator());
2703fe6060f1SDimitry Andric   DFSF.storePrimitiveShadowOrigin(SI.getPointerOperand(), Size, SI.getAlign(),
2704*0fca6ea1SDimitry Andric                                   PrimitiveShadow, Origin, SI.getIterator());
27055ffd83dbSDimitry Andric   if (ClEventCallbacks) {
27065ffd83dbSDimitry Andric     IRBuilder<> IRB(&SI);
27075f757f3fSDimitry Andric     Value *Addr = SI.getPointerOperand();
2708bdd1243dSDimitry Andric     CallInst *CI =
27095f757f3fSDimitry Andric         IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2710bdd1243dSDimitry Andric     CI->addParamAttr(0, Attribute::ZExt);
27115ffd83dbSDimitry Andric   }
27120b57cec5SDimitry Andric }
27130b57cec5SDimitry Andric 
2714fe6060f1SDimitry Andric void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &I) {
2715fe6060f1SDimitry Andric   assert(isa<AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I));
2716fe6060f1SDimitry Andric 
2717fe6060f1SDimitry Andric   Value *Val = I.getOperand(1);
2718*0fca6ea1SDimitry Andric   const auto &DL = I.getDataLayout();
2719fe6060f1SDimitry Andric   uint64_t Size = DL.getTypeStoreSize(Val->getType());
2720fe6060f1SDimitry Andric   if (Size == 0)
2721fe6060f1SDimitry Andric     return;
2722fe6060f1SDimitry Andric 
2723fe6060f1SDimitry Andric   // Conservatively set data at stored addresses and return with zero shadow to
2724fe6060f1SDimitry Andric   // prevent shadow data races.
2725fe6060f1SDimitry Andric   IRBuilder<> IRB(&I);
2726fe6060f1SDimitry Andric   Value *Addr = I.getOperand(0);
2727fe6060f1SDimitry Andric   const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2728*0fca6ea1SDimitry Andric   DFSF.storeZeroPrimitiveShadow(Addr, Size, ShadowAlign, I.getIterator());
2729fe6060f1SDimitry Andric   DFSF.setShadow(&I, DFSF.DFS.getZeroShadow(&I));
2730fe6060f1SDimitry Andric   DFSF.setOrigin(&I, DFSF.DFS.ZeroOrigin);
2731fe6060f1SDimitry Andric }
2732fe6060f1SDimitry Andric 
2733fe6060f1SDimitry Andric void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
2734fe6060f1SDimitry Andric   visitCASOrRMW(I.getAlign(), I);
2735fe6060f1SDimitry Andric   // TODO: The ordering change follows MSan. It is possible not to change
2736fe6060f1SDimitry Andric   // ordering because we always set and use 0 shadows.
2737fe6060f1SDimitry Andric   I.setOrdering(addReleaseOrdering(I.getOrdering()));
2738fe6060f1SDimitry Andric }
2739fe6060f1SDimitry Andric 
2740fe6060f1SDimitry Andric void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
2741fe6060f1SDimitry Andric   visitCASOrRMW(I.getAlign(), I);
2742fe6060f1SDimitry Andric   // TODO: The ordering change follows MSan. It is possible not to change
2743fe6060f1SDimitry Andric   // ordering because we always set and use 0 shadows.
2744fe6060f1SDimitry Andric   I.setSuccessOrdering(addReleaseOrdering(I.getSuccessOrdering()));
2745fe6060f1SDimitry Andric }
2746fe6060f1SDimitry Andric 
27470b57cec5SDimitry Andric void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2748fe6060f1SDimitry Andric   visitInstOperands(UO);
27490b57cec5SDimitry Andric }
27500b57cec5SDimitry Andric 
27510b57cec5SDimitry Andric void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2752fe6060f1SDimitry Andric   visitInstOperands(BO);
27530b57cec5SDimitry Andric }
27540b57cec5SDimitry Andric 
2755fe6060f1SDimitry Andric void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2756fe6060f1SDimitry Andric   // Special case: if this is the bitcast (there is exactly 1 allowed) between
2757fe6060f1SDimitry Andric   // a musttail call and a ret, don't instrument. New instructions are not
2758fe6060f1SDimitry Andric   // allowed after a musttail call.
2759fe6060f1SDimitry Andric   if (auto *CI = dyn_cast<CallInst>(BCI.getOperand(0)))
2760fe6060f1SDimitry Andric     if (CI->isMustTailCall())
2761fe6060f1SDimitry Andric       return;
2762fe6060f1SDimitry Andric   visitInstOperands(BCI);
2763fe6060f1SDimitry Andric }
2764fe6060f1SDimitry Andric 
2765fe6060f1SDimitry Andric void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
27660b57cec5SDimitry Andric 
27675ffd83dbSDimitry Andric void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2768fe6060f1SDimitry Andric   visitInstOperands(CI);
27695ffd83dbSDimitry Andric   if (ClEventCallbacks) {
27705ffd83dbSDimitry Andric     IRBuilder<> IRB(&CI);
2771fe6060f1SDimitry Andric     Value *CombinedShadow = DFSF.getShadow(&CI);
2772bdd1243dSDimitry Andric     CallInst *CallI =
27735ffd83dbSDimitry Andric         IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2774bdd1243dSDimitry Andric     CallI->addParamAttr(0, Attribute::ZExt);
27755ffd83dbSDimitry Andric   }
27765ffd83dbSDimitry Andric }
27770b57cec5SDimitry Andric 
2778fe6060f1SDimitry Andric void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2779fe6060f1SDimitry Andric   // We do not need to track data through LandingPadInst.
2780fe6060f1SDimitry Andric   //
2781fe6060f1SDimitry Andric   // For the C++ exceptions, if a value is thrown, this value will be stored
2782fe6060f1SDimitry Andric   // in a memory location provided by __cxa_allocate_exception(...) (on the
2783fe6060f1SDimitry Andric   // throw side) or  __cxa_begin_catch(...) (on the catch side).
2784fe6060f1SDimitry Andric   // This memory will have a shadow, so with the loads and stores we will be
2785fe6060f1SDimitry Andric   // able to propagate labels on data thrown through exceptions, without any
2786fe6060f1SDimitry Andric   // special handling of the LandingPadInst.
2787fe6060f1SDimitry Andric   //
2788fe6060f1SDimitry Andric   // The second element in the pair result of the LandingPadInst is a
2789fe6060f1SDimitry Andric   // register value, but it is for a type ID and should never be tainted.
2790fe6060f1SDimitry Andric   DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2791fe6060f1SDimitry Andric   DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2792fe6060f1SDimitry Andric }
2793fe6060f1SDimitry Andric 
27940b57cec5SDimitry Andric void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
279581ad6265SDimitry Andric   if (ClCombineOffsetLabelsOnGEP ||
279681ad6265SDimitry Andric       DFSF.isLookupTableConstant(
279781ad6265SDimitry Andric           StripPointerGEPsAndCasts(GEPI.getPointerOperand()))) {
2798fe6060f1SDimitry Andric     visitInstOperands(GEPI);
2799fe6060f1SDimitry Andric     return;
2800fe6060f1SDimitry Andric   }
2801fe6060f1SDimitry Andric 
2802fe6060f1SDimitry Andric   // Only propagate shadow/origin of base pointer value but ignore those of
2803fe6060f1SDimitry Andric   // offset operands.
2804fe6060f1SDimitry Andric   Value *BasePointer = GEPI.getPointerOperand();
2805fe6060f1SDimitry Andric   DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2806fe6060f1SDimitry Andric   if (DFSF.DFS.shouldTrackOrigins())
2807fe6060f1SDimitry Andric     DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
28080b57cec5SDimitry Andric }
28090b57cec5SDimitry Andric 
28100b57cec5SDimitry Andric void DFSanVisitor::visitExtractElementInst(ExtractElementInst &I) {
2811fe6060f1SDimitry Andric   visitInstOperands(I);
28120b57cec5SDimitry Andric }
28130b57cec5SDimitry Andric 
28140b57cec5SDimitry Andric void DFSanVisitor::visitInsertElementInst(InsertElementInst &I) {
2815fe6060f1SDimitry Andric   visitInstOperands(I);
28160b57cec5SDimitry Andric }
28170b57cec5SDimitry Andric 
28180b57cec5SDimitry Andric void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &I) {
2819fe6060f1SDimitry Andric   visitInstOperands(I);
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric void DFSanVisitor::visitExtractValueInst(ExtractValueInst &I) {
2823e8d8bef9SDimitry Andric   IRBuilder<> IRB(&I);
2824e8d8bef9SDimitry Andric   Value *Agg = I.getAggregateOperand();
2825e8d8bef9SDimitry Andric   Value *AggShadow = DFSF.getShadow(Agg);
2826e8d8bef9SDimitry Andric   Value *ResShadow = IRB.CreateExtractValue(AggShadow, I.getIndices());
2827e8d8bef9SDimitry Andric   DFSF.setShadow(&I, ResShadow);
2828fe6060f1SDimitry Andric   visitInstOperandOrigins(I);
28290b57cec5SDimitry Andric }
28300b57cec5SDimitry Andric 
28310b57cec5SDimitry Andric void DFSanVisitor::visitInsertValueInst(InsertValueInst &I) {
2832e8d8bef9SDimitry Andric   IRBuilder<> IRB(&I);
2833e8d8bef9SDimitry Andric   Value *AggShadow = DFSF.getShadow(I.getAggregateOperand());
2834e8d8bef9SDimitry Andric   Value *InsShadow = DFSF.getShadow(I.getInsertedValueOperand());
2835e8d8bef9SDimitry Andric   Value *Res = IRB.CreateInsertValue(AggShadow, InsShadow, I.getIndices());
2836e8d8bef9SDimitry Andric   DFSF.setShadow(&I, Res);
2837fe6060f1SDimitry Andric   visitInstOperandOrigins(I);
28380b57cec5SDimitry Andric }
28390b57cec5SDimitry Andric 
28400b57cec5SDimitry Andric void DFSanVisitor::visitAllocaInst(AllocaInst &I) {
28410b57cec5SDimitry Andric   bool AllLoadsStores = true;
28420b57cec5SDimitry Andric   for (User *U : I.users()) {
28430b57cec5SDimitry Andric     if (isa<LoadInst>(U))
28440b57cec5SDimitry Andric       continue;
28450b57cec5SDimitry Andric 
28460b57cec5SDimitry Andric     if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
28470b57cec5SDimitry Andric       if (SI->getPointerOperand() == &I)
28480b57cec5SDimitry Andric         continue;
28490b57cec5SDimitry Andric     }
28500b57cec5SDimitry Andric 
28510b57cec5SDimitry Andric     AllLoadsStores = false;
28520b57cec5SDimitry Andric     break;
28530b57cec5SDimitry Andric   }
28540b57cec5SDimitry Andric   if (AllLoadsStores) {
28550b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
2856e8d8bef9SDimitry Andric     DFSF.AllocaShadowMap[&I] = IRB.CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2857fe6060f1SDimitry Andric     if (DFSF.DFS.shouldTrackOrigins()) {
2858fe6060f1SDimitry Andric       DFSF.AllocaOriginMap[&I] =
2859fe6060f1SDimitry Andric           IRB.CreateAlloca(DFSF.DFS.OriginTy, nullptr, "_dfsa");
2860fe6060f1SDimitry Andric     }
28610b57cec5SDimitry Andric   }
2862e8d8bef9SDimitry Andric   DFSF.setShadow(&I, DFSF.DFS.ZeroPrimitiveShadow);
2863fe6060f1SDimitry Andric   DFSF.setOrigin(&I, DFSF.DFS.ZeroOrigin);
28640b57cec5SDimitry Andric }
28650b57cec5SDimitry Andric 
28660b57cec5SDimitry Andric void DFSanVisitor::visitSelectInst(SelectInst &I) {
28670b57cec5SDimitry Andric   Value *CondShadow = DFSF.getShadow(I.getCondition());
28680b57cec5SDimitry Andric   Value *TrueShadow = DFSF.getShadow(I.getTrueValue());
28690b57cec5SDimitry Andric   Value *FalseShadow = DFSF.getShadow(I.getFalseValue());
2870e8d8bef9SDimitry Andric   Value *ShadowSel = nullptr;
2871fe6060f1SDimitry Andric   const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2872fe6060f1SDimitry Andric   std::vector<Value *> Shadows;
2873fe6060f1SDimitry Andric   std::vector<Value *> Origins;
2874fe6060f1SDimitry Andric   Value *TrueOrigin =
2875fe6060f1SDimitry Andric       ShouldTrackOrigins ? DFSF.getOrigin(I.getTrueValue()) : nullptr;
2876fe6060f1SDimitry Andric   Value *FalseOrigin =
2877fe6060f1SDimitry Andric       ShouldTrackOrigins ? DFSF.getOrigin(I.getFalseValue()) : nullptr;
28780b57cec5SDimitry Andric 
287904eeddc0SDimitry Andric   DFSF.addConditionalCallbacksIfEnabled(I, I.getCondition());
288004eeddc0SDimitry Andric 
28810b57cec5SDimitry Andric   if (isa<VectorType>(I.getCondition()->getType())) {
2882e8d8bef9SDimitry Andric     ShadowSel = DFSF.combineShadowsThenConvert(I.getType(), TrueShadow,
2883*0fca6ea1SDimitry Andric                                                FalseShadow, I.getIterator());
2884fe6060f1SDimitry Andric     if (ShouldTrackOrigins) {
2885fe6060f1SDimitry Andric       Shadows.push_back(TrueShadow);
2886fe6060f1SDimitry Andric       Shadows.push_back(FalseShadow);
2887fe6060f1SDimitry Andric       Origins.push_back(TrueOrigin);
2888fe6060f1SDimitry Andric       Origins.push_back(FalseOrigin);
2889fe6060f1SDimitry Andric     }
28900b57cec5SDimitry Andric   } else {
28910b57cec5SDimitry Andric     if (TrueShadow == FalseShadow) {
28920b57cec5SDimitry Andric       ShadowSel = TrueShadow;
2893fe6060f1SDimitry Andric       if (ShouldTrackOrigins) {
2894fe6060f1SDimitry Andric         Shadows.push_back(TrueShadow);
2895fe6060f1SDimitry Andric         Origins.push_back(TrueOrigin);
2896fe6060f1SDimitry Andric       }
28970b57cec5SDimitry Andric     } else {
2898*0fca6ea1SDimitry Andric       ShadowSel = SelectInst::Create(I.getCondition(), TrueShadow, FalseShadow,
2899*0fca6ea1SDimitry Andric                                      "", I.getIterator());
2900fe6060f1SDimitry Andric       if (ShouldTrackOrigins) {
2901fe6060f1SDimitry Andric         Shadows.push_back(ShadowSel);
2902fe6060f1SDimitry Andric         Origins.push_back(SelectInst::Create(I.getCondition(), TrueOrigin,
2903*0fca6ea1SDimitry Andric                                              FalseOrigin, "", I.getIterator()));
2904fe6060f1SDimitry Andric       }
29050b57cec5SDimitry Andric     }
29060b57cec5SDimitry Andric   }
2907*0fca6ea1SDimitry Andric   DFSF.setShadow(&I, ClTrackSelectControlFlow ? DFSF.combineShadowsThenConvert(
2908*0fca6ea1SDimitry Andric                                                     I.getType(), CondShadow,
2909*0fca6ea1SDimitry Andric                                                     ShadowSel, I.getIterator())
2910e8d8bef9SDimitry Andric                                               : ShadowSel);
2911fe6060f1SDimitry Andric   if (ShouldTrackOrigins) {
2912fe6060f1SDimitry Andric     if (ClTrackSelectControlFlow) {
2913fe6060f1SDimitry Andric       Shadows.push_back(CondShadow);
2914fe6060f1SDimitry Andric       Origins.push_back(DFSF.getOrigin(I.getCondition()));
2915fe6060f1SDimitry Andric     }
2916*0fca6ea1SDimitry Andric     DFSF.setOrigin(&I, DFSF.combineOrigins(Shadows, Origins, I.getIterator()));
2917fe6060f1SDimitry Andric   }
29180b57cec5SDimitry Andric }
29190b57cec5SDimitry Andric 
29200b57cec5SDimitry Andric void DFSanVisitor::visitMemSetInst(MemSetInst &I) {
29210b57cec5SDimitry Andric   IRBuilder<> IRB(&I);
29220b57cec5SDimitry Andric   Value *ValShadow = DFSF.getShadow(I.getValue());
2923fe6060f1SDimitry Andric   Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2924fe6060f1SDimitry Andric                          ? DFSF.getOrigin(I.getValue())
2925fe6060f1SDimitry Andric                          : DFSF.DFS.ZeroOrigin;
29265f757f3fSDimitry Andric   IRB.CreateCall(DFSF.DFS.DFSanSetLabelFn,
29275f757f3fSDimitry Andric                  {ValShadow, ValOrigin, I.getDest(),
29280b57cec5SDimitry Andric                   IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
29290b57cec5SDimitry Andric }
29300b57cec5SDimitry Andric 
29310b57cec5SDimitry Andric void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) {
29320b57cec5SDimitry Andric   IRBuilder<> IRB(&I);
2933fe6060f1SDimitry Andric 
2934fe6060f1SDimitry Andric   // CopyOrMoveOrigin transfers origins by refering to their shadows. So we
2935fe6060f1SDimitry Andric   // need to move origins before moving shadows.
2936fe6060f1SDimitry Andric   if (DFSF.DFS.shouldTrackOrigins()) {
2937fe6060f1SDimitry Andric     IRB.CreateCall(
2938fe6060f1SDimitry Andric         DFSF.DFS.DFSanMemOriginTransferFn,
29395f757f3fSDimitry Andric         {I.getArgOperand(0), I.getArgOperand(1),
2940fe6060f1SDimitry Andric          IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2941fe6060f1SDimitry Andric   }
2942fe6060f1SDimitry Andric 
2943*0fca6ea1SDimitry Andric   Value *DestShadow = DFSF.DFS.getShadowAddress(I.getDest(), I.getIterator());
2944*0fca6ea1SDimitry Andric   Value *SrcShadow = DFSF.DFS.getShadowAddress(I.getSource(), I.getIterator());
29455ffd83dbSDimitry Andric   Value *LenShadow =
29465ffd83dbSDimitry Andric       IRB.CreateMul(I.getLength(), ConstantInt::get(I.getLength()->getType(),
29475ffd83dbSDimitry Andric                                                     DFSF.DFS.ShadowWidthBytes));
29480b57cec5SDimitry Andric   auto *MTI = cast<MemTransferInst>(
29495ffd83dbSDimitry Andric       IRB.CreateCall(I.getFunctionType(), I.getCalledOperand(),
29500b57cec5SDimitry Andric                      {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
295181ad6265SDimitry Andric   MTI->setDestAlignment(DFSF.getShadowAlign(I.getDestAlign().valueOrOne()));
295281ad6265SDimitry Andric   MTI->setSourceAlignment(DFSF.getShadowAlign(I.getSourceAlign().valueOrOne()));
29535ffd83dbSDimitry Andric   if (ClEventCallbacks) {
29545f757f3fSDimitry Andric     IRB.CreateCall(
29555f757f3fSDimitry Andric         DFSF.DFS.DFSanMemTransferCallbackFn,
29565f757f3fSDimitry Andric         {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
29570b57cec5SDimitry Andric   }
29580b57cec5SDimitry Andric }
29590b57cec5SDimitry Andric 
296004eeddc0SDimitry Andric void DFSanVisitor::visitBranchInst(BranchInst &BR) {
296104eeddc0SDimitry Andric   if (!BR.isConditional())
296204eeddc0SDimitry Andric     return;
296304eeddc0SDimitry Andric 
296404eeddc0SDimitry Andric   DFSF.addConditionalCallbacksIfEnabled(BR, BR.getCondition());
296504eeddc0SDimitry Andric }
296604eeddc0SDimitry Andric 
296704eeddc0SDimitry Andric void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
296804eeddc0SDimitry Andric   DFSF.addConditionalCallbacksIfEnabled(SW, SW.getCondition());
296904eeddc0SDimitry Andric }
297004eeddc0SDimitry Andric 
2971fe6060f1SDimitry Andric static bool isAMustTailRetVal(Value *RetVal) {
2972fe6060f1SDimitry Andric   // Tail call may have a bitcast between return.
2973fe6060f1SDimitry Andric   if (auto *I = dyn_cast<BitCastInst>(RetVal)) {
2974fe6060f1SDimitry Andric     RetVal = I->getOperand(0);
2975fe6060f1SDimitry Andric   }
2976fe6060f1SDimitry Andric   if (auto *I = dyn_cast<CallInst>(RetVal)) {
2977fe6060f1SDimitry Andric     return I->isMustTailCall();
2978fe6060f1SDimitry Andric   }
2979fe6060f1SDimitry Andric   return false;
2980fe6060f1SDimitry Andric }
2981fe6060f1SDimitry Andric 
29820b57cec5SDimitry Andric void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
29830b57cec5SDimitry Andric   if (!DFSF.IsNativeABI && RI.getReturnValue()) {
2984fe6060f1SDimitry Andric     // Don't emit the instrumentation for musttail call returns.
2985fe6060f1SDimitry Andric     if (isAMustTailRetVal(RI.getReturnValue()))
2986fe6060f1SDimitry Andric       return;
2987fe6060f1SDimitry Andric 
29880b57cec5SDimitry Andric     Value *S = DFSF.getShadow(RI.getReturnValue());
29890b57cec5SDimitry Andric     IRBuilder<> IRB(&RI);
2990e8d8bef9SDimitry Andric     Type *RT = DFSF.F->getFunctionType()->getReturnType();
2991349cc55cSDimitry Andric     unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2992fe6060f1SDimitry Andric     if (Size <= RetvalTLSSize) {
2993e8d8bef9SDimitry Andric       // If the size overflows, stores nothing. At callsite, oversized return
2994e8d8bef9SDimitry Andric       // shadows are set to zero.
2995349cc55cSDimitry Andric       IRB.CreateAlignedStore(S, DFSF.getRetvalTLS(RT, IRB), ShadowTLSAlignment);
2996fe6060f1SDimitry Andric     }
2997fe6060f1SDimitry Andric     if (DFSF.DFS.shouldTrackOrigins()) {
2998fe6060f1SDimitry Andric       Value *O = DFSF.getOrigin(RI.getReturnValue());
2999fe6060f1SDimitry Andric       IRB.CreateStore(O, DFSF.getRetvalOriginTLS());
3000e8d8bef9SDimitry Andric     }
30010b57cec5SDimitry Andric   }
30020b57cec5SDimitry Andric }
30030b57cec5SDimitry Andric 
3004fe6060f1SDimitry Andric void DFSanVisitor::addShadowArguments(Function &F, CallBase &CB,
3005fe6060f1SDimitry Andric                                       std::vector<Value *> &Args,
3006fe6060f1SDimitry Andric                                       IRBuilder<> &IRB) {
3007fe6060f1SDimitry Andric   FunctionType *FT = F.getFunctionType();
3008fe6060f1SDimitry Andric 
3009fe6060f1SDimitry Andric   auto *I = CB.arg_begin();
3010fe6060f1SDimitry Andric 
3011fe6060f1SDimitry Andric   // Adds non-variable argument shadows.
3012fe6060f1SDimitry Andric   for (unsigned N = FT->getNumParams(); N != 0; ++I, --N)
3013*0fca6ea1SDimitry Andric     Args.push_back(
3014*0fca6ea1SDimitry Andric         DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*I), CB.getIterator()));
3015fe6060f1SDimitry Andric 
3016fe6060f1SDimitry Andric   // Adds variable argument shadows.
3017fe6060f1SDimitry Andric   if (FT->isVarArg()) {
3018fe6060f1SDimitry Andric     auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3019fe6060f1SDimitry Andric                                      CB.arg_size() - FT->getNumParams());
3020fe6060f1SDimitry Andric     auto *LabelVAAlloca =
3021fe6060f1SDimitry Andric         new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3022*0fca6ea1SDimitry Andric                        "labelva", DFSF.F->getEntryBlock().begin());
3023fe6060f1SDimitry Andric 
3024fe6060f1SDimitry Andric     for (unsigned N = 0; I != CB.arg_end(); ++I, ++N) {
3025fe6060f1SDimitry Andric       auto *LabelVAPtr = IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, N);
3026*0fca6ea1SDimitry Andric       IRB.CreateStore(
3027*0fca6ea1SDimitry Andric           DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*I), CB.getIterator()),
3028fe6060f1SDimitry Andric           LabelVAPtr);
30290b57cec5SDimitry Andric     }
30300b57cec5SDimitry Andric 
3031fe6060f1SDimitry Andric     Args.push_back(IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, 0));
3032fe6060f1SDimitry Andric   }
30330b57cec5SDimitry Andric 
3034fe6060f1SDimitry Andric   // Adds the return value shadow.
3035fe6060f1SDimitry Andric   if (!FT->getReturnType()->isVoidTy()) {
3036fe6060f1SDimitry Andric     if (!DFSF.LabelReturnAlloca) {
3037fe6060f1SDimitry Andric       DFSF.LabelReturnAlloca = new AllocaInst(
3038fe6060f1SDimitry Andric           DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3039*0fca6ea1SDimitry Andric           "labelreturn", DFSF.F->getEntryBlock().begin());
3040fe6060f1SDimitry Andric     }
3041fe6060f1SDimitry Andric     Args.push_back(DFSF.LabelReturnAlloca);
3042fe6060f1SDimitry Andric   }
3043fe6060f1SDimitry Andric }
3044fe6060f1SDimitry Andric 
3045fe6060f1SDimitry Andric void DFSanVisitor::addOriginArguments(Function &F, CallBase &CB,
3046fe6060f1SDimitry Andric                                       std::vector<Value *> &Args,
3047fe6060f1SDimitry Andric                                       IRBuilder<> &IRB) {
3048fe6060f1SDimitry Andric   FunctionType *FT = F.getFunctionType();
3049fe6060f1SDimitry Andric 
3050fe6060f1SDimitry Andric   auto *I = CB.arg_begin();
3051fe6060f1SDimitry Andric 
3052fe6060f1SDimitry Andric   // Add non-variable argument origins.
3053fe6060f1SDimitry Andric   for (unsigned N = FT->getNumParams(); N != 0; ++I, --N)
3054fe6060f1SDimitry Andric     Args.push_back(DFSF.getOrigin(*I));
3055fe6060f1SDimitry Andric 
3056fe6060f1SDimitry Andric   // Add variable argument origins.
3057fe6060f1SDimitry Andric   if (FT->isVarArg()) {
3058fe6060f1SDimitry Andric     auto *OriginVATy =
3059fe6060f1SDimitry Andric         ArrayType::get(DFSF.DFS.OriginTy, CB.arg_size() - FT->getNumParams());
3060fe6060f1SDimitry Andric     auto *OriginVAAlloca =
3061fe6060f1SDimitry Andric         new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3062*0fca6ea1SDimitry Andric                        "originva", DFSF.F->getEntryBlock().begin());
3063fe6060f1SDimitry Andric 
3064fe6060f1SDimitry Andric     for (unsigned N = 0; I != CB.arg_end(); ++I, ++N) {
3065fe6060f1SDimitry Andric       auto *OriginVAPtr = IRB.CreateStructGEP(OriginVATy, OriginVAAlloca, N);
3066fe6060f1SDimitry Andric       IRB.CreateStore(DFSF.getOrigin(*I), OriginVAPtr);
3067fe6060f1SDimitry Andric     }
3068fe6060f1SDimitry Andric 
3069fe6060f1SDimitry Andric     Args.push_back(IRB.CreateStructGEP(OriginVATy, OriginVAAlloca, 0));
3070fe6060f1SDimitry Andric   }
3071fe6060f1SDimitry Andric 
3072fe6060f1SDimitry Andric   // Add the return value origin.
3073fe6060f1SDimitry Andric   if (!FT->getReturnType()->isVoidTy()) {
3074fe6060f1SDimitry Andric     if (!DFSF.OriginReturnAlloca) {
3075fe6060f1SDimitry Andric       DFSF.OriginReturnAlloca = new AllocaInst(
3076fe6060f1SDimitry Andric           DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3077*0fca6ea1SDimitry Andric           "originreturn", DFSF.F->getEntryBlock().begin());
3078fe6060f1SDimitry Andric     }
3079fe6060f1SDimitry Andric     Args.push_back(DFSF.OriginReturnAlloca);
3080fe6060f1SDimitry Andric   }
3081fe6060f1SDimitry Andric }
3082fe6060f1SDimitry Andric 
3083fe6060f1SDimitry Andric bool DFSanVisitor::visitWrappedCallBase(Function &F, CallBase &CB) {
30845ffd83dbSDimitry Andric   IRBuilder<> IRB(&CB);
3085fe6060f1SDimitry Andric   switch (DFSF.DFS.getWrapperKind(&F)) {
30860b57cec5SDimitry Andric   case DataFlowSanitizer::WK_Warning:
3087fe6060f1SDimitry Andric     CB.setCalledFunction(&F);
30880b57cec5SDimitry Andric     IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3089fe6060f1SDimitry Andric                    IRB.CreateGlobalStringPtr(F.getName()));
309081ad6265SDimitry Andric     DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3091e8d8bef9SDimitry Andric     DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3092fe6060f1SDimitry Andric     DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3093fe6060f1SDimitry Andric     return true;
30940b57cec5SDimitry Andric   case DataFlowSanitizer::WK_Discard:
3095fe6060f1SDimitry Andric     CB.setCalledFunction(&F);
309681ad6265SDimitry Andric     DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3097e8d8bef9SDimitry Andric     DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3098fe6060f1SDimitry Andric     DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3099fe6060f1SDimitry Andric     return true;
31000b57cec5SDimitry Andric   case DataFlowSanitizer::WK_Functional:
3101fe6060f1SDimitry Andric     CB.setCalledFunction(&F);
310281ad6265SDimitry Andric     DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3103fe6060f1SDimitry Andric     visitInstOperands(CB);
3104fe6060f1SDimitry Andric     return true;
31050b57cec5SDimitry Andric   case DataFlowSanitizer::WK_Custom:
31060b57cec5SDimitry Andric     // Don't try to handle invokes of custom functions, it's too complicated.
31070b57cec5SDimitry Andric     // Instead, invoke the dfsw$ wrapper, which will in turn call the __dfsw_
31080b57cec5SDimitry Andric     // wrapper.
3109fe6060f1SDimitry Andric     CallInst *CI = dyn_cast<CallInst>(&CB);
3110fe6060f1SDimitry Andric     if (!CI)
3111fe6060f1SDimitry Andric       return false;
3112fe6060f1SDimitry Andric 
3113fe6060f1SDimitry Andric     const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3114fe6060f1SDimitry Andric     FunctionType *FT = F.getFunctionType();
31150b57cec5SDimitry Andric     TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3116fe6060f1SDimitry Andric     std::string CustomFName = ShouldTrackOrigins ? "__dfso_" : "__dfsw_";
3117fe6060f1SDimitry Andric     CustomFName += F.getName();
31180b57cec5SDimitry Andric     FunctionCallee CustomF = DFSF.DFS.Mod->getOrInsertFunction(
31190b57cec5SDimitry Andric         CustomFName, CustomFn.TransformedType);
31200b57cec5SDimitry Andric     if (Function *CustomFn = dyn_cast<Function>(CustomF.getCallee())) {
3121fe6060f1SDimitry Andric       CustomFn->copyAttributesFrom(&F);
31220b57cec5SDimitry Andric 
31230b57cec5SDimitry Andric       // Custom functions returning non-void will write to the return label.
31240b57cec5SDimitry Andric       if (!FT->getReturnType()->isVoidTy()) {
3125349cc55cSDimitry Andric         CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
31260b57cec5SDimitry Andric       }
31270b57cec5SDimitry Andric     }
31280b57cec5SDimitry Andric 
31290b57cec5SDimitry Andric     std::vector<Value *> Args;
31300b57cec5SDimitry Andric 
3131fe6060f1SDimitry Andric     // Adds non-variable arguments.
3132fe6060f1SDimitry Andric     auto *I = CB.arg_begin();
3133fe6060f1SDimitry Andric     for (unsigned N = FT->getNumParams(); N != 0; ++I, --N) {
3134fe6060f1SDimitry Andric       Args.push_back(*I);
31350b57cec5SDimitry Andric     }
31360b57cec5SDimitry Andric 
3137fe6060f1SDimitry Andric     // Adds shadow arguments.
31380b57cec5SDimitry Andric     const unsigned ShadowArgStart = Args.size();
3139fe6060f1SDimitry Andric     addShadowArguments(F, CB, Args, IRB);
31400b57cec5SDimitry Andric 
3141fe6060f1SDimitry Andric     // Adds origin arguments.
3142fe6060f1SDimitry Andric     const unsigned OriginArgStart = Args.size();
3143fe6060f1SDimitry Andric     if (ShouldTrackOrigins)
3144fe6060f1SDimitry Andric       addOriginArguments(F, CB, Args, IRB);
31450b57cec5SDimitry Andric 
3146fe6060f1SDimitry Andric     // Adds variable arguments.
3147fe6060f1SDimitry Andric     append_range(Args, drop_begin(CB.args(), FT->getNumParams()));
31480b57cec5SDimitry Andric 
31490b57cec5SDimitry Andric     CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
31500b57cec5SDimitry Andric     CustomCI->setCallingConv(CI->getCallingConv());
3151fe6060f1SDimitry Andric     CustomCI->setAttributes(transformFunctionAttributes(
3152fe6060f1SDimitry Andric         CustomFn, CI->getContext(), CI->getAttributes()));
31530b57cec5SDimitry Andric 
31540b57cec5SDimitry Andric     // Update the parameter attributes of the custom call instruction to
31550b57cec5SDimitry Andric     // zero extend the shadow parameters. This is required for targets
3156e8d8bef9SDimitry Andric     // which consider PrimitiveShadowTy an illegal type.
3157fe6060f1SDimitry Andric     for (unsigned N = 0; N < FT->getNumParams(); N++) {
3158fe6060f1SDimitry Andric       const unsigned ArgNo = ShadowArgStart + N;
3159e8d8bef9SDimitry Andric       if (CustomCI->getArgOperand(ArgNo)->getType() ==
3160e8d8bef9SDimitry Andric           DFSF.DFS.PrimitiveShadowTy)
31610b57cec5SDimitry Andric         CustomCI->addParamAttr(ArgNo, Attribute::ZExt);
3162fe6060f1SDimitry Andric       if (ShouldTrackOrigins) {
3163fe6060f1SDimitry Andric         const unsigned OriginArgNo = OriginArgStart + N;
3164fe6060f1SDimitry Andric         if (CustomCI->getArgOperand(OriginArgNo)->getType() ==
3165fe6060f1SDimitry Andric             DFSF.DFS.OriginTy)
3166fe6060f1SDimitry Andric           CustomCI->addParamAttr(OriginArgNo, Attribute::ZExt);
3167fe6060f1SDimitry Andric       }
31680b57cec5SDimitry Andric     }
31690b57cec5SDimitry Andric 
3170fe6060f1SDimitry Andric     // Loads the return value shadow and origin.
31710b57cec5SDimitry Andric     if (!FT->getReturnType()->isVoidTy()) {
3172fe6060f1SDimitry Andric       LoadInst *LabelLoad =
3173fe6060f1SDimitry Andric           IRB.CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3174*0fca6ea1SDimitry Andric       DFSF.setShadow(CustomCI,
3175*0fca6ea1SDimitry Andric                      DFSF.expandFromPrimitiveShadow(
3176*0fca6ea1SDimitry Andric                          FT->getReturnType(), LabelLoad, CB.getIterator()));
3177fe6060f1SDimitry Andric       if (ShouldTrackOrigins) {
3178fe6060f1SDimitry Andric         LoadInst *OriginLoad =
3179fe6060f1SDimitry Andric             IRB.CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3180fe6060f1SDimitry Andric         DFSF.setOrigin(CustomCI, OriginLoad);
3181fe6060f1SDimitry Andric       }
31820b57cec5SDimitry Andric     }
31830b57cec5SDimitry Andric 
31840b57cec5SDimitry Andric     CI->replaceAllUsesWith(CustomCI);
31850b57cec5SDimitry Andric     CI->eraseFromParent();
3186fe6060f1SDimitry Andric     return true;
31870b57cec5SDimitry Andric   }
3188fe6060f1SDimitry Andric   return false;
31890b57cec5SDimitry Andric }
31900b57cec5SDimitry Andric 
3191bdd1243dSDimitry Andric Value *DFSanVisitor::makeAddAcquireOrderingTable(IRBuilder<> &IRB) {
3192bdd1243dSDimitry Andric   constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3193bdd1243dSDimitry Andric   uint32_t OrderingTable[NumOrderings] = {};
3194bdd1243dSDimitry Andric 
3195bdd1243dSDimitry Andric   OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3196bdd1243dSDimitry Andric       OrderingTable[(int)AtomicOrderingCABI::acquire] =
3197bdd1243dSDimitry Andric           OrderingTable[(int)AtomicOrderingCABI::consume] =
3198bdd1243dSDimitry Andric               (int)AtomicOrderingCABI::acquire;
3199bdd1243dSDimitry Andric   OrderingTable[(int)AtomicOrderingCABI::release] =
3200bdd1243dSDimitry Andric       OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3201bdd1243dSDimitry Andric           (int)AtomicOrderingCABI::acq_rel;
3202bdd1243dSDimitry Andric   OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3203bdd1243dSDimitry Andric       (int)AtomicOrderingCABI::seq_cst;
3204bdd1243dSDimitry Andric 
3205*0fca6ea1SDimitry Andric   return ConstantDataVector::get(IRB.getContext(), OrderingTable);
3206bdd1243dSDimitry Andric }
3207bdd1243dSDimitry Andric 
3208bdd1243dSDimitry Andric void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3209bdd1243dSDimitry Andric   // Since we use getNextNode here, we can't have CB terminate the BB.
3210bdd1243dSDimitry Andric   assert(isa<CallInst>(CB));
3211bdd1243dSDimitry Andric 
3212bdd1243dSDimitry Andric   IRBuilder<> IRB(&CB);
3213bdd1243dSDimitry Andric   Value *Size = CB.getArgOperand(0);
3214bdd1243dSDimitry Andric   Value *SrcPtr = CB.getArgOperand(1);
3215bdd1243dSDimitry Andric   Value *DstPtr = CB.getArgOperand(2);
3216bdd1243dSDimitry Andric   Value *Ordering = CB.getArgOperand(3);
3217bdd1243dSDimitry Andric   // Convert the call to have at least Acquire ordering to make sure
3218bdd1243dSDimitry Andric   // the shadow operations aren't reordered before it.
3219bdd1243dSDimitry Andric   Value *NewOrdering =
3220bdd1243dSDimitry Andric       IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);
3221bdd1243dSDimitry Andric   CB.setArgOperand(3, NewOrdering);
3222bdd1243dSDimitry Andric 
3223bdd1243dSDimitry Andric   IRBuilder<> NextIRB(CB.getNextNode());
3224bdd1243dSDimitry Andric   NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
3225bdd1243dSDimitry Andric 
3226bdd1243dSDimitry Andric   // TODO: Support ClCombinePointerLabelsOnLoad
3227bdd1243dSDimitry Andric   // TODO: Support ClEventCallbacks
3228bdd1243dSDimitry Andric 
32295f757f3fSDimitry Andric   NextIRB.CreateCall(
32305f757f3fSDimitry Andric       DFSF.DFS.DFSanMemShadowOriginTransferFn,
32315f757f3fSDimitry Andric       {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3232bdd1243dSDimitry Andric }
3233bdd1243dSDimitry Andric 
3234bdd1243dSDimitry Andric Value *DFSanVisitor::makeAddReleaseOrderingTable(IRBuilder<> &IRB) {
3235bdd1243dSDimitry Andric   constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3236bdd1243dSDimitry Andric   uint32_t OrderingTable[NumOrderings] = {};
3237bdd1243dSDimitry Andric 
3238bdd1243dSDimitry Andric   OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3239bdd1243dSDimitry Andric       OrderingTable[(int)AtomicOrderingCABI::release] =
3240bdd1243dSDimitry Andric           (int)AtomicOrderingCABI::release;
3241bdd1243dSDimitry Andric   OrderingTable[(int)AtomicOrderingCABI::consume] =
3242bdd1243dSDimitry Andric       OrderingTable[(int)AtomicOrderingCABI::acquire] =
3243bdd1243dSDimitry Andric           OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3244bdd1243dSDimitry Andric               (int)AtomicOrderingCABI::acq_rel;
3245bdd1243dSDimitry Andric   OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3246bdd1243dSDimitry Andric       (int)AtomicOrderingCABI::seq_cst;
3247bdd1243dSDimitry Andric 
3248*0fca6ea1SDimitry Andric   return ConstantDataVector::get(IRB.getContext(), OrderingTable);
3249bdd1243dSDimitry Andric }
3250bdd1243dSDimitry Andric 
3251bdd1243dSDimitry Andric void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3252bdd1243dSDimitry Andric   IRBuilder<> IRB(&CB);
3253bdd1243dSDimitry Andric   Value *Size = CB.getArgOperand(0);
3254bdd1243dSDimitry Andric   Value *SrcPtr = CB.getArgOperand(1);
3255bdd1243dSDimitry Andric   Value *DstPtr = CB.getArgOperand(2);
3256bdd1243dSDimitry Andric   Value *Ordering = CB.getArgOperand(3);
3257bdd1243dSDimitry Andric   // Convert the call to have at least Release ordering to make sure
3258bdd1243dSDimitry Andric   // the shadow operations aren't reordered after it.
3259bdd1243dSDimitry Andric   Value *NewOrdering =
3260bdd1243dSDimitry Andric       IRB.CreateExtractElement(makeAddReleaseOrderingTable(IRB), Ordering);
3261bdd1243dSDimitry Andric   CB.setArgOperand(3, NewOrdering);
3262bdd1243dSDimitry Andric 
3263bdd1243dSDimitry Andric   // TODO: Support ClCombinePointerLabelsOnStore
3264bdd1243dSDimitry Andric   // TODO: Support ClEventCallbacks
3265bdd1243dSDimitry Andric 
32665f757f3fSDimitry Andric   IRB.CreateCall(
32675f757f3fSDimitry Andric       DFSF.DFS.DFSanMemShadowOriginTransferFn,
32685f757f3fSDimitry Andric       {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3269bdd1243dSDimitry Andric }
3270bdd1243dSDimitry Andric 
3271bdd1243dSDimitry Andric void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3272bdd1243dSDimitry Andric   // void __atomic_exchange(size_t size, void *ptr, void *val, void *ret, int
3273bdd1243dSDimitry Andric   // ordering)
3274bdd1243dSDimitry Andric   IRBuilder<> IRB(&CB);
3275bdd1243dSDimitry Andric   Value *Size = CB.getArgOperand(0);
3276bdd1243dSDimitry Andric   Value *TargetPtr = CB.getArgOperand(1);
3277bdd1243dSDimitry Andric   Value *SrcPtr = CB.getArgOperand(2);
3278bdd1243dSDimitry Andric   Value *DstPtr = CB.getArgOperand(3);
3279bdd1243dSDimitry Andric 
3280bdd1243dSDimitry Andric   // This operation is not atomic for the shadow and origin memory.
3281bdd1243dSDimitry Andric   // This could result in DFSan false positives or false negatives.
3282bdd1243dSDimitry Andric   // For now we will assume these operations are rare, and
3283bdd1243dSDimitry Andric   // the additional complexity to address this is not warrented.
3284bdd1243dSDimitry Andric 
3285bdd1243dSDimitry Andric   // Current Target to Dest
32865f757f3fSDimitry Andric   IRB.CreateCall(
32875f757f3fSDimitry Andric       DFSF.DFS.DFSanMemShadowOriginTransferFn,
32885f757f3fSDimitry Andric       {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3289bdd1243dSDimitry Andric 
3290bdd1243dSDimitry Andric   // Current Src to Target (overriding)
32915f757f3fSDimitry Andric   IRB.CreateCall(
32925f757f3fSDimitry Andric       DFSF.DFS.DFSanMemShadowOriginTransferFn,
32935f757f3fSDimitry Andric       {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3294bdd1243dSDimitry Andric }
3295bdd1243dSDimitry Andric 
3296bdd1243dSDimitry Andric void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3297bdd1243dSDimitry Andric   // bool __atomic_compare_exchange(size_t size, void *ptr, void *expected, void
3298bdd1243dSDimitry Andric   // *desired, int success_order, int failure_order)
3299bdd1243dSDimitry Andric   Value *Size = CB.getArgOperand(0);
3300bdd1243dSDimitry Andric   Value *TargetPtr = CB.getArgOperand(1);
3301bdd1243dSDimitry Andric   Value *ExpectedPtr = CB.getArgOperand(2);
3302bdd1243dSDimitry Andric   Value *DesiredPtr = CB.getArgOperand(3);
3303bdd1243dSDimitry Andric 
3304bdd1243dSDimitry Andric   // This operation is not atomic for the shadow and origin memory.
3305bdd1243dSDimitry Andric   // This could result in DFSan false positives or false negatives.
3306bdd1243dSDimitry Andric   // For now we will assume these operations are rare, and
3307bdd1243dSDimitry Andric   // the additional complexity to address this is not warrented.
3308bdd1243dSDimitry Andric 
3309bdd1243dSDimitry Andric   IRBuilder<> NextIRB(CB.getNextNode());
3310bdd1243dSDimitry Andric   NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
3311bdd1243dSDimitry Andric 
3312bdd1243dSDimitry Andric   DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3313bdd1243dSDimitry Andric 
3314bdd1243dSDimitry Andric   // If original call returned true, copy Desired to Target.
3315bdd1243dSDimitry Andric   // If original call returned false, copy Target to Expected.
33165f757f3fSDimitry Andric   NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3317bdd1243dSDimitry Andric                      {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
33185f757f3fSDimitry Andric                       TargetPtr, ExpectedPtr, DesiredPtr,
3319bdd1243dSDimitry Andric                       NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3320bdd1243dSDimitry Andric }
3321bdd1243dSDimitry Andric 
3322fe6060f1SDimitry Andric void DFSanVisitor::visitCallBase(CallBase &CB) {
3323fe6060f1SDimitry Andric   Function *F = CB.getCalledFunction();
3324fe6060f1SDimitry Andric   if ((F && F->isIntrinsic()) || CB.isInlineAsm()) {
3325fe6060f1SDimitry Andric     visitInstOperands(CB);
3326fe6060f1SDimitry Andric     return;
3327fe6060f1SDimitry Andric   }
3328fe6060f1SDimitry Andric 
3329fe6060f1SDimitry Andric   // Calls to this function are synthesized in wrappers, and we shouldn't
3330fe6060f1SDimitry Andric   // instrument them.
3331fe6060f1SDimitry Andric   if (F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3332fe6060f1SDimitry Andric     return;
3333fe6060f1SDimitry Andric 
3334bdd1243dSDimitry Andric   LibFunc LF;
3335bdd1243dSDimitry Andric   if (DFSF.TLI.getLibFunc(CB, LF)) {
3336bdd1243dSDimitry Andric     // libatomic.a functions need to have special handling because there isn't
3337bdd1243dSDimitry Andric     // a good way to intercept them or compile the library with
3338bdd1243dSDimitry Andric     // instrumentation.
3339bdd1243dSDimitry Andric     switch (LF) {
3340bdd1243dSDimitry Andric     case LibFunc_atomic_load:
3341bdd1243dSDimitry Andric       if (!isa<CallInst>(CB)) {
3342bdd1243dSDimitry Andric         llvm::errs() << "DFSAN -- cannot instrument invoke of libatomic load. "
3343bdd1243dSDimitry Andric                         "Ignoring!\n";
3344bdd1243dSDimitry Andric         break;
3345bdd1243dSDimitry Andric       }
3346bdd1243dSDimitry Andric       visitLibAtomicLoad(CB);
3347bdd1243dSDimitry Andric       return;
3348bdd1243dSDimitry Andric     case LibFunc_atomic_store:
3349bdd1243dSDimitry Andric       visitLibAtomicStore(CB);
3350bdd1243dSDimitry Andric       return;
3351bdd1243dSDimitry Andric     default:
3352bdd1243dSDimitry Andric       break;
3353bdd1243dSDimitry Andric     }
3354bdd1243dSDimitry Andric   }
3355bdd1243dSDimitry Andric 
3356bdd1243dSDimitry Andric   // TODO: These are not supported by TLI? They are not in the enum.
3357bdd1243dSDimitry Andric   if (F && F->hasName() && !F->isVarArg()) {
3358bdd1243dSDimitry Andric     if (F->getName() == "__atomic_exchange") {
3359bdd1243dSDimitry Andric       visitLibAtomicExchange(CB);
3360bdd1243dSDimitry Andric       return;
3361bdd1243dSDimitry Andric     }
3362bdd1243dSDimitry Andric     if (F->getName() == "__atomic_compare_exchange") {
3363bdd1243dSDimitry Andric       visitLibAtomicCompareExchange(CB);
3364bdd1243dSDimitry Andric       return;
3365bdd1243dSDimitry Andric     }
3366bdd1243dSDimitry Andric   }
3367bdd1243dSDimitry Andric 
3368fe6060f1SDimitry Andric   DenseMap<Value *, Function *>::iterator UnwrappedFnIt =
3369fe6060f1SDimitry Andric       DFSF.DFS.UnwrappedFnMap.find(CB.getCalledOperand());
3370fe6060f1SDimitry Andric   if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3371fe6060f1SDimitry Andric     if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3372fe6060f1SDimitry Andric       return;
3373fe6060f1SDimitry Andric 
3374fe6060f1SDimitry Andric   IRBuilder<> IRB(&CB);
3375fe6060f1SDimitry Andric 
3376fe6060f1SDimitry Andric   const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
33775ffd83dbSDimitry Andric   FunctionType *FT = CB.getFunctionType();
3378349cc55cSDimitry Andric   const DataLayout &DL = getDataLayout();
3379349cc55cSDimitry Andric 
3380fe6060f1SDimitry Andric   // Stores argument shadows.
3381e8d8bef9SDimitry Andric   unsigned ArgOffset = 0;
3382e8d8bef9SDimitry Andric   for (unsigned I = 0, N = FT->getNumParams(); I != N; ++I) {
3383fe6060f1SDimitry Andric     if (ShouldTrackOrigins) {
3384fe6060f1SDimitry Andric       // Ignore overflowed origins
3385fe6060f1SDimitry Andric       Value *ArgShadow = DFSF.getShadow(CB.getArgOperand(I));
3386fe6060f1SDimitry Andric       if (I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3387fe6060f1SDimitry Andric           !DFSF.DFS.isZeroShadow(ArgShadow))
3388fe6060f1SDimitry Andric         IRB.CreateStore(DFSF.getOrigin(CB.getArgOperand(I)),
3389fe6060f1SDimitry Andric                         DFSF.getArgOriginTLS(I, IRB));
3390fe6060f1SDimitry Andric     }
3391fe6060f1SDimitry Andric 
3392e8d8bef9SDimitry Andric     unsigned Size =
3393e8d8bef9SDimitry Andric         DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(I)));
3394e8d8bef9SDimitry Andric     // Stop storing if arguments' size overflows. Inside a function, arguments
3395e8d8bef9SDimitry Andric     // after overflow have zero shadow values.
3396fe6060f1SDimitry Andric     if (ArgOffset + Size > ArgTLSSize)
3397e8d8bef9SDimitry Andric       break;
3398349cc55cSDimitry Andric     IRB.CreateAlignedStore(DFSF.getShadow(CB.getArgOperand(I)),
3399e8d8bef9SDimitry Andric                            DFSF.getArgTLS(FT->getParamType(I), ArgOffset, IRB),
3400fe6060f1SDimitry Andric                            ShadowTLSAlignment);
3401fe6060f1SDimitry Andric     ArgOffset += alignTo(Size, ShadowTLSAlignment);
34020b57cec5SDimitry Andric   }
34030b57cec5SDimitry Andric 
34040b57cec5SDimitry Andric   Instruction *Next = nullptr;
34055ffd83dbSDimitry Andric   if (!CB.getType()->isVoidTy()) {
34065ffd83dbSDimitry Andric     if (InvokeInst *II = dyn_cast<InvokeInst>(&CB)) {
34070b57cec5SDimitry Andric       if (II->getNormalDest()->getSinglePredecessor()) {
34080b57cec5SDimitry Andric         Next = &II->getNormalDest()->front();
34090b57cec5SDimitry Andric       } else {
34100b57cec5SDimitry Andric         BasicBlock *NewBB =
34110b57cec5SDimitry Andric             SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
34120b57cec5SDimitry Andric         Next = &NewBB->front();
34130b57cec5SDimitry Andric       }
34140b57cec5SDimitry Andric     } else {
34155ffd83dbSDimitry Andric       assert(CB.getIterator() != CB.getParent()->end());
34165ffd83dbSDimitry Andric       Next = CB.getNextNode();
34170b57cec5SDimitry Andric     }
34180b57cec5SDimitry Andric 
3419fe6060f1SDimitry Andric     // Don't emit the epilogue for musttail call returns.
3420fe6060f1SDimitry Andric     if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3421fe6060f1SDimitry Andric       return;
3422fe6060f1SDimitry Andric 
3423fe6060f1SDimitry Andric     // Loads the return value shadow.
34240b57cec5SDimitry Andric     IRBuilder<> NextIRB(Next);
3425e8d8bef9SDimitry Andric     unsigned Size = DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3426fe6060f1SDimitry Andric     if (Size > RetvalTLSSize) {
3427e8d8bef9SDimitry Andric       // Set overflowed return shadow to be zero.
3428e8d8bef9SDimitry Andric       DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3429e8d8bef9SDimitry Andric     } else {
3430e8d8bef9SDimitry Andric       LoadInst *LI = NextIRB.CreateAlignedLoad(
3431e8d8bef9SDimitry Andric           DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.getType(), NextIRB),
3432fe6060f1SDimitry Andric           ShadowTLSAlignment, "_dfsret");
34330b57cec5SDimitry Andric       DFSF.SkipInsts.insert(LI);
34345ffd83dbSDimitry Andric       DFSF.setShadow(&CB, LI);
34350b57cec5SDimitry Andric       DFSF.NonZeroChecks.push_back(LI);
34360b57cec5SDimitry Andric     }
3437fe6060f1SDimitry Andric 
3438fe6060f1SDimitry Andric     if (ShouldTrackOrigins) {
3439349cc55cSDimitry Andric       LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3440349cc55cSDimitry Andric                                         DFSF.getRetvalOriginTLS(), "_dfsret_o");
3441fe6060f1SDimitry Andric       DFSF.SkipInsts.insert(LI);
3442fe6060f1SDimitry Andric       DFSF.setOrigin(&CB, LI);
3443fe6060f1SDimitry Andric     }
3444bdd1243dSDimitry Andric 
3445bdd1243dSDimitry Andric     DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
34460b57cec5SDimitry Andric   }
3447e8d8bef9SDimitry Andric }
34480b57cec5SDimitry Andric 
34490b57cec5SDimitry Andric void DFSanVisitor::visitPHINode(PHINode &PN) {
3450e8d8bef9SDimitry Andric   Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3451*0fca6ea1SDimitry Andric   PHINode *ShadowPN = PHINode::Create(ShadowTy, PN.getNumIncomingValues(), "",
3452*0fca6ea1SDimitry Andric                                       PN.getIterator());
34530b57cec5SDimitry Andric 
34540b57cec5SDimitry Andric   // Give the shadow phi node valid predecessors to fool SplitEdge into working.
3455e8d8bef9SDimitry Andric   Value *UndefShadow = UndefValue::get(ShadowTy);
3456fe6060f1SDimitry Andric   for (BasicBlock *BB : PN.blocks())
3457fe6060f1SDimitry Andric     ShadowPN->addIncoming(UndefShadow, BB);
3458fe6060f1SDimitry Andric 
3459fe6060f1SDimitry Andric   DFSF.setShadow(&PN, ShadowPN);
3460fe6060f1SDimitry Andric 
3461fe6060f1SDimitry Andric   PHINode *OriginPN = nullptr;
3462fe6060f1SDimitry Andric   if (DFSF.DFS.shouldTrackOrigins()) {
3463*0fca6ea1SDimitry Andric     OriginPN = PHINode::Create(DFSF.DFS.OriginTy, PN.getNumIncomingValues(), "",
3464*0fca6ea1SDimitry Andric                                PN.getIterator());
3465fe6060f1SDimitry Andric     Value *UndefOrigin = UndefValue::get(DFSF.DFS.OriginTy);
3466fe6060f1SDimitry Andric     for (BasicBlock *BB : PN.blocks())
3467fe6060f1SDimitry Andric       OriginPN->addIncoming(UndefOrigin, BB);
3468fe6060f1SDimitry Andric     DFSF.setOrigin(&PN, OriginPN);
34690b57cec5SDimitry Andric   }
34700b57cec5SDimitry Andric 
3471fe6060f1SDimitry Andric   DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
34720b57cec5SDimitry Andric }
3473e8d8bef9SDimitry Andric 
3474e8d8bef9SDimitry Andric PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
3475e8d8bef9SDimitry Andric                                              ModuleAnalysisManager &AM) {
3476bdd1243dSDimitry Andric   auto GetTLI = [&](Function &F) -> TargetLibraryInfo & {
3477bdd1243dSDimitry Andric     auto &FAM =
3478bdd1243dSDimitry Andric         AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
3479bdd1243dSDimitry Andric     return FAM.getResult<TargetLibraryAnalysis>(F);
3480bdd1243dSDimitry Andric   };
3481bdd1243dSDimitry Andric   if (!DataFlowSanitizer(ABIListFiles).runImpl(M, GetTLI))
3482e8d8bef9SDimitry Andric     return PreservedAnalyses::all();
3483bdd1243dSDimitry Andric 
3484bdd1243dSDimitry Andric   PreservedAnalyses PA = PreservedAnalyses::none();
3485bdd1243dSDimitry Andric   // GlobalsAA is considered stateless and does not get invalidated unless
3486bdd1243dSDimitry Andric   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
3487bdd1243dSDimitry Andric   // make changes that require GlobalsAA to be invalidated.
3488bdd1243dSDimitry Andric   PA.abandon<GlobalsAA>();
3489bdd1243dSDimitry Andric   return PA;
3490e8d8bef9SDimitry Andric }
3491