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
getGlobalTypeString(const GlobalValue & G)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
set(std::unique_ptr<SpecialCaseList> List)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.
isIn(const Function & F,StringRef Category) const3280b57cec5SDimitry 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.
isIn(const GlobalAlias & GA,StringRef Category) const3370b57cec5SDimitry 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.
isIn(const Module & M,StringRef Category) const3500b57cec5SDimitry 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 {
TransformedFunction__anon5712215c0211::TransformedFunction359fe6060f1SDimitry 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
transformFunctionAttributes(const TransformedFunction & TransformedFunction,LLVMContext & Ctx,AttributeList CallSiteAttrs)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
DFSanFunction__anon5712215c0211::DFSanFunction618349cc55cSDimitry 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
DFSanVisitor(DFSanFunction & DFSF)7890b57cec5SDimitry Andric DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
7900b57cec5SDimitry Andric
getDataLayout() const7910b57cec5SDimitry 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
LibAtomicFunction(const Function & F)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
DataFlowSanitizer(const std::vector<std::string> & ABIListFiles)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
getCustomFunctionType(FunctionType * T)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
isZeroShadow(Value * V)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
hasLoadSizeForFastPath(uint64_t Size)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
shouldTrackOrigins()932fe6060f1SDimitry Andric bool DataFlowSanitizer::shouldTrackOrigins() {
933349cc55cSDimitry Andric static const bool ShouldTrackOrigins = ClTrackOrigins;
934fe6060f1SDimitry Andric return ShouldTrackOrigins;
935fe6060f1SDimitry Andric }
936fe6060f1SDimitry Andric
getZeroShadow(Type * OrigTy)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
getZeroShadow(Value * V)944e8d8bef9SDimitry Andric Constant *DataFlowSanitizer::getZeroShadow(Value *V) {
945e8d8bef9SDimitry Andric return getZeroShadow(V->getType());
946e8d8bef9SDimitry Andric }
947e8d8bef9SDimitry Andric
expandFromPrimitiveShadowRecursive(Value * Shadow,SmallVector<unsigned,4> & Indices,Type * SubShadowTy,Value * PrimitiveShadow,IRBuilder<> & IRB)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
shouldInstrumentWithCall()976fe6060f1SDimitry Andric bool DFSanFunction::shouldInstrumentWithCall() {
977fe6060f1SDimitry Andric return ClInstrumentWithCallThreshold >= 0 &&
978fe6060f1SDimitry Andric NumOriginStores >= ClInstrumentWithCallThreshold;
979fe6060f1SDimitry Andric }
980fe6060f1SDimitry Andric
expandFromPrimitiveShadow(Type * T,Value * PrimitiveShadow,BasicBlock::iterator Pos)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>
collapseAggregateShadow(AggregateType * AT,Value * Shadow,IRBuilder<> & IRB)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
collapseToPrimitiveShadow(Value * Shadow,IRBuilder<> & IRB)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
collapseToPrimitiveShadow(Value * Shadow,BasicBlock::iterator Pos)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
addConditionalCallbacksIfEnabled(Instruction & I,Value * Condition)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
addReachesFunctionCallbacksIfEnabled(IRBuilder<> & IRB,Instruction & I,Value * Data)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
getShadowTy(Type * OrigTy)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
getShadowTy(Value * V)1126e8d8bef9SDimitry Andric Type *DataFlowSanitizer::getShadowTy(Value *V) {
1127e8d8bef9SDimitry Andric return getShadowTy(V->getType());
1128e8d8bef9SDimitry Andric }
1129e8d8bef9SDimitry Andric
initializeModule(Module & M)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
isInstrumented(const Function * F)12370b57cec5SDimitry Andric bool DataFlowSanitizer::isInstrumented(const Function *F) {
12380b57cec5SDimitry Andric return !ABIList.isIn(*F, "uninstrumented");
12390b57cec5SDimitry Andric }
12400b57cec5SDimitry Andric
isInstrumented(const GlobalAlias * GA)12410b57cec5SDimitry Andric bool DataFlowSanitizer::isInstrumented(const GlobalAlias *GA) {
12420b57cec5SDimitry Andric return !ABIList.isIn(*GA, "uninstrumented");
12430b57cec5SDimitry Andric }
12440b57cec5SDimitry Andric
isForceZeroLabels(const Function * F)1245349cc55cSDimitry Andric bool DataFlowSanitizer::isForceZeroLabels(const Function *F) {
1246349cc55cSDimitry Andric return ABIList.isIn(*F, "force_zero_labels");
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric
getWrapperKind(Function * F)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
addGlobalNameSuffix(GlobalValue * GV)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
buildExternWeakCheckIfNeeded(IRBuilder<> & IRB,Function * F)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 *
buildWrapperFunction(Function * F,StringRef NewFName,GlobalValue::LinkageTypes NewFLink,FunctionType * NewFT)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
initializeRuntimeFunctions(Module & M)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
initializeCallbackFunctions(Module & M)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
runImpl(Module & M,llvm::function_ref<TargetLibraryInfo & (Function &)> GetTLI)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
getArgTLS(Type * T,unsigned ArgOffset,IRBuilder<> & IRB)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
getRetvalTLS(Type * T,IRBuilder<> & IRB)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
getRetvalOriginTLS()1804fe6060f1SDimitry Andric Value *DFSanFunction::getRetvalOriginTLS() { return DFS.RetvalOriginTLS; }
1805fe6060f1SDimitry Andric
getArgOriginTLS(unsigned ArgNo,IRBuilder<> & IRB)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
getOrigin(Value * V)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
setOrigin(Instruction * I,Value * Origin)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
getShadowForTLSArgument(Argument * A)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
getShadow(Value * V)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
setShadow(Instruction * I,Value * Shadow)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
getShadowOffset(Value * Addr,IRBuilder<> & IRB)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 *>
getShadowOriginAddress(Value * Addr,Align InstAlignment,BasicBlock::iterator Pos)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
getShadowAddress(Value * Addr,BasicBlock::iterator Pos,Value * ShadowOffset)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
getShadowAddress(Value * Addr,BasicBlock::iterator Pos)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
combineShadowsThenConvert(Type * T,Value * V1,Value * V2,BasicBlock::iterator Pos)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.
combineShadows(Value * V1,Value * V2,BasicBlock::iterator Pos)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.
combineOperandShadows(Instruction * Inst)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
visitInstOperands(Instruction & I)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
combineOrigins(const std::vector<Value * > & Shadows,const std::vector<Value * > & Origins,BasicBlock::iterator Pos,ConstantInt * Zero)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
combineOperandOrigins(Instruction * Inst)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
visitInstOperandOrigins(Instruction & I)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
getShadowAlign(Align InstAlignment)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
getOriginAlign(Align InstAlignment)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
isLookupTableConstant(Value * P)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
useCallbackLoadLabelAndOrigin(uint64_t Size,Align InstAlignment)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
loadNextOrigin(BasicBlock::iterator Pos,Align OriginAlign,Value ** OriginAddr)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
loadShadowFast(Value * ShadowAddr,Value * OriginAddr,uint64_t Size,Align ShadowAlign,Align OriginAlign,Value * FirstOrigin,BasicBlock::iterator Pos)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
loadShadowOriginSansLoadTracking(Value * Addr,uint64_t Size,Align InstAlignment,BasicBlock::iterator Pos)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 *>
loadShadowOrigin(Value * Addr,uint64_t Size,Align InstAlignment,BasicBlock::iterator Pos)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
addAcquireOrdering(AtomicOrdering AO)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
StripPointerGEPsAndCasts(Value * V)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
visitLoadInst(LoadInst & LI)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
updateOriginIfTainted(Value * Shadow,Value * Origin,IRBuilder<> & IRB)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
updateOrigin(Value * V,IRBuilder<> & IRB)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
originToIntptr(IRBuilder<> & IRB,Value * Origin)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
paintOrigin(IRBuilder<> & IRB,Value * Origin,Value * StoreOriginAddr,uint64_t StoreOriginSize,Align Alignment)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
convertToBool(Value * V,IRBuilder<> & IRB,const Twine & Name)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
storeOrigin(BasicBlock::iterator Pos,Value * Addr,uint64_t Size,Value * Shadow,Value * Origin,Value * StoreOriginAddr,Align InstAlignment)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
storeZeroPrimitiveShadow(Value * Addr,uint64_t Size,Align ShadowAlign,BasicBlock::iterator Pos)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
storePrimitiveShadowOrigin(Value * Addr,uint64_t Size,Align InstAlignment,Value * PrimitiveShadow,Value * Origin,BasicBlock::iterator Pos)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
addReleaseOrdering(AtomicOrdering AO)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
visitStoreInst(StoreInst & SI)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
visitCASOrRMW(Align InstAlignment,Instruction & I)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
visitAtomicRMWInst(AtomicRMWInst & I)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
visitAtomicCmpXchgInst(AtomicCmpXchgInst & I)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
visitUnaryOperator(UnaryOperator & UO)27470b57cec5SDimitry Andric void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2748fe6060f1SDimitry Andric visitInstOperands(UO);
27490b57cec5SDimitry Andric }
27500b57cec5SDimitry Andric
visitBinaryOperator(BinaryOperator & BO)27510b57cec5SDimitry Andric void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2752fe6060f1SDimitry Andric visitInstOperands(BO);
27530b57cec5SDimitry Andric }
27540b57cec5SDimitry Andric
visitBitCastInst(BitCastInst & BCI)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
visitCastInst(CastInst & CI)2765fe6060f1SDimitry Andric void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
27660b57cec5SDimitry Andric
visitCmpInst(CmpInst & CI)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
visitLandingPadInst(LandingPadInst & LPI)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
visitGetElementPtrInst(GetElementPtrInst & GEPI)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
visitExtractElementInst(ExtractElementInst & I)28100b57cec5SDimitry Andric void DFSanVisitor::visitExtractElementInst(ExtractElementInst &I) {
2811fe6060f1SDimitry Andric visitInstOperands(I);
28120b57cec5SDimitry Andric }
28130b57cec5SDimitry Andric
visitInsertElementInst(InsertElementInst & I)28140b57cec5SDimitry Andric void DFSanVisitor::visitInsertElementInst(InsertElementInst &I) {
2815fe6060f1SDimitry Andric visitInstOperands(I);
28160b57cec5SDimitry Andric }
28170b57cec5SDimitry Andric
visitShuffleVectorInst(ShuffleVectorInst & I)28180b57cec5SDimitry Andric void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &I) {
2819fe6060f1SDimitry Andric visitInstOperands(I);
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric
visitExtractValueInst(ExtractValueInst & I)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
visitInsertValueInst(InsertValueInst & I)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
visitAllocaInst(AllocaInst & I)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
visitSelectInst(SelectInst & I)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
visitMemSetInst(MemSetInst & I)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
visitMemTransferInst(MemTransferInst & I)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
visitBranchInst(BranchInst & BR)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
visitSwitchInst(SwitchInst & SW)296704eeddc0SDimitry Andric void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
296804eeddc0SDimitry Andric DFSF.addConditionalCallbacksIfEnabled(SW, SW.getCondition());
296904eeddc0SDimitry Andric }
297004eeddc0SDimitry Andric
isAMustTailRetVal(Value * RetVal)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
visitReturnInst(ReturnInst & RI)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
addShadowArguments(Function & F,CallBase & CB,std::vector<Value * > & Args,IRBuilder<> & IRB)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
addOriginArguments(Function & F,CallBase & CB,std::vector<Value * > & Args,IRBuilder<> & IRB)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
visitWrappedCallBase(Function & F,CallBase & CB)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
makeAddAcquireOrderingTable(IRBuilder<> & IRB)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
visitLibAtomicLoad(CallBase & CB)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
makeAddReleaseOrderingTable(IRBuilder<> & IRB)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
visitLibAtomicStore(CallBase & CB)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
visitLibAtomicExchange(CallBase & CB)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
visitLibAtomicCompareExchange(CallBase & CB)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
visitCallBase(CallBase & CB)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
visitPHINode(PHINode & PN)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
run(Module & M,ModuleAnalysisManager & AM)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