1//===- X86LFIRewritePass.cpp - Modify code generation for LFI ---*- C++ -*-===//
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// This file implements the X86LFIRewritePass, which prepares machine code for
10// LFI sandboxing by making sure that every address which may legitimately be
11// the destination of an indirect branch is aligned to a bundle boundary.
12//
13//===----------------------------------------------------------------------===//
14
15#include "MCTargetDesc/X86MCLFIRewriter.h"
16#include "X86.h"
17#include "llvm/CodeGen/MachineFunctionPass.h"
18#include "llvm/CodeGen/MachineJumpTableInfo.h"
19#include "llvm/Support/Alignment.h"
20
21using namespace llvm;
22
23static constexpr Align BundleAlign = Align::Constant<X86::LFIBundleSize>();
24
25namespace {
26class X86LFIRewriteLegacy : public MachineFunctionPass {
27public:
28 static char ID;
29 X86LFIRewriteLegacy() : MachineFunctionPass(ID) {}
30
31 bool runOnMachineFunction(MachineFunction &MF) override;
32
33 StringRef getPassName() const override { return "X86 LFI rewrites"; }
34};
35} // namespace
36
37char X86LFIRewriteLegacy::ID = 0;
38
39static void alignToBundle(MachineBasicBlock &MBB) {
40 MBB.setAlignment(A: std::max(a: MBB.getAlignment(), b: BundleAlign), /*MaxBytes=*/0);
41}
42
43// Returns true if MBB may be reached by an indirect branch (does not include
44// jump table targets).
45static bool isIndirectlyReachable(const MachineBasicBlock &MBB) {
46 return MBB.hasAddressTaken() || MBB.isEHPad();
47}
48
49static void alignIndirectBranchTargets(MachineFunction &MF) {
50 // Function entry points are reachable through function pointers.
51 MF.ensureAlignment(A: BundleAlign);
52
53 // Blocks that are the target of a jump table are not considered
54 // address-taken by LLVM, but they are still reached by an indirect branch.
55 // This also covers the SJLJ landing pads, which EmitSjLjDispatchBlock puts
56 // into a jump table.
57 if (const MachineJumpTableInfo *JTI = MF.getJumpTableInfo())
58 for (const MachineJumpTableEntry &JTE : JTI->getJumpTables())
59 for (MachineBasicBlock *MBB : JTE.MBBs)
60 alignToBundle(MBB&: *MBB);
61
62 for (MachineBasicBlock &MBB : MF) {
63 if (isIndirectlyReachable(MBB))
64 alignToBundle(MBB);
65 }
66}
67
68bool X86LFIRewriteLegacy::runOnMachineFunction(MachineFunction &MF) {
69 alignIndirectBranchTargets(MF);
70 return true;
71}
72
73PreservedAnalyses X86LFIRewritePass::run(MachineFunction &MF,
74 MachineFunctionAnalysisManager &) {
75 alignIndirectBranchTargets(MF);
76 return PreservedAnalyses::all();
77}
78
79FunctionPass *llvm::createX86LFIRewritePass() {
80 return new X86LFIRewriteLegacy();
81}
82