LLVM: lib/Target/X86/X86LoadValueInjectionLoadHardening.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

65

66using namespace llvm;

67

68#define PASS_KEY "x86-lvi-load"

69#define DEBUG_TYPE PASS_KEY

70

71STATISTIC(NumFences, "Number of LFENCEs inserted for LVI mitigation");

72STATISTIC(NumFunctionsConsidered, "Number of functions analyzed");

73STATISTIC(NumFunctionsMitigated, "Number of functions for which mitigations "

74 "were deployed");

75STATISTIC(NumGadgets, "Number of LVI gadgets detected during analysis");

76

79 cl::desc("Specify a plugin to optimize LFENCE insertion"), cl::Hidden);

80

83 cl::desc("Don't treat conditional branches as disclosure gadgets. This "

84 "may improve performance, at the cost of security."),

86

90 "For each function, emit a dot graph depicting potential LVI gadgets"),

92

95 cl::desc("For each function, emit a dot graph depicting potential LVI "

96 "gadgets, and do not insert any fences"),

98

101 cl::desc("For each function, emit a dot graph to stdout depicting "

102 "potential LVI gadgets, used for testing purposes only"),

104

106typedef int (*OptimizeCutT)(unsigned int *Nodes, unsigned int NodesSize,

107 unsigned int *Edges, int *EdgeValues,

108 int *CutEdges , unsigned int EdgesSize);

110

111namespace {

112

113struct MachineGadgetGraph : ImmutableGraph<MachineInstr *, int> {

114 static constexpr int GadgetEdgeSentinel = -1;

115 static constexpr MachineInstr *const ArgNodeSentinel = nullptr;

116

118 using Node = GraphT::Node;

119 using Edge = GraphT::Edge;

121 MachineGadgetGraph(std::unique_ptr<Node[]> Nodes,

122 std::unique_ptr<Edge[]> Edges, size_type NodesSize,

123 size_type EdgesSize, int NumFences = 0, int NumGadgets = 0)

124 : GraphT(std::move(Nodes), std::move(Edges), NodesSize, EdgesSize),

125 NumFences(NumFences), NumGadgets(NumGadgets) {}

126 static inline bool isCFGEdge(const Edge &E) {

127 return E.getValue() != GadgetEdgeSentinel;

128 }

129 static inline bool isGadgetEdge(const Edge &E) {

130 return E.getValue() == GadgetEdgeSentinel;

131 }

132 int NumFences;

133 int NumGadgets;

134};

135

136class X86LoadValueInjectionLoadHardeningPass : public MachineFunctionPass {

137public:

139

140 StringRef getPassName() const override {

141 return "X86 Load Value Injection (LVI) Load Hardening";

142 }

143 void getAnalysisUsage(AnalysisUsage &AU) const override;

145

146 static char ID;

147

148private:

150 using Edge = MachineGadgetGraph::Edge;

151 using Node = MachineGadgetGraph::Node;

152 using EdgeSet = MachineGadgetGraph::EdgeSet;

153 using NodeSet = MachineGadgetGraph::NodeSet;

154

158

159 std::unique_ptr

164 std::unique_ptr Graph) const;

166 std::unique_ptr Graph) const;

167 int elimMitigatedEdgesAndNodes(MachineGadgetGraph &G,

168 EdgeSet &ElimEdges ,

169 NodeSet &ElimNodes ) const;

170 std::unique_ptr

171 trimMitigatedEdges(std::unique_ptr Graph) const;

173 EdgeSet &CutEdges ) const;

177 return MI && (MI->getOpcode() == X86::LFENCE ||

178 (STI->useLVIControlFlowIntegrity() && MI->isCall()));

179 }

180};

181

182}

183

184namespace llvm {

185

186template <>

189

190template <>

198

200

202 if (Node->getValue() == MachineGadgetGraph::ArgNodeSentinel)

203 return "ARGS";

204

205 std::string Str;

207 OS << *Node->getValue();

208 return OS.str();

209 }

210

213 if (MI == MachineGadgetGraph::ArgNodeSentinel)

214 return "color = blue";

215 if (MI->getOpcode() == X86::LFENCE)

216 return "color = green";

217 return "";

218 }

219

222 int EdgeVal = (*E.getCurrent()).getValue();

223 return EdgeVal >= 0 ? "label = " + std::to_string(EdgeVal)

224 : "color = red, style = \"dashed\"";

225 }

226};

227

228}

229

230char X86LoadValueInjectionLoadHardeningPass::ID = 0;

231

232void X86LoadValueInjectionLoadHardeningPass::getAnalysisUsage(

235 AU.addRequired();

236 AU.addRequired();

237 AU.addRequired();

239}

240

242 MachineGadgetGraph *G) {

244 "Speculative gadgets for \"" + MF.getName() + "\" function");

245}

246

247bool X86LoadValueInjectionLoadHardeningPass::runOnMachineFunction(

248 MachineFunction &MF) {

250 << " *****\n");

252 if (!STI->useLVILoadHardening())

253 return false;

254

255

256 if (!STI->is64Bit())

257 report_fatal_error("LVI load hardening is only supported on 64-bit", false);

258

259

261 if (F.hasOptNone() && skipFunction(F))

262 return false;

263

264 ++NumFunctionsConsidered;

268 const auto &MLI = getAnalysis().getLI();

269 const auto &MDT = getAnalysis().getDomTree();

270 const auto &MDF = getAnalysis();

271 std::unique_ptr Graph = getGadgetGraph(MF, MLI, MDT, MDF);

272 LLVM_DEBUG(dbgs() << "Building gadget graph... Done\n");

273 if (Graph == nullptr)

274 return false;

275

278 return false;

279 }

280

283 std::error_code FileError;

284 std::string FileName = "lvi.";

285 FileName += MF.getName();

286 FileName += ".dot";

287 raw_fd_ostream FileOut(FileName, FileError);

288 if (FileError)

289 errs() << FileError.message();

291 FileOut.close();

292 LLVM_DEBUG(dbgs() << "Emitting gadget graph... Done\n");

294 return false;

295 }

296

297 int FencesInserted;

300 std::string ErrorMsg;

303 if (!ErrorMsg.empty())

304 report_fatal_error(Twine("Failed to load opt plugin: \"") + ErrorMsg +

305 "\"");

309 }

310 FencesInserted = hardenLoadsWithPlugin(MF, std::move(Graph));

311 } else {

312 FencesInserted = hardenLoadsWithHeuristic(MF, std::move(Graph));

313 }

314

315 if (FencesInserted > 0)

316 ++NumFunctionsMitigated;

317 NumFences += FencesInserted;

318 return (FencesInserted > 0);

319}

320

321std::unique_ptr

322X86LoadValueInjectionLoadHardeningPass::getGadgetGraph(

323 MachineFunction &MF, const MachineLoopInfo &MLI,

324 const MachineDominatorTree &MDT,

325 const MachineDominanceFrontier &MDF) const {

326 using namespace rdf;

327

328

329 DataFlowGraph DFG{MF, *TII, *TRI, MDT, MDF};

330 DFG.build();

332 L.computePhiInfo();

333

334 GraphBuilder Builder;

335 using GraphIter = GraphBuilder::BuilderNodeRef;

336 DenseMap<MachineInstr *, GraphIter> NodeMap;

337 int FenceCount = 0, GadgetCount = 0;

338 auto MaybeAddNode = [&NodeMap, &Builder](MachineInstr *MI) {

340 if (Inserted) {

341 auto I = Builder.addVertex(MI);

342 Ref->second = I;

343 return std::pair<GraphIter, bool>{I, true};

344 }

345 return std::pair<GraphIter, bool>{Ref->getSecond(), false};

346 };

347

348

349

350

351

352 DenseMap<NodeId, std::vector> Transmitters;

353

354

355

356 auto AnalyzeDef = [&](NodeAddr<DefNode *> SourceDef) {

357 SmallSet<NodeId, 8> UsesVisited, DefsVisited;

358 std::function<void(NodeAddr<DefNode *>)> AnalyzeDefUseChain =

359 [&](NodeAddr<DefNode *> Def) {

361 return;

362

363

366 for (auto UseID : L.getAllReachedUses(DefReg, Def)) {

367 auto Use = DFG.addr<UseNode *>(UseID);

368 if (Use.Addr->getFlags() & NodeAttrs::PhiRef) {

370 for (const auto& I : L.getRealUses(Phi.Id)) {

371 if (DFG.getPRI().alias(RegisterRef(I.first), DefReg)) {

372 for (const auto &UA : I.second)

373 Uses.emplace(UA.first);

374 }

375 }

376 } else {

377 Uses.emplace(UseID);

378 }

379 }

380

381

382

383

384 for (auto UseID : Uses) {

385 if (!UsesVisited.insert(UseID).second)

386 continue;

387

388 auto Use = DFG.addr<UseNode *>(UseID);

393

394

395

396

397

398 if (UseMI.isCall())

399 continue;

400

401

402 if (instrUsesRegToAccessMemory(UseMI, UseMO.getReg()) ||

404 instrUsesRegToBranch(UseMI, UseMO.getReg()))) {

406 if (UseMI.mayLoad())

407 continue;

408

409

410 }

411

412

414 for (const auto &ChildDef :

415 Owner.Addr->members_if(DataFlowGraph::IsDef, DFG)) {

416 if (!DefsVisited.insert(ChildDef.Id).second)

417 continue;

419 continue;

420 if (Def.Id == ChildDef.Id)

421 continue;

422

423 AnalyzeDefUseChain(ChildDef);

424

425

426 for (auto TransmitterId : Transmitters[ChildDef.Id])

427 Transmitters[Def.Id].push_back(TransmitterId);

428 }

429 }

430

431

432

433 auto &DefTransmitters = Transmitters[Def.Id];

434

435

437 DefTransmitters.erase(llvm::unique(DefTransmitters),

438 DefTransmitters.end());

439 };

440

441

442 AnalyzeDefUseChain(SourceDef);

443 auto &SourceDefTransmitters = Transmitters[SourceDef.Id];

444 if (SourceDefTransmitters.empty())

445 return;

446

447 MachineInstr *Source = SourceDef.Addr->getFlags() & NodeAttrs::PhiRef

448 ? MachineGadgetGraph::ArgNodeSentinel

449 : SourceDef.Addr->getOp().getParent();

450 auto GadgetSource = MaybeAddNode(Source);

451

452 for (auto TransmitterId : SourceDefTransmitters) {

453 MachineInstr *Sink = DFG.addr<StmtNode *>(TransmitterId).Addr->getCode();

454 auto GadgetSink = MaybeAddNode(Sink);

455

456 Builder.addEdge(MachineGadgetGraph::GadgetEdgeSentinel,

457 GadgetSource.first, GadgetSink.first);

458 ++GadgetCount;

459 }

460 };

461

462 LLVM_DEBUG(dbgs() << "Analyzing def-use chains to find gadgets\n");

463

464 NodeAddr<BlockNode *> EntryBlock = DFG.getFunc().Addr->getEntryBlock(DFG);

465 for (NodeAddr<PhiNode *> ArgPhi :

466 EntryBlock.Addr->members_if(DataFlowGraph::IsPhi, DFG)) {

467 NodeList Defs = ArgPhi.Addr->members_if(DataFlowGraph::IsDef, DFG);

469 }

470

471 for (NodeAddr<BlockNode *> BA : DFG.getFunc().Addr->members(DFG)) {

472 for (NodeAddr<StmtNode *> SA :

473 BA.Addr->members_if(DataFlowGraph::IsCodeNodeAttrs::Stmt, DFG)) {

474 MachineInstr *MI = SA.Addr->getCode();

475 if (isFence(MI)) {

476 MaybeAddNode(MI);

477 ++FenceCount;

478 } else if (MI->mayLoad()) {

479 NodeList Defs = SA.Addr->members_if(DataFlowGraph::IsDef, DFG);

481 }

482 }

483 }

484 LLVM_DEBUG(dbgs() << "Found " << FenceCount << " fences\n");

485 LLVM_DEBUG(dbgs() << "Found " << GadgetCount << " gadgets\n");

486 if (GadgetCount == 0)

487 return nullptr;

488 NumGadgets += GadgetCount;

489

490

491 SmallPtrSet<MachineBasicBlock *, 8> BlocksVisited;

492 std::function<void(MachineBasicBlock *, GraphIter, unsigned)> TraverseCFG =

493 [&](MachineBasicBlock *MBB, GraphIter GI, unsigned ParentDepth) {

496

498 auto BeginBB = MaybeAddNode(&*NI);

499 Builder.addEdge(ParentDepth, GI, BeginBB.first);

500 if (!BlocksVisited.insert(MBB).second)

501 return;

502

503

504 GI = BeginBB.first;

505 while (++NI != MBB->end()) {

506 auto Ref = NodeMap.find(&*NI);

507 if (Ref != NodeMap.end()) {

508 Builder.addEdge(LoopDepth, GI, Ref->getSecond());

509 GI = Ref->getSecond();

510 }

511 }

512

513

516 auto EndBB = MaybeAddNode(&*T);

517 if (EndBB.second)

518 Builder.addEdge(LoopDepth, GI, EndBB.first);

519 GI = EndBB.first;

520 }

521 }

522 for (MachineBasicBlock *Succ : MBB->successors())

523 TraverseCFG(Succ, GI, LoopDepth);

524 };

525

526

527 GraphIter ArgNode = MaybeAddNode(MachineGadgetGraph::ArgNodeSentinel).first;

528 TraverseCFG(&MF.front(), ArgNode, 0);

529 std::unique_ptr G{Builder.get(FenceCount, GadgetCount)};

530 LLVM_DEBUG(dbgs() << "Found " << G->nodes_size() << " nodes\n");

531 return G;

532}

533

534

535int X86LoadValueInjectionLoadHardeningPass::elimMitigatedEdgesAndNodes(

536 MachineGadgetGraph &G, EdgeSet &ElimEdges ,

537 NodeSet &ElimNodes ) const {

538 if (G.NumFences > 0) {

539

540

541 for (const Edge &E : G.edges()) {

542 const Node *Dest = E.getDest();

543 if (isFence(Dest->getValue())) {

544 ElimNodes.insert(*Dest);

545 ElimEdges.insert(E);

546 for (const Edge &DE : Dest->edges())

547 ElimEdges.insert(DE);

548 }

549 }

550 }

551

552

553 int RemainingGadgets = 0;

554 NodeSet ReachableNodes{G};

555 for (const Node &RootN : G.nodes()) {

556 if (llvm::none_of(RootN.edges(), MachineGadgetGraph::isGadgetEdge))

557 continue;

558

559

560 ReachableNodes.clear();

561 std::function<void(const Node *, bool)> FindReachableNodes =

562 [&](const Node *N, bool FirstNode) {

563 if (!FirstNode)

564 ReachableNodes.insert(*N);

565 for (const Edge &E : N->edges()) {

566 const Node *Dest = E.getDest();

567 if (MachineGadgetGraph::isCFGEdge(E) && !ElimEdges.contains(E) &&

568 !ReachableNodes.contains(*Dest))

569 FindReachableNodes(Dest, false);

570 }

571 };

572 FindReachableNodes(&RootN, true);

573

574

575 for (const Edge &E : RootN.edges()) {

576 if (MachineGadgetGraph::isGadgetEdge(E)) {

577 if (ReachableNodes.contains(*E.getDest())) {

578

579 ++RemainingGadgets;

580 } else {

581 ElimEdges.insert(E);

582 }

583 }

584 }

585 }

586 return RemainingGadgets;

587}

588

589std::unique_ptr

590X86LoadValueInjectionLoadHardeningPass::trimMitigatedEdges(

591 std::unique_ptr Graph) const {

592 NodeSet ElimNodes{*Graph};

593 EdgeSet ElimEdges{*Graph};

594 int RemainingGadgets =

595 elimMitigatedEdgesAndNodes(*Graph, ElimEdges, ElimNodes);

596 if (ElimEdges.empty() && ElimNodes.empty()) {

597 Graph->NumFences = 0;

598 Graph->NumGadgets = RemainingGadgets;

599 } else {

600 Graph = GraphBuilder::trim(*Graph, ElimNodes, ElimEdges, 0 ,

601 RemainingGadgets);

602 }

603 return Graph;

604}

605

606int X86LoadValueInjectionLoadHardeningPass::hardenLoadsWithPlugin(

607 MachineFunction &MF, std::unique_ptr Graph) const {

608 int FencesInserted = 0;

609

610 do {

611 LLVM_DEBUG(dbgs() << "Eliminating mitigated paths...\n");

612 Graph = trimMitigatedEdges(std::move(Graph));

613 LLVM_DEBUG(dbgs() << "Eliminating mitigated paths... Done\n");

614 if (Graph->NumGadgets == 0)

615 break;

616

618 EdgeSet CutEdges{*Graph};

619 auto Nodes = std::make_unique<unsigned int[]>(Graph->nodes_size() +

620 1 );

621 auto Edges = std::make_unique<unsigned int[]>(Graph->edges_size());

622 auto EdgeCuts = std::make_unique<int[]>(Graph->edges_size());

623 auto EdgeValues = std::make_unique<int[]>(Graph->edges_size());

624 for (const Node &N : Graph->nodes()) {

625 Nodes[Graph->getNodeIndex(N)] = Graph->getEdgeIndex(*N.edges_begin());

626 }

627 Nodes[Graph->nodes_size()] = Graph->edges_size();

628 for (const Edge &E : Graph->edges()) {

629 Edges[Graph->getEdgeIndex(E)] = Graph->getNodeIndex(*E.getDest());

630 EdgeValues[Graph->getEdgeIndex(E)] = E.getValue();

631 }

632 OptimizeCut(Nodes.get(), Graph->nodes_size(), Edges.get(), EdgeValues.get(),

633 EdgeCuts.get(), Graph->edges_size());

634 for (int I = 0; I < Graph->edges_size(); ++I)

635 if (EdgeCuts[I])

636 CutEdges.set(I);

638 LLVM_DEBUG(dbgs() << "Cut " << CutEdges.count() << " edges\n");

639

641 FencesInserted += insertFences(MF, *Graph, CutEdges);

643 LLVM_DEBUG(dbgs() << "Inserted " << FencesInserted << " fences\n");

644

645 Graph = GraphBuilder::trim(*Graph, NodeSet{*Graph}, CutEdges);

646 } while (true);

647

648 return FencesInserted;

649}

650

651int X86LoadValueInjectionLoadHardeningPass::hardenLoadsWithHeuristic(

652 MachineFunction &MF, std::unique_ptr Graph) const {

653

654

655 if (Graph->NumFences > 0) {

656 LLVM_DEBUG(dbgs() << "Eliminating mitigated paths...\n");

657 Graph = trimMitigatedEdges(std::move(Graph));

658 LLVM_DEBUG(dbgs() << "Eliminating mitigated paths... Done\n");

659 }

660

661 if (Graph->NumGadgets == 0)

662 return 0;

663

665 EdgeSet CutEdges{*Graph};

666

667

668 DenseMap<const Node *, SmallVector<const Edge *, 2>> IngressEdgeMap;

669 for (const Edge &E : Graph->edges())

670 if (MachineGadgetGraph::isCFGEdge(E))

671 IngressEdgeMap[E.getDest()].push_back(&E);

672

673

674

675

676

677

678

679

680

681 for (const Node &N : Graph->nodes()) {

682 for (const Edge &E : N.edges()) {

683 if (!MachineGadgetGraph::isGadgetEdge(E))

684 continue;

685

688 for (const Edge &EgressEdge : N.edges())

689 if (MachineGadgetGraph::isCFGEdge(EgressEdge))

690 EgressEdges.push_back(&EgressEdge);

691

692 int EgressCutCost = 0, IngressCutCost = 0;

693 for (const Edge *EgressEdge : EgressEdges)

694 if (!CutEdges.contains(*EgressEdge))

695 EgressCutCost += EgressEdge->getValue();

696 for (const Edge *IngressEdge : IngressEdges)

697 if (!CutEdges.contains(*IngressEdge))

698 IngressCutCost += IngressEdge->getValue();

699

700 auto &EdgesToCut =

701 IngressCutCost < EgressCutCost ? IngressEdges : EgressEdges;

702 for (const Edge *E : EdgesToCut)

703 CutEdges.insert(*E);

704 }

705 }

707 LLVM_DEBUG(dbgs() << "Cut " << CutEdges.count() << " edges\n");

708

710 int FencesInserted = insertFences(MF, *Graph, CutEdges);

712 LLVM_DEBUG(dbgs() << "Inserted " << FencesInserted << " fences\n");

713

714 return FencesInserted;

715}

716

717int X86LoadValueInjectionLoadHardeningPass::insertFences(

718 MachineFunction &MF, MachineGadgetGraph &G,

719 EdgeSet &CutEdges ) const {

720 int FencesInserted = 0;

721 for (const Node &N : G.nodes()) {

722 for (const Edge &E : N.edges()) {

723 if (CutEdges.contains(E)) {

724 MachineInstr *MI = N.getValue(), *Prev;

725 MachineBasicBlock *MBB;

727 if (MI == MachineGadgetGraph::ArgNodeSentinel) {

728

731 Prev = nullptr;

732 } else if (MI->isBranch()) {

733 MBB = MI->getParent();

734 InsertionPt = MI;

735 Prev = MI->getPrevNode();

736

737

738 for (const Edge &E : N.edges()) {

739 if (MachineGadgetGraph::isCFGEdge(E))

740 CutEdges.insert(E);

741 }

742 } else {

743 MBB = MI->getParent();

744 InsertionPt = MI->getNextNode() ? MI->getNextNode() : MBB->end();

745 Prev = InsertionPt == MBB->end()

747 : InsertionPt->getPrevNode();

748 }

749

750 if ((InsertionPt == MBB->end() || !isFence(&*InsertionPt)) &&

751 (!Prev || !isFence(Prev))) {

753 ++FencesInserted;

754 }

755 }

756 }

757 }

758 return FencesInserted;

759}

760

761bool X86LoadValueInjectionLoadHardeningPass::instrUsesRegToAccessMemory(

763 if (MI.mayLoadOrStore() || MI.getOpcode() == X86::MFENCE ||

764 MI.getOpcode() == X86::SFENCE || MI.getOpcode() == X86::LFENCE)

765 return false;

766

768 if (MemRefBeginIdx < 0) {

769 LLVM_DEBUG(dbgs() << "Warning: unable to obtain memory operand for loading "

770 "instruction:\n";

772 return false;

773 }

774

775 const MachineOperand &BaseMO =

777 const MachineOperand &IndexMO =

783}

784

785bool X86LoadValueInjectionLoadHardeningPass::instrUsesRegToBranch(

787 if (MI.isConditionalBranch())

788 return false;

789 for (const MachineOperand &Use : MI.uses())

790 if (Use.isReg() && Use.getReg() == Reg)

791 return true;

792 return false;

793}

794

796 "X86 LVI load hardening", false, false)

802

804 return new X86LoadValueInjectionLoadHardeningPass();

805}

MachineInstrBuilder & UseMI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static ManagedStatic< DebugCounterOwner > Owner

This file defines the DenseMap class.

Description: ImmutableGraph is a fast DAG implementation that cannot be modified, except by creating ...

Register const TargetRegisterInfo * TRI

Promote Memory to Register

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

Remove Loads Into Fake Uses

std::pair< BasicBlock *, BasicBlock * > Edge

This file defines the SmallSet class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

int(* OptimizeCutT)(unsigned int *Nodes, unsigned int NodesSize, unsigned int *Edges, int *EdgeValues, int *CutEdges, unsigned int EdgesSize)

Definition X86LoadValueInjectionLoadHardening.cpp:106

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)

static cl::opt< std::string > OptimizePluginPath(PASS_KEY "-opt-plugin", cl::desc("Specify a plugin to optimize LFENCE insertion"), cl::Hidden)

static void writeGadgetGraph(raw_ostream &OS, MachineFunction &MF, MachineGadgetGraph *G)

Definition X86LoadValueInjectionLoadHardening.cpp:241

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)

static llvm::sys::DynamicLibrary OptimizeDL

Definition X86LoadValueInjectionLoadHardening.cpp:105

static OptimizeCutT OptimizeCut

Definition X86LoadValueInjectionLoadHardening.cpp:109

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)

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)

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

iterator find(const_arg_type_t< KeyT > Val)

std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)

bool contains(const_arg_type_t< KeyT > Val) const

Return true if the specified key is in the map, false otherwise.

FunctionPass class - This class is used to implement most global optimizations.

unsigned getLoopDepth(const BlockT *BB) const

Return the loop nesting level of the specified block.

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

LLVM_ABI iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

iterator_range< succ_iterator > successors()

MachineInstrBundleIterator< MachineInstr > iterator

Analysis pass which computes a MachineDominatorTree.

DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineBasicBlock & front() const

Representation of each machine instruction.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

MachineInstr * getParent()

getParent - Return the instruction that this operand belongs to.

Register getReg() const

getReg - Returns the register number.

A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...

virtual void print(raw_ostream &OS, const Module *M) const

print - Print out the internal state of the pass.

Wrapper class representing virtual and physical registers.

constexpr bool isValid() const

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

void push_back(const T &Elt)

StringRef - Represent a constant reference to a string, i.e.

TargetInstrInfo - Interface to description of machine instruction set.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

const X86InstrInfo * getInstrInfo() const override

const X86RegisterInfo * getRegisterInfo() const override

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an std::string.

std::string & str()

Returns the string's reference.

This class provides a portable interface to dynamic libraries which also might be known as shared lib...

static LLVM_ABI 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...

LLVM_ABI void * getAddressOfSymbol(const char *symbolName)

Searches through the library for the symbol symbolName.

bool isValid() const

Returns true if the object refers to a valid library.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

int getFirstAddrOperandIdx(const MachineInstr &MI)

Return the index of the instruction's first address operand, if it has a memory reference,...

initializer< Ty > init(const Ty &Val)

NodeAddr< DefNode * > Def

NodeAddr< PhiNode * > Phi

NodeAddr< UseNode * > Use

std::set< NodeId > NodeSet

SmallVector< Node, 4 > NodeList

This is an optimization pass for GlobalISel generic memory operations.

UnaryFunction for_each(R &&Range, UnaryFunction F)

Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

FunctionPass * createX86LoadValueInjectionLoadHardeningPass()

Definition X86LoadValueInjectionLoadHardening.cpp:803

LLVM_ABI raw_fd_ostream & outs()

This returns a reference to a raw_fd_ostream for standard output.

raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")

auto unique(Range &&R, Predicate P)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool none_of(R &&Range, UnaryPredicate P)

Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

@ Ref

The access may reference the value stored in memory.

static std::string getNodeAttributes(NodeRef Node, GraphType *)

Definition X86LoadValueInjectionLoadHardening.cpp:211

Traits::ChildIteratorType ChildIteratorType

Definition X86LoadValueInjectionLoadHardening.cpp:196

std::string getNodeLabel(NodeRef Node, GraphType *)

Definition X86LoadValueInjectionLoadHardening.cpp:201

static std::string getEdgeAttributes(NodeRef, ChildIteratorType E, GraphType *)

Definition X86LoadValueInjectionLoadHardening.cpp:220

MachineGadgetGraph GraphType

Definition X86LoadValueInjectionLoadHardening.cpp:192

Traits::EdgeRef EdgeRef

Definition X86LoadValueInjectionLoadHardening.cpp:195

Traits::ChildEdgeIteratorType ChildEdgeIteratorType

Definition X86LoadValueInjectionLoadHardening.cpp:197

Traits::NodeRef NodeRef

Definition X86LoadValueInjectionLoadHardening.cpp:194

llvm::GraphTraits< GraphType * > Traits

Definition X86LoadValueInjectionLoadHardening.cpp:193

DOTGraphTraits(bool IsSimple=false)

Definition X86LoadValueInjectionLoadHardening.cpp:199

DefaultDOTGraphTraits(bool simple=false)

typename GraphType::UnknownGraphTypeError NodeRef

uint16_t getAttrs() const

uint16_t getFlags() const

RegisterRef getRegRef(const DataFlowGraph &G) const

Node getOwner(const DataFlowGraph &G)