| //===- X86LFIRewritePass.cpp - Modify code generation for LFI ---*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the X86LFIRewritePass, which prepares machine code for |
| // LFI sandboxing by making sure that every address which may legitimately be |
| // the destination of an indirect branch is aligned to a bundle boundary. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MCTargetDesc/X86MCLFIRewriter.h" |
| #include "X86.h" |
| #include "llvm/CodeGen/MachineFunctionPass.h" |
| #include "llvm/CodeGen/MachineJumpTableInfo.h" |
| #include "llvm/Support/Alignment.h" |
| |
| using namespace llvm; |
| |
| static constexpr Align BundleAlign = Align::Constant<X86::LFIBundleSize>(); |
| |
| namespace { |
| class X86LFIRewriteLegacy : public MachineFunctionPass { |
| public: |
| static char ID; |
| X86LFIRewriteLegacy() : MachineFunctionPass(ID) {} |
| |
| bool runOnMachineFunction(MachineFunction &MF) override; |
| |
| StringRef getPassName() const override { return "X86 LFI rewrites"; } |
| }; |
| } // namespace |
| |
| char X86LFIRewriteLegacy::ID = 0; |
| |
| static void alignToBundle(MachineBasicBlock &MBB) { |
| MBB.setAlignment(std::max(MBB.getAlignment(), BundleAlign), /*MaxBytes=*/0); |
| } |
| |
| // Returns true if MBB may be reached by an indirect branch (does not include |
| // jump table targets). |
| static bool isIndirectlyReachable(const MachineBasicBlock &MBB) { |
| return MBB.hasAddressTaken() || MBB.isEHPad(); |
| } |
| |
| static void alignIndirectBranchTargets(MachineFunction &MF) { |
| // Function entry points are reachable through function pointers. |
| MF.ensureAlignment(BundleAlign); |
| |
| // Blocks that are the target of a jump table are not considered |
| // address-taken by LLVM, but they are still reached by an indirect branch. |
| // This also covers the SJLJ landing pads, which EmitSjLjDispatchBlock puts |
| // into a jump table. |
| if (const MachineJumpTableInfo *JTI = MF.getJumpTableInfo()) |
| for (const MachineJumpTableEntry &JTE : JTI->getJumpTables()) |
| for (MachineBasicBlock *MBB : JTE.MBBs) |
| alignToBundle(*MBB); |
| |
| for (MachineBasicBlock &MBB : MF) { |
| if (isIndirectlyReachable(MBB)) |
| alignToBundle(MBB); |
| } |
| } |
| |
| bool X86LFIRewriteLegacy::runOnMachineFunction(MachineFunction &MF) { |
| alignIndirectBranchTargets(MF); |
| return true; |
| } |
| |
| PreservedAnalyses X86LFIRewritePass::run(MachineFunction &MF, |
| MachineFunctionAnalysisManager &) { |
| alignIndirectBranchTargets(MF); |
| return PreservedAnalyses::all(); |
| } |
| |
| FunctionPass *llvm::createX86LFIRewritePass() { |
| return new X86LFIRewriteLegacy(); |
| } |