LLVM  16.0.0git
X86LoadValueInjectionLoadHardening.cpp
Go to the documentation of this file.
1 //==-- X86LoadValueInjectionLoadHardening.cpp - LVI load hardening for x86 --=//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// Description: This pass finds Load Value Injection (LVI) gadgets consisting
10 /// of a load from memory (i.e., SOURCE), and any operation that may transmit
11 /// the value loaded from memory over a covert channel, or use the value loaded
12 /// from memory to determine a branch/call target (i.e., SINK). After finding
13 /// all such gadgets in a given function, the pass minimally inserts LFENCE
14 /// instructions in such a manner that the following property is satisfied: for
15 /// all SOURCE+SINK pairs, all paths in the CFG from SOURCE to SINK contain at
16 /// least one LFENCE instruction. The algorithm that implements this minimal
17 /// insertion is influenced by an academic paper that minimally inserts memory
18 /// fences for high-performance concurrent programs:
19 /// http://www.cs.ucr.edu/~lesani/companion/oopsla15/OOPSLA15.pdf
20 /// The algorithm implemented in this pass is as follows:
21 /// 1. Build a condensed CFG (i.e., a GadgetGraph) consisting only of the
22 /// following components:
23 /// - SOURCE instructions (also includes function arguments)
24 /// - SINK instructions
25 /// - Basic block entry points
26 /// - Basic block terminators
27 /// - LFENCE instructions
28 /// 2. Analyze the GadgetGraph to determine which SOURCE+SINK pairs (i.e.,
29 /// gadgets) are already mitigated by existing LFENCEs. If all gadgets have been
30 /// mitigated, go to step 6.
31 /// 3. Use a heuristic or plugin to approximate minimal LFENCE insertion.
32 /// 4. Insert one LFENCE along each CFG edge that was cut in step 3.
33 /// 5. Go to step 2.
34 /// 6. If any LFENCEs were inserted, return `true` from runOnMachineFunction()
35 /// to tell LLVM that the function was modified.
36 ///
37 //===----------------------------------------------------------------------===//
38 
39 #include "ImmutableGraph.h"
40 #include "X86.h"
41 #include "X86Subtarget.h"
42 #include "X86TargetMachine.h"
43 #include "llvm/ADT/DenseMap.h"
44 #include "llvm/ADT/DenseSet.h"
45 #include "llvm/ADT/STLExtras.h"
46 #include "llvm/ADT/SmallSet.h"
47 #include "llvm/ADT/Statistic.h"
48 #include "llvm/ADT/StringRef.h"
58 #include "llvm/CodeGen/RDFGraph.h"
60 #include "llvm/InitializePasses.h"
63 #include "llvm/Support/Debug.h"
67 
68 using namespace llvm;
69 
70 #define PASS_KEY "x86-lvi-load"
71 #define DEBUG_TYPE PASS_KEY
72 
73 STATISTIC(NumFences, "Number of LFENCEs inserted for LVI mitigation");
74 STATISTIC(NumFunctionsConsidered, "Number of functions analyzed");
75 STATISTIC(NumFunctionsMitigated, "Number of functions for which mitigations "
76  "were deployed");
77 STATISTIC(NumGadgets, "Number of LVI gadgets detected during analysis");
78 
80  PASS_KEY "-opt-plugin",
81  cl::desc("Specify a plugin to optimize LFENCE insertion"), cl::Hidden);
82 
84  PASS_KEY "-no-cbranch",
85  cl::desc("Don't treat conditional branches as disclosure gadgets. This "
86  "may improve performance, at the cost of security."),
87  cl::init(false), cl::Hidden);
88 
89 static cl::opt<bool> EmitDot(
90  PASS_KEY "-dot",
91  cl::desc(
92  "For each function, emit a dot graph depicting potential LVI gadgets"),
93  cl::init(false), cl::Hidden);
94 
96  PASS_KEY "-dot-only",
97  cl::desc("For each function, emit a dot graph depicting potential LVI "
98  "gadgets, and do not insert any fences"),
99  cl::init(false), cl::Hidden);
100 
102  PASS_KEY "-dot-verify",
103  cl::desc("For each function, emit a dot graph to stdout depicting "
104  "potential LVI gadgets, used for testing purposes only"),
105  cl::init(false), cl::Hidden);
106 
108 typedef int (*OptimizeCutT)(unsigned int *Nodes, unsigned int NodesSize,
109  unsigned int *Edges, int *EdgeValues,
110  int *CutEdges /* out */, unsigned int EdgesSize);
111 static OptimizeCutT OptimizeCut = nullptr;
112 
113 namespace {
114 
115 struct MachineGadgetGraph : ImmutableGraph<MachineInstr *, int> {
116  static constexpr int GadgetEdgeSentinel = -1;
117  static constexpr MachineInstr *const ArgNodeSentinel = nullptr;
118 
120  using Node = typename GraphT::Node;
121  using Edge = typename GraphT::Edge;
122  using size_type = typename GraphT::size_type;
123  MachineGadgetGraph(std::unique_ptr<Node[]> Nodes,
124  std::unique_ptr<Edge[]> Edges, size_type NodesSize,
125  size_type EdgesSize, int NumFences = 0, int NumGadgets = 0)
126  : GraphT(std::move(Nodes), std::move(Edges), NodesSize, EdgesSize),
127  NumFences(NumFences), NumGadgets(NumGadgets) {}
128  static inline bool isCFGEdge(const Edge &E) {
129  return E.getValue() != GadgetEdgeSentinel;
130  }
131  static inline bool isGadgetEdge(const Edge &E) {
132  return E.getValue() == GadgetEdgeSentinel;
133  }
134  int NumFences;
135  int NumGadgets;
136 };
137 
138 class X86LoadValueInjectionLoadHardeningPass : public MachineFunctionPass {
139 public:
140  X86LoadValueInjectionLoadHardeningPass() : MachineFunctionPass(ID) {}
141 
142  StringRef getPassName() const override {
143  return "X86 Load Value Injection (LVI) Load Hardening";
144  }
145  void getAnalysisUsage(AnalysisUsage &AU) const override;
146  bool runOnMachineFunction(MachineFunction &MF) override;
147 
148  static char ID;
149 
150 private:
151  using GraphBuilder = ImmutableGraphBuilder<MachineGadgetGraph>;
152  using Edge = MachineGadgetGraph::Edge;
153  using Node = MachineGadgetGraph::Node;
154  using EdgeSet = MachineGadgetGraph::EdgeSet;
156 
157  const X86Subtarget *STI;
158  const TargetInstrInfo *TII;
159  const TargetRegisterInfo *TRI;
160 
161  std::unique_ptr<MachineGadgetGraph>
162  getGadgetGraph(MachineFunction &MF, const MachineLoopInfo &MLI,
163  const MachineDominatorTree &MDT,
164  const MachineDominanceFrontier &MDF) const;
165  int hardenLoadsWithPlugin(MachineFunction &MF,
166  std::unique_ptr<MachineGadgetGraph> Graph) const;
167  int hardenLoadsWithHeuristic(MachineFunction &MF,
168  std::unique_ptr<MachineGadgetGraph> Graph) const;
169  int elimMitigatedEdgesAndNodes(MachineGadgetGraph &G,
170  EdgeSet &ElimEdges /* in, out */,
171  NodeSet &ElimNodes /* in, out */) const;
172  std::unique_ptr<MachineGadgetGraph>
173  trimMitigatedEdges(std::unique_ptr<MachineGadgetGraph> Graph) const;
174  int insertFences(MachineFunction &MF, MachineGadgetGraph &G,
175  EdgeSet &CutEdges /* in, out */) const;
176  bool instrUsesRegToAccessMemory(const MachineInstr &I, unsigned Reg) const;
177  bool instrUsesRegToBranch(const MachineInstr &I, unsigned Reg) const;
178  inline bool isFence(const MachineInstr *MI) const {
179  return MI && (MI->getOpcode() == X86::LFENCE ||
180  (STI->useLVIControlFlowIntegrity() && MI->isCall()));
181  }
182 };
183 
184 } // end anonymous namespace
185 
186 namespace llvm {
187 
188 template <>
189 struct GraphTraits<MachineGadgetGraph *>
191 
192 template <>
193 struct DOTGraphTraits<MachineGadgetGraph *> : DefaultDOTGraphTraits {
194  using GraphType = MachineGadgetGraph;
196  using NodeRef = typename Traits::NodeRef;
197  using EdgeRef = typename Traits::EdgeRef;
198  using ChildIteratorType = typename Traits::ChildIteratorType;
199  using ChildEdgeIteratorType = typename Traits::ChildEdgeIteratorType;
200 
201  DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {}
202 
203  std::string getNodeLabel(NodeRef Node, GraphType *) {
204  if (Node->getValue() == MachineGadgetGraph::ArgNodeSentinel)
205  return "ARGS";
206 
207  std::string Str;
208  raw_string_ostream OS(Str);
209  OS << *Node->getValue();
210  return OS.str();
211  }
212 
213  static std::string getNodeAttributes(NodeRef Node, GraphType *) {
214  MachineInstr *MI = Node->getValue();
215  if (MI == MachineGadgetGraph::ArgNodeSentinel)
216  return "color = blue";
217  if (MI->getOpcode() == X86::LFENCE)
218  return "color = green";
219  return "";
220  }
221 
223  GraphType *) {
224  int EdgeVal = (*E.getCurrent()).getValue();
225  return EdgeVal >= 0 ? "label = " + std::to_string(EdgeVal)
226  : "color = red, style = \"dashed\"";
227  }
228 };
229 
230 } // end namespace llvm
231 
232 constexpr MachineInstr *MachineGadgetGraph::ArgNodeSentinel;
233 constexpr int MachineGadgetGraph::GadgetEdgeSentinel;
234 
236 
237 void X86LoadValueInjectionLoadHardeningPass::getAnalysisUsage(
238  AnalysisUsage &AU) const {
243  AU.setPreservesCFG();
244 }
245 
247  MachineGadgetGraph *G) {
248  WriteGraph(OS, G, /*ShortNames*/ false,
249  "Speculative gadgets for \"" + MF.getName() + "\" function");
250 }
251 
252 bool X86LoadValueInjectionLoadHardeningPass::runOnMachineFunction(
253  MachineFunction &MF) {
254  LLVM_DEBUG(dbgs() << "***** " << getPassName() << " : " << MF.getName()
255  << " *****\n");
256  STI = &MF.getSubtarget<X86Subtarget>();
257  if (!STI->useLVILoadHardening())
258  return false;
259 
260  // FIXME: support 32-bit
261  if (!STI->is64Bit())
262  report_fatal_error("LVI load hardening is only supported on 64-bit", false);
263 
264  // Don't skip functions with the "optnone" attr but participate in opt-bisect.
265  const Function &F = MF.getFunction();
266  if (!F.hasOptNone() && skipFunction(F))
267  return false;
268 
269  ++NumFunctionsConsidered;
270  TII = STI->getInstrInfo();
271  TRI = STI->getRegisterInfo();
272  LLVM_DEBUG(dbgs() << "Building gadget graph...\n");
273  const auto &MLI = getAnalysis<MachineLoopInfo>();
274  const auto &MDT = getAnalysis<MachineDominatorTree>();
275  const auto &MDF = getAnalysis<MachineDominanceFrontier>();
276  std::unique_ptr<MachineGadgetGraph> Graph = getGadgetGraph(MF, MLI, MDT, MDF);
277  LLVM_DEBUG(dbgs() << "Building gadget graph... Done\n");
278  if (Graph == nullptr)
279  return false; // didn't find any gadgets
280 
281  if (EmitDotVerify) {
282  writeGadgetGraph(outs(), MF, Graph.get());
283  return false;
284  }
285 
286  if (EmitDot || EmitDotOnly) {
287  LLVM_DEBUG(dbgs() << "Emitting gadget graph...\n");
288  std::error_code FileError;
289  std::string FileName = "lvi.";
290  FileName += MF.getName();
291  FileName += ".dot";
292  raw_fd_ostream FileOut(FileName, FileError);
293  if (FileError)
294  errs() << FileError.message();
295  writeGadgetGraph(FileOut, MF, Graph.get());
296  FileOut.close();
297  LLVM_DEBUG(dbgs() << "Emitting gadget graph... Done\n");
298  if (EmitDotOnly)
299  return false;
300  }
301 
302  int FencesInserted;
303  if (!OptimizePluginPath.empty()) {
304  if (!OptimizeDL.isValid()) {
305  std::string ErrorMsg;
307  OptimizePluginPath.c_str(), &ErrorMsg);
308  if (!ErrorMsg.empty())
309  report_fatal_error(Twine("Failed to load opt plugin: \"") + ErrorMsg +
310  "\"");
312  if (!OptimizeCut)
313  report_fatal_error("Invalid optimization plugin");
314  }
315  FencesInserted = hardenLoadsWithPlugin(MF, std::move(Graph));
316  } else { // Use the default greedy heuristic
317  FencesInserted = hardenLoadsWithHeuristic(MF, std::move(Graph));
318  }
319 
320  if (FencesInserted > 0)
321  ++NumFunctionsMitigated;
322  NumFences += FencesInserted;
323  return (FencesInserted > 0);
324 }
325 
326 std::unique_ptr<MachineGadgetGraph>
327 X86LoadValueInjectionLoadHardeningPass::getGadgetGraph(
328  MachineFunction &MF, const MachineLoopInfo &MLI,
329  const MachineDominatorTree &MDT,
330  const MachineDominanceFrontier &MDF) const {
331  using namespace rdf;
332 
333  // Build the Register Dataflow Graph using the RDF framework
334  DataFlowGraph DFG{MF, *TII, *TRI, MDT, MDF};
335  DFG.build();
336  Liveness L{MF.getRegInfo(), DFG};
337  L.computePhiInfo();
338 
339  GraphBuilder Builder;
340  using GraphIter = typename GraphBuilder::BuilderNodeRef;
342  int FenceCount = 0, GadgetCount = 0;
343  auto MaybeAddNode = [&NodeMap, &Builder](MachineInstr *MI) {
344  auto Ref = NodeMap.find(MI);
345  if (Ref == NodeMap.end()) {
346  auto I = Builder.addVertex(MI);
347  NodeMap[MI] = I;
348  return std::pair<GraphIter, bool>{I, true};
349  }
350  return std::pair<GraphIter, bool>{Ref->getSecond(), false};
351  };
352 
353  // The `Transmitters` map memoizes transmitters found for each def. If a def
354  // has not yet been analyzed, then it will not appear in the map. If a def
355  // has been analyzed and was determined not to have any transmitters, then
356  // its list of transmitters will be empty.
358 
359  // Analyze all machine instructions to find gadgets and LFENCEs, adding
360  // each interesting value to `Nodes`
361  auto AnalyzeDef = [&](NodeAddr<DefNode *> SourceDef) {
362  SmallSet<NodeId, 8> UsesVisited, DefsVisited;
363  std::function<void(NodeAddr<DefNode *>)> AnalyzeDefUseChain =
364  [&](NodeAddr<DefNode *> Def) {
365  if (Transmitters.find(Def.Id) != Transmitters.end())
366  return; // Already analyzed `Def`
367 
368  // Use RDF to find all the uses of `Def`
370  RegisterRef DefReg = Def.Addr->getRegRef(DFG);
371  for (auto UseID : L.getAllReachedUses(DefReg, Def)) {
372  auto Use = DFG.addr<UseNode *>(UseID);
373  if (Use.Addr->getFlags() & NodeAttrs::PhiRef) { // phi node
374  NodeAddr<PhiNode *> Phi = Use.Addr->getOwner(DFG);
375  for (const auto& I : L.getRealUses(Phi.Id)) {
376  if (DFG.getPRI().alias(RegisterRef(I.first), DefReg)) {
377  for (const auto &UA : I.second)
378  Uses.emplace(UA.first);
379  }
380  }
381  } else { // not a phi node
382  Uses.emplace(UseID);
383  }
384  }
385 
386  // For each use of `Def`, we want to know whether:
387  // (1) The use can leak the Def'ed value,
388  // (2) The use can further propagate the Def'ed value to more defs
389  for (auto UseID : Uses) {
390  if (!UsesVisited.insert(UseID).second)
391  continue; // Already visited this use of `Def`
392 
393  auto Use = DFG.addr<UseNode *>(UseID);
394  assert(!(Use.Addr->getFlags() & NodeAttrs::PhiRef));
395  MachineOperand &UseMO = Use.Addr->getOp();
396  MachineInstr &UseMI = *UseMO.getParent();
397  assert(UseMO.isReg());
398 
399  // We naively assume that an instruction propagates any loaded
400  // uses to all defs unless the instruction is a call, in which
401  // case all arguments will be treated as gadget sources during
402  // analysis of the callee function.
403  if (UseMI.isCall())
404  continue;
405 
406  // Check whether this use can transmit (leak) its value.
407  if (instrUsesRegToAccessMemory(UseMI, UseMO.getReg()) ||
409  instrUsesRegToBranch(UseMI, UseMO.getReg()))) {
410  Transmitters[Def.Id].push_back(Use.Addr->getOwner(DFG).Id);
411  if (UseMI.mayLoad())
412  continue; // Found a transmitting load -- no need to continue
413  // traversing its defs (i.e., this load will become
414  // a new gadget source anyways).
415  }
416 
417  // Check whether the use propagates to more defs.
418  NodeAddr<InstrNode *> Owner{Use.Addr->getOwner(DFG)};
419  rdf::NodeList AnalyzedChildDefs;
420  for (const auto &ChildDef :
421  Owner.Addr->members_if(DataFlowGraph::IsDef, DFG)) {
422  if (!DefsVisited.insert(ChildDef.Id).second)
423  continue; // Already visited this def
424  if (Def.Addr->getAttrs() & NodeAttrs::Dead)
425  continue;
426  if (Def.Id == ChildDef.Id)
427  continue; // `Def` uses itself (e.g., increment loop counter)
428 
429  AnalyzeDefUseChain(ChildDef);
430 
431  // `Def` inherits all of its child defs' transmitters.
432  for (auto TransmitterId : Transmitters[ChildDef.Id])
433  Transmitters[Def.Id].push_back(TransmitterId);
434  }
435  }
436 
437  // Note that this statement adds `Def.Id` to the map if no
438  // transmitters were found for `Def`.
439  auto &DefTransmitters = Transmitters[Def.Id];
440 
441  // Remove duplicate transmitters
442  llvm::sort(DefTransmitters);
443  DefTransmitters.erase(
444  std::unique(DefTransmitters.begin(), DefTransmitters.end()),
445  DefTransmitters.end());
446  };
447 
448  // Find all of the transmitters
449  AnalyzeDefUseChain(SourceDef);
450  auto &SourceDefTransmitters = Transmitters[SourceDef.Id];
451  if (SourceDefTransmitters.empty())
452  return; // No transmitters for `SourceDef`
453 
454  MachineInstr *Source = SourceDef.Addr->getFlags() & NodeAttrs::PhiRef
455  ? MachineGadgetGraph::ArgNodeSentinel
456  : SourceDef.Addr->getOp().getParent();
457  auto GadgetSource = MaybeAddNode(Source);
458  // Each transmitter is a sink for `SourceDef`.
459  for (auto TransmitterId : SourceDefTransmitters) {
460  MachineInstr *Sink = DFG.addr<StmtNode *>(TransmitterId).Addr->getCode();
461  auto GadgetSink = MaybeAddNode(Sink);
462  // Add the gadget edge to the graph.
463  Builder.addEdge(MachineGadgetGraph::GadgetEdgeSentinel,
464  GadgetSource.first, GadgetSink.first);
465  ++GadgetCount;
466  }
467  };
468 
469  LLVM_DEBUG(dbgs() << "Analyzing def-use chains to find gadgets\n");
470  // Analyze function arguments
471  NodeAddr<BlockNode *> EntryBlock = DFG.getFunc().Addr->getEntryBlock(DFG);
472  for (NodeAddr<PhiNode *> ArgPhi :
473  EntryBlock.Addr->members_if(DataFlowGraph::IsPhi, DFG)) {
474  NodeList Defs = ArgPhi.Addr->members_if(DataFlowGraph::IsDef, DFG);
475  llvm::for_each(Defs, AnalyzeDef);
476  }
477  // Analyze every instruction in MF
478  for (NodeAddr<BlockNode *> BA : DFG.getFunc().Addr->members(DFG)) {
479  for (NodeAddr<StmtNode *> SA :
480  BA.Addr->members_if(DataFlowGraph::IsCode<NodeAttrs::Stmt>, DFG)) {
481  MachineInstr *MI = SA.Addr->getCode();
482  if (isFence(MI)) {
483  MaybeAddNode(MI);
484  ++FenceCount;
485  } else if (MI->mayLoad()) {
486  NodeList Defs = SA.Addr->members_if(DataFlowGraph::IsDef, DFG);
487  llvm::for_each(Defs, AnalyzeDef);
488  }
489  }
490  }
491  LLVM_DEBUG(dbgs() << "Found " << FenceCount << " fences\n");
492  LLVM_DEBUG(dbgs() << "Found " << GadgetCount << " gadgets\n");
493  if (GadgetCount == 0)
494  return nullptr;
495  NumGadgets += GadgetCount;
496 
497  // Traverse CFG to build the rest of the graph
498  SmallSet<MachineBasicBlock *, 8> BlocksVisited;
499  std::function<void(MachineBasicBlock *, GraphIter, unsigned)> TraverseCFG =
500  [&](MachineBasicBlock *MBB, GraphIter GI, unsigned ParentDepth) {
501  unsigned LoopDepth = MLI.getLoopDepth(MBB);
502  if (!MBB->empty()) {
503  // Always add the first instruction in each block
504  auto NI = MBB->begin();
505  auto BeginBB = MaybeAddNode(&*NI);
506  Builder.addEdge(ParentDepth, GI, BeginBB.first);
507  if (!BlocksVisited.insert(MBB).second)
508  return;
509 
510  // Add any instructions within the block that are gadget components
511  GI = BeginBB.first;
512  while (++NI != MBB->end()) {
513  auto Ref = NodeMap.find(&*NI);
514  if (Ref != NodeMap.end()) {
515  Builder.addEdge(LoopDepth, GI, Ref->getSecond());
516  GI = Ref->getSecond();
517  }
518  }
519 
520  // Always add the terminator instruction, if one exists
521  auto T = MBB->getFirstTerminator();
522  if (T != MBB->end()) {
523  auto EndBB = MaybeAddNode(&*T);
524  if (EndBB.second)
525  Builder.addEdge(LoopDepth, GI, EndBB.first);
526  GI = EndBB.first;
527  }
528  }
529  for (MachineBasicBlock *Succ : MBB->successors())
530  TraverseCFG(Succ, GI, LoopDepth);
531  };
532  // ArgNodeSentinel is a pseudo-instruction that represents MF args in the
533  // GadgetGraph
534  GraphIter ArgNode = MaybeAddNode(MachineGadgetGraph::ArgNodeSentinel).first;
535  TraverseCFG(&MF.front(), ArgNode, 0);
536  std::unique_ptr<MachineGadgetGraph> G{Builder.get(FenceCount, GadgetCount)};
537  LLVM_DEBUG(dbgs() << "Found " << G->nodes_size() << " nodes\n");
538  return G;
539 }
540 
541 // Returns the number of remaining gadget edges that could not be eliminated
542 int X86LoadValueInjectionLoadHardeningPass::elimMitigatedEdgesAndNodes(
543  MachineGadgetGraph &G, EdgeSet &ElimEdges /* in, out */,
544  NodeSet &ElimNodes /* in, out */) const {
545  if (G.NumFences > 0) {
546  // Eliminate fences and CFG edges that ingress and egress the fence, as
547  // they are trivially mitigated.
548  for (const Edge &E : G.edges()) {
549  const Node *Dest = E.getDest();
550  if (isFence(Dest->getValue())) {
551  ElimNodes.insert(*Dest);
552  ElimEdges.insert(E);
553  for (const Edge &DE : Dest->edges())
554  ElimEdges.insert(DE);
555  }
556  }
557  }
558 
559  // Find and eliminate gadget edges that have been mitigated.
560  int RemainingGadgets = 0;
561  NodeSet ReachableNodes{G};
562  for (const Node &RootN : G.nodes()) {
563  if (llvm::none_of(RootN.edges(), MachineGadgetGraph::isGadgetEdge))
564  continue; // skip this node if it isn't a gadget source
565 
566  // Find all of the nodes that are CFG-reachable from RootN using DFS
567  ReachableNodes.clear();
568  std::function<void(const Node *, bool)> FindReachableNodes =
569  [&](const Node *N, bool FirstNode) {
570  if (!FirstNode)
571  ReachableNodes.insert(*N);
572  for (const Edge &E : N->edges()) {
573  const Node *Dest = E.getDest();
574  if (MachineGadgetGraph::isCFGEdge(E) && !ElimEdges.contains(E) &&
575  !ReachableNodes.contains(*Dest))
576  FindReachableNodes(Dest, false);
577  }
578  };
579  FindReachableNodes(&RootN, true);
580 
581  // Any gadget whose sink is unreachable has been mitigated
582  for (const Edge &E : RootN.edges()) {
583  if (MachineGadgetGraph::isGadgetEdge(E)) {
584  if (ReachableNodes.contains(*E.getDest())) {
585  // This gadget's sink is reachable
586  ++RemainingGadgets;
587  } else { // This gadget's sink is unreachable, and therefore mitigated
588  ElimEdges.insert(E);
589  }
590  }
591  }
592  }
593  return RemainingGadgets;
594 }
595 
596 std::unique_ptr<MachineGadgetGraph>
597 X86LoadValueInjectionLoadHardeningPass::trimMitigatedEdges(
598  std::unique_ptr<MachineGadgetGraph> Graph) const {
599  NodeSet ElimNodes{*Graph};
600  EdgeSet ElimEdges{*Graph};
601  int RemainingGadgets =
602  elimMitigatedEdgesAndNodes(*Graph, ElimEdges, ElimNodes);
603  if (ElimEdges.empty() && ElimNodes.empty()) {
604  Graph->NumFences = 0;
605  Graph->NumGadgets = RemainingGadgets;
606  } else {
607  Graph = GraphBuilder::trim(*Graph, ElimNodes, ElimEdges, 0 /* NumFences */,
608  RemainingGadgets);
609  }
610  return Graph;
611 }
612 
613 int X86LoadValueInjectionLoadHardeningPass::hardenLoadsWithPlugin(
614  MachineFunction &MF, std::unique_ptr<MachineGadgetGraph> Graph) const {
615  int FencesInserted = 0;
616 
617  do {
618  LLVM_DEBUG(dbgs() << "Eliminating mitigated paths...\n");
619  Graph = trimMitigatedEdges(std::move(Graph));
620  LLVM_DEBUG(dbgs() << "Eliminating mitigated paths... Done\n");
621  if (Graph->NumGadgets == 0)
622  break;
623 
624  LLVM_DEBUG(dbgs() << "Cutting edges...\n");
625  EdgeSet CutEdges{*Graph};
626  auto Nodes = std::make_unique<unsigned int[]>(Graph->nodes_size() +
627  1 /* terminator node */);
628  auto Edges = std::make_unique<unsigned int[]>(Graph->edges_size());
629  auto EdgeCuts = std::make_unique<int[]>(Graph->edges_size());
630  auto EdgeValues = std::make_unique<int[]>(Graph->edges_size());
631  for (const Node &N : Graph->nodes()) {
632  Nodes[Graph->getNodeIndex(N)] = Graph->getEdgeIndex(*N.edges_begin());
633  }
634  Nodes[Graph->nodes_size()] = Graph->edges_size(); // terminator node
635  for (const Edge &E : Graph->edges()) {
636  Edges[Graph->getEdgeIndex(E)] = Graph->getNodeIndex(*E.getDest());
637  EdgeValues[Graph->getEdgeIndex(E)] = E.getValue();
638  }
639  OptimizeCut(Nodes.get(), Graph->nodes_size(), Edges.get(), EdgeValues.get(),
640  EdgeCuts.get(), Graph->edges_size());
641  for (int I = 0; I < Graph->edges_size(); ++I)
642  if (EdgeCuts[I])
643  CutEdges.set(I);
644  LLVM_DEBUG(dbgs() << "Cutting edges... Done\n");
645  LLVM_DEBUG(dbgs() << "Cut " << CutEdges.count() << " edges\n");
646 
647  LLVM_DEBUG(dbgs() << "Inserting LFENCEs...\n");
648  FencesInserted += insertFences(MF, *Graph, CutEdges);
649  LLVM_DEBUG(dbgs() << "Inserting LFENCEs... Done\n");
650  LLVM_DEBUG(dbgs() << "Inserted " << FencesInserted << " fences\n");
651 
652  Graph = GraphBuilder::trim(*Graph, NodeSet{*Graph}, CutEdges);
653  } while (true);
654 
655  return FencesInserted;
656 }
657 
658 int X86LoadValueInjectionLoadHardeningPass::hardenLoadsWithHeuristic(
659  MachineFunction &MF, std::unique_ptr<MachineGadgetGraph> Graph) const {
660  // If `MF` does not have any fences, then no gadgets would have been
661  // mitigated at this point.
662  if (Graph->NumFences > 0) {
663  LLVM_DEBUG(dbgs() << "Eliminating mitigated paths...\n");
664  Graph = trimMitigatedEdges(std::move(Graph));
665  LLVM_DEBUG(dbgs() << "Eliminating mitigated paths... Done\n");
666  }
667 
668  if (Graph->NumGadgets == 0)
669  return 0;
670 
671  LLVM_DEBUG(dbgs() << "Cutting edges...\n");
672  EdgeSet CutEdges{*Graph};
673 
674  // Begin by collecting all ingress CFG edges for each node
676  for (const Edge &E : Graph->edges())
677  if (MachineGadgetGraph::isCFGEdge(E))
678  IngressEdgeMap[E.getDest()].push_back(&E);
679 
680  // For each gadget edge, make cuts that guarantee the gadget will be
681  // mitigated. A computationally efficient way to achieve this is to either:
682  // (a) cut all egress CFG edges from the gadget source, or
683  // (b) cut all ingress CFG edges to the gadget sink.
684  //
685  // Moreover, the algorithm tries not to make a cut into a loop by preferring
686  // to make a (b)-type cut if the gadget source resides at a greater loop depth
687  // than the gadget sink, or an (a)-type cut otherwise.
688  for (const Node &N : Graph->nodes()) {
689  for (const Edge &E : N.edges()) {
690  if (!MachineGadgetGraph::isGadgetEdge(E))
691  continue;
692 
693  SmallVector<const Edge *, 2> EgressEdges;
694  SmallVector<const Edge *, 2> &IngressEdges = IngressEdgeMap[E.getDest()];
695  for (const Edge &EgressEdge : N.edges())
696  if (MachineGadgetGraph::isCFGEdge(EgressEdge))
697  EgressEdges.push_back(&EgressEdge);
698 
699  int EgressCutCost = 0, IngressCutCost = 0;
700  for (const Edge *EgressEdge : EgressEdges)
701  if (!CutEdges.contains(*EgressEdge))
702  EgressCutCost += EgressEdge->getValue();
703  for (const Edge *IngressEdge : IngressEdges)
704  if (!CutEdges.contains(*IngressEdge))
705  IngressCutCost += IngressEdge->getValue();
706 
707  auto &EdgesToCut =
708  IngressCutCost < EgressCutCost ? IngressEdges : EgressEdges;
709  for (const Edge *E : EdgesToCut)
710  CutEdges.insert(*E);
711  }
712  }
713  LLVM_DEBUG(dbgs() << "Cutting edges... Done\n");
714  LLVM_DEBUG(dbgs() << "Cut " << CutEdges.count() << " edges\n");
715 
716  LLVM_DEBUG(dbgs() << "Inserting LFENCEs...\n");
717  int FencesInserted = insertFences(MF, *Graph, CutEdges);
718  LLVM_DEBUG(dbgs() << "Inserting LFENCEs... Done\n");
719  LLVM_DEBUG(dbgs() << "Inserted " << FencesInserted << " fences\n");
720 
721  return FencesInserted;
722 }
723 
724 int X86LoadValueInjectionLoadHardeningPass::insertFences(
725  MachineFunction &MF, MachineGadgetGraph &G,
726  EdgeSet &CutEdges /* in, out */) const {
727  int FencesInserted = 0;
728  for (const Node &N : G.nodes()) {
729  for (const Edge &E : N.edges()) {
730  if (CutEdges.contains(E)) {
731  MachineInstr *MI = N.getValue(), *Prev;
732  MachineBasicBlock *MBB; // Insert an LFENCE in this MBB
733  MachineBasicBlock::iterator InsertionPt; // ...at this point
734  if (MI == MachineGadgetGraph::ArgNodeSentinel) {
735  // insert LFENCE at beginning of entry block
736  MBB = &MF.front();
737  InsertionPt = MBB->begin();
738  Prev = nullptr;
739  } else if (MI->isBranch()) { // insert the LFENCE before the branch
740  MBB = MI->getParent();
741  InsertionPt = MI;
742  Prev = MI->getPrevNode();
743  // Remove all egress CFG edges from this branch because the inserted
744  // LFENCE prevents gadgets from crossing the branch.
745  for (const Edge &E : N.edges()) {
746  if (MachineGadgetGraph::isCFGEdge(E))
747  CutEdges.insert(E);
748  }
749  } else { // insert the LFENCE after the instruction
750  MBB = MI->getParent();
751  InsertionPt = MI->getNextNode() ? MI->getNextNode() : MBB->end();
752  Prev = InsertionPt == MBB->end()
753  ? (MBB->empty() ? nullptr : &MBB->back())
754  : InsertionPt->getPrevNode();
755  }
756  // Ensure this insertion is not redundant (two LFENCEs in sequence).
757  if ((InsertionPt == MBB->end() || !isFence(&*InsertionPt)) &&
758  (!Prev || !isFence(Prev))) {
759  BuildMI(*MBB, InsertionPt, DebugLoc(), TII->get(X86::LFENCE));
760  ++FencesInserted;
761  }
762  }
763  }
764  }
765  return FencesInserted;
766 }
767 
768 bool X86LoadValueInjectionLoadHardeningPass::instrUsesRegToAccessMemory(
769  const MachineInstr &MI, unsigned Reg) const {
770  if (!MI.mayLoadOrStore() || MI.getOpcode() == X86::MFENCE ||
771  MI.getOpcode() == X86::SFENCE || MI.getOpcode() == X86::LFENCE)
772  return false;
773 
774  // FIXME: This does not handle pseudo loading instruction like TCRETURN*
775  const MCInstrDesc &Desc = MI.getDesc();
776  int MemRefBeginIdx = X86II::getMemoryOperandNo(Desc.TSFlags);
777  if (MemRefBeginIdx < 0) {
778  LLVM_DEBUG(dbgs() << "Warning: unable to obtain memory operand for loading "
779  "instruction:\n";
780  MI.print(dbgs()); dbgs() << '\n';);
781  return false;
782  }
783  MemRefBeginIdx += X86II::getOperandBias(Desc);
784 
785  const MachineOperand &BaseMO =
786  MI.getOperand(MemRefBeginIdx + X86::AddrBaseReg);
787  const MachineOperand &IndexMO =
788  MI.getOperand(MemRefBeginIdx + X86::AddrIndexReg);
789  return (BaseMO.isReg() && BaseMO.getReg() != X86::NoRegister &&
790  TRI->regsOverlap(BaseMO.getReg(), Reg)) ||
791  (IndexMO.isReg() && IndexMO.getReg() != X86::NoRegister &&
792  TRI->regsOverlap(IndexMO.getReg(), Reg));
793 }
794 
795 bool X86LoadValueInjectionLoadHardeningPass::instrUsesRegToBranch(
796  const MachineInstr &MI, unsigned Reg) const {
797  if (!MI.isConditionalBranch())
798  return false;
799  for (const MachineOperand &Use : MI.uses())
800  if (Use.isReg() && Use.getReg() == Reg)
801  return true;
802  return false;
803 }
804 
805 INITIALIZE_PASS_BEGIN(X86LoadValueInjectionLoadHardeningPass, PASS_KEY,
806  "X86 LVI load hardening", false, false)
810 INITIALIZE_PASS_END(X86LoadValueInjectionLoadHardeningPass, PASS_KEY,
812 
814  return new X86LoadValueInjectionLoadHardeningPass();
815 }
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:108
MachineInstr.h
llvm::DOTGraphTraits< MachineGadgetGraph * >::NodeRef
typename Traits::NodeRef NodeRef
Definition: X86LoadValueInjectionLoadHardening.cpp:196
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::X86II::getMemoryOperandNo
int getMemoryOperandNo(uint64_t TSFlags)
The function returns the MCInst operand # for the first field of the memory operand.
Definition: X86BaseInfo.h:1100
llvm::tgtok::Def
@ Def
Definition: TGLexer.h:50
llvm::ImmutableGraph
Definition: ImmutableGraph.h:38
UseMI
MachineInstrBuilder & UseMI
Definition: AArch64ExpandPseudoInsts.cpp:107
llvm::none_of
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1723
llvm::ImmutableGraphBuilder
Definition: ImmutableGraph.h:294
llvm::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:818
X86Subtarget.h
llvm::sys::DynamicLibrary::getAddressOfSymbol
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
Definition: DynamicLibrary.cpp:212
llvm::DOTGraphTraits< MachineGadgetGraph * >::getNodeAttributes
static std::string getNodeAttributes(NodeRef Node, GraphType *)
Definition: X86LoadValueInjectionLoadHardening.cpp:213
llvm::Function
Definition: Function.h:60
StringRef.h
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:628
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
Statistic.h
llvm::DOTGraphTraits< MachineGadgetGraph * >::EdgeRef
typename Traits::EdgeRef EdgeRef
Definition: X86LoadValueInjectionLoadHardening.cpp:197
llvm::X86Subtarget
Definition: X86Subtarget.h:52
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
writeGadgetGraph
static void writeGadgetGraph(raw_ostream &OS, MachineFunction &MF, MachineGadgetGraph *G)
Definition: X86LoadValueInjectionLoadHardening.cpp:246
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
MachineBasicBlock.h
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:140
llvm::DOTGraphTraits< MachineGadgetGraph * >::DOTGraphTraits
DOTGraphTraits(bool IsSimple=false)
Definition: X86LoadValueInjectionLoadHardening.cpp:201
llvm::TargetRegisterInfo
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Definition: TargetRegisterInfo.h:237
DynamicLibrary.h
DenseMap.h
llvm::FileError
This class wraps a filename and another Error.
Definition: Error.h:1262
llvm::SmallSet
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:136
OptimizePluginPath
static cl::opt< std::string > OptimizePluginPath(PASS_KEY "-opt-plugin", cl::desc("Specify a plugin to optimize LFENCE insertion"), cl::Hidden)
T
#define T
Definition: Mips16ISelLowering.cpp:341
ImmutableGraph.h
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
llvm::NodeSet::empty
bool empty() const
Definition: MachinePipeliner.h:369
STLExtras.h
llvm::MachineBasicBlock::back
MachineInstr & back()
Definition: MachineBasicBlock.h:285
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1628
PASS_KEY
#define PASS_KEY
Definition: X86LoadValueInjectionLoadHardening.cpp:70
EmitDot
static cl::opt< bool > EmitDot(PASS_KEY "-dot", cl::desc("For each function, emit a dot graph depicting potential LVI gadgets"), cl::init(false), cl::Hidden)
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:167
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::sys::DynamicLibrary
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
Definition: DynamicLibrary.h:33
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::MachineLoopInfo
Definition: MachineLoopInfo.h:89
MachineRegisterInfo.h
Uses
SmallPtrSet< MachineInstr *, 2 > Uses
Definition: ARMLowOverheadLoops.cpp:590
llvm::X86::AddrBaseReg
@ AddrBaseReg
Definition: X86BaseInfo.h:32
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
CommandLine.h
RDFLiveness.h
llvm::MachineFunction::front
const MachineBasicBlock & front() const
Definition: MachineFunction.h:866
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:667
llvm::MCInstrDesc::TSFlags
uint64_t TSFlags
Definition: MCInstrDesc.h:205
X86.h
llvm::TargetInstrInfo
TargetInstrInfo - Interface to description of machine instruction set.
Definition: TargetInstrInfo.h:98
MachineLoopInfo.h
llvm::ModRefInfo::Ref
@ Ref
The access may reference the value stored in memory.
llvm::outs
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
Definition: raw_ostream.cpp:883
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(X86LoadValueInjectionLoadHardeningPass, PASS_KEY, "X86 LVI load hardening", false, false) INITIALIZE_PASS_END(X86LoadValueInjectionLoadHardeningPass
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::sys::DynamicLibrary::getPermanentLibrary
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path using the library load operatio...
Definition: DynamicLibrary.cpp:165
int
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
Definition: README.txt:536
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
DenseSet.h
false
Definition: StackSlotColoring.cpp:141
llvm::X86ISD::MFENCE
@ MFENCE
Definition: X86ISelLowering.h:671
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:125
llvm::MCInstrDesc
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:197
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:48
NodeList
Definition: MicrosoftDemangle.cpp:37
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::rdf::detail::NodeRef
std::pair< NodeId, LaneBitmask > NodeRef
Definition: RDFLiveness.h:39
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::rdf::DataFlowGraph::IsDef
static bool IsDef(const NodeAddr< NodeBase * > BA)
Definition: RDFGraph.h:796
llvm::DOTGraphTraits< MachineGadgetGraph * >::ChildIteratorType
typename Traits::ChildIteratorType ChildIteratorType
Definition: X86LoadValueInjectionLoadHardening.cpp:198
llvm::NodeSet
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
Definition: MachinePipeliner.h:321
llvm::sys::DynamicLibrary::isValid
bool isValid() const
Returns true if the object refers to a valid library.
Definition: DynamicLibrary.h:49
llvm::MachineOperand::getParent
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Definition: MachineOperand.h:237
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
llvm::ErrorInfoBase::message
virtual std::string message() const
Return the error message as a string.
Definition: Error.h:54
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::Pass::print
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Definition: Pass.cpp:130
llvm::DOTGraphTraits
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
Definition: DOTGraphTraits.h:166
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1657
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:657
llvm::cl::opt
Definition: CommandLine.h:1412
llvm::X86II::getOperandBias
unsigned getOperandBias(const MCInstrDesc &Desc)
Compute whether all of the def operands are repeated in the uses and therefore should be skipped.
Definition: X86BaseInfo.h:1060
llvm::TargetRegisterInfo::regsOverlap
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
Definition: TargetRegisterInfo.h:422
llvm::MachineOperand::isReg
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Definition: MachineOperand.h:320
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
llvm::for_each
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1702
llvm::MachineDominanceFrontier
Definition: MachineDominanceFrontier.h:20
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:79
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
OptimizeDL
static llvm::sys::DynamicLibrary OptimizeDL
Definition: X86LoadValueInjectionLoadHardening.cpp:107
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:714
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:447
MachineFunctionPass.h
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:567
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::rdf::DataFlowGraph::IsPhi
static bool IsPhi(const NodeAddr< NodeBase * > BA)
Definition: RDFGraph.h:806
load
LLVM currently emits rax rax movq rax rax ret It could narrow the loads and stores to emit rax rax movq rax rax ret The trouble is that there is a TokenFactor between the store and the load
Definition: README.txt:1531
llvm::WriteGraph
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
Definition: GraphWriter.h:359
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:359
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:651
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::MachineBasicBlock::getFirstTerminator
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
Definition: MachineBasicBlock.cpp:239
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:99
llvm::MachineBasicBlock::successors
iterator_range< succ_iterator > successors()
Definition: MachineBasicBlock.h:392
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:265
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
RDFGraph.h
llvm::cl::Sink
@ Sink
Definition: CommandLine.h:168
OptimizeCut
static OptimizeCutT OptimizeCut
Definition: X86LoadValueInjectionLoadHardening.cpp:111
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:440
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::createX86LoadValueInjectionLoadHardeningPass
FunctionPass * createX86LoadValueInjectionLoadHardeningPass()
Definition: X86LoadValueInjectionLoadHardening.cpp:813
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
GraphWriter.h
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:623
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::end
iterator end()
Definition: DenseMap.h:84
X86TargetMachine.h
MachineDominanceFrontier.h
DOTGraphTraits.h
llvm::unique
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:1940
EmitDotVerify
static cl::opt< bool > EmitDotVerify(PASS_KEY "-dot-verify", cl::desc("For each function, emit a dot graph to stdout depicting " "potential LVI gadgets, used for testing purposes only"), cl::init(false), cl::Hidden)
llvm::MachineLoopInfo::getLoopDepth
unsigned getLoopDepth(const MachineBasicBlock *BB) const
Return the loop nesting level of the specified block.
Definition: MachineLoopInfo.h:136
llvm::rdf::NodeAttrs::Dead
@ Dead
Definition: RDFGraph.h:291
OptimizeCutT
int(* OptimizeCutT)(unsigned int *Nodes, unsigned int NodesSize, unsigned int *Edges, int *EdgeValues, int *CutEdges, unsigned int EdgesSize)
Definition: X86LoadValueInjectionLoadHardening.cpp:108
llvm::SmallSet::insert
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:178
llvm::rdf::NodeAttrs::PhiRef
@ PhiRef
Definition: RDFGraph.h:287
llvm::DOTGraphTraits< MachineGadgetGraph * >::getEdgeAttributes
static std::string getEdgeAttributes(NodeRef, ChildIteratorType E, GraphType *)
Definition: X86LoadValueInjectionLoadHardening.cpp:222
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:357
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:305
llvm::rdf::NodeSet
std::set< NodeId > NodeSet
Definition: RDFGraph.h:514
MachineInstrBuilder.h
llvm::DOTGraphTraits< MachineGadgetGraph * >::getNodeLabel
std::string getNodeLabel(NodeRef Node, GraphType *)
Definition: X86LoadValueInjectionLoadHardening.cpp:203
llvm::X86::AddrIndexReg
@ AddrIndexReg
Definition: X86BaseInfo.h:34
N
#define N
llvm::to_string
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:85
llvm::MachineBasicBlock::empty
bool empty() const
Definition: MachineBasicBlock.h:277
hardening
X86 LVI load hardening
Definition: X86LoadValueInjectionLoadHardening.cpp:811
llvm::DefaultDOTGraphTraits
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
Definition: DOTGraphTraits.h:28
llvm::NodeSet::insert
bool insert(SUnit *SU)
Definition: MachinePipeliner.h:355
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::GraphTraits
Definition: GraphTraits.h:37
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::cl::desc
Definition: CommandLine.h:413
NoConditionalBranches
static cl::opt< bool > NoConditionalBranches(PASS_KEY "-no-cbranch", cl::desc("Don't treat conditional branches as disclosure gadgets. This " "may improve performance, at the cost of security."), cl::init(false), cl::Hidden)
raw_ostream.h
llvm::MachineDominatorTree
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Definition: MachineDominators.h:51
MachineFunction.h
llvm::DOTGraphTraits< MachineGadgetGraph * >::ChildEdgeIteratorType
typename Traits::ChildEdgeIteratorType ChildEdgeIteratorType
Definition: X86LoadValueInjectionLoadHardening.cpp:199
llvm::DOTGraphTraits< MachineGadgetGraph * >::GraphType
MachineGadgetGraph GraphType
Definition: X86LoadValueInjectionLoadHardening.cpp:194
X86
Unrolling by would eliminate the &in both leading to a net reduction in code size The resultant code would then also be suitable for exit value computation We miss a bunch of rotate opportunities on various including etc On X86
Definition: README.txt:568
llvm::MachineInstrBundleIterator< MachineInstr >
llvm::raw_string_ostream::str
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:646
InitializePasses.h
Debug.h
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:307
EmitDotOnly
static cl::opt< bool > EmitDotOnly(PASS_KEY "-dot-only", cl::desc("For each function, emit a dot graph depicting potential LVI " "gadgets, and do not insert any fences"), cl::init(false), cl::Hidden)
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
MachineDominators.h
SmallSet.h
llvm::SmallVectorImpl::insert
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:809