LLVM 24.0.0git
AArch64MCLFIRewriter.h
Go to the documentation of this file.
1//===- AArch64MCLFIRewriter.h -----------------------------------*- 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 declares the AArch64MCLFIRewriter class, the AArch64 specific
10// subclass of MCLFIRewriter.
11//
12//===----------------------------------------------------------------------===//
13#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCLFIREWRITER_H
14#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCLFIREWRITER_H
15
17#include "AArch64MCOptions.h"
18#include "llvm/MC/MCInstrInfo.h"
20#include "llvm/MC/MCRegister.h"
22
23#include <optional>
24
25namespace llvm {
26class MCContext;
27class MCExpr;
28class MCInst;
29class MCOperand;
30class MCStreamer;
31class MCSubtargetInfo;
32class MCSymbol;
33
34/// Rewrites AArch64 instructions for LFI sandboxing.
35///
36/// This class implements the LFI (Lightweight Fault Isolation) rewriting
37/// for AArch64 instructions. It transforms instructions to ensure memory
38/// accesses and control flow are confined within the sandbox region.
39///
40/// Reserved registers:
41/// - X27: Sandbox base address (always holds the base)
42/// - X28: Safe address register (always within sandbox)
43/// - X26: Scratch register for intermediate calculations
44/// - X25: context register (points to thread-local runtime data)
45/// - SP: Stack pointer (always within sandbox)
46/// - X30: Link register (always within sandbox)
48 const AArch64MCOptions &CLOpts;
49
50public:
51 AArch64MCLFIRewriter(MCContext &Ctx, std::unique_ptr<MCRegisterInfo> &&RI,
52 std::unique_ptr<MCInstrInfo> &&II)
53 : MCLFIRewriter(Ctx, std::move(RI), std::move(II)),
54 CLOpts(AArch64MCOptions::Global) {}
55
56 bool rewriteInst(const MCInst &Inst, MCStreamer &Out,
57 const MCSubtargetInfo &STI) override;
58
59 void onLabel(const MCSymbol *Symbol, MCStreamer &Out) override;
60 void finish(MCStreamer &Out) override;
61
62private:
63 /// Recursion guard to prevent infinite loops when emitting instructions.
64 bool Guard = false;
65
66 /// When set, an instruction has modified the link register but its guard
67 /// (`add x30, x27, w30, uxtw`) has not been emitted yet. The guard is
68 /// deferred until the next control-flow instruction so that pointer
69 /// authentication can run on the signed value before the mask overwrites the
70 /// upper bits of the pointer.
71 bool DeferredLRGuard = false;
72
73 /// Most recently seen MCSubtargetInfo.
74 const MCSubtargetInfo *LastSTI = nullptr;
75
76 /// Deferred `.tlsdesccall` symbol. The directive attaches a
77 /// R_AARCH64_TLSDESC_CALL relocation to the following BLR. Since LFI inserts
78 /// a guard before that BLR, the marker is deferred and re-emitted between
79 /// the guard and the branch so the relocation stays on the BLR.
80 const MCExpr *PendingTLSDescCall = nullptr;
81
82 /// Rewriter state for implementing the guard-elimination optimization, which
83 /// allows redundant add masks to be skipped. When it holds a value, x28 is
84 /// known to already hold the guarded value of that register.
85 std::optional<MCRegister> ActiveGuardReg;
86
87 // Instruction classification. Returns the reserved register that may be
88 // modified, or an invalid register if no reserved register is touched.
89 MCRegister mayModifyReserved(const MCInst &Inst) const;
90 bool mayModifySP(const MCInst &Inst) const;
91
92 // Instruction emission.
93 void emitInst(const MCInst &Inst, MCStreamer &Out,
94 const MCSubtargetInfo &STI);
95 void emitAddMask(MCRegister Dest, MCRegister Src, MCStreamer &Out,
96 const MCSubtargetInfo &STI);
97 void emitBranch(unsigned Opcode, MCRegister Target, MCStreamer &Out,
98 const MCSubtargetInfo &STI);
99 void emitPendingTLSDescCall(MCStreamer &Out, const MCSubtargetInfo &STI);
100 void emitMov(MCRegister Dest, MCRegister Src, MCStreamer &Out,
101 const MCSubtargetInfo &STI);
102 void emitAddImm(MCRegister Dest, MCRegister Src, int64_t Imm, MCStreamer &Out,
103 const MCSubtargetInfo &STI);
104 void emitAddReg(MCRegister Dest, MCRegister Src1, MCRegister Src2,
105 unsigned Shift, MCStreamer &Out, const MCSubtargetInfo &STI);
106 void emitAddRegExtend(MCRegister Dest, MCRegister Src1, MCRegister Src2,
107 AArch64_AM::ShiftExtendType ExtType, unsigned Shift,
108 MCStreamer &Out, const MCSubtargetInfo &STI);
109 void emitMemRoW(unsigned Opcode, const MCOperand &DataOp, MCRegister BaseReg,
110 MCStreamer &Out, const MCSubtargetInfo &STI);
111
112 // Rewriting logic.
113 void doRewriteInst(const MCInst &Inst, MCStreamer &Out,
114 const MCSubtargetInfo &STI);
115
116 // Control flow.
117 void rewriteIndirectBranch(const MCInst &Inst, MCStreamer &Out,
118 const MCSubtargetInfo &STI);
119 void rewriteReturn(const MCInst &Inst, MCStreamer &Out,
120 const MCSubtargetInfo &STI);
121
122 // Memory access.
123 void rewriteLoadStore(const MCInst &Inst, MCStreamer &Out,
124 const MCSubtargetInfo &STI);
125 void rewriteLoadStoreBase(const MCInst &Inst, MCStreamer &Out,
126 const MCSubtargetInfo &STI);
127 bool rewriteLoadStoreRoW(const MCInst &Inst, MCStreamer &Out,
128 const MCSubtargetInfo &STI);
129
130 // SP register modification.
131 void rewriteSPModification(const MCInst &Inst, MCStreamer &Out,
132 const MCSubtargetInfo &STI);
133
134 // Link register modification.
135 void rewriteLRModification(const MCInst &Inst, MCStreamer &Out,
136 const MCSubtargetInfo &STI);
137
138 // PAC instructions.
139 void rewriteAuthenticatedReturn(const MCInst &Inst, MCStreamer &Out,
140 const MCSubtargetInfo &STI);
141 void rewriteAuthenticatedBranchOrCall(const MCInst &Inst,
142 unsigned BranchOpcode, MCStreamer &Out,
143 const MCSubtargetInfo &STI);
144
145 // System instructions.
146 void rewriteSyscall(const MCInst &Inst, MCStreamer &Out,
147 const MCSubtargetInfo &STI);
148 void rewriteTPRead(const MCInst &Inst, MCStreamer &Out,
149 const MCSubtargetInfo &STI);
150 void rewriteTPWrite(const MCInst &Inst, MCStreamer &Out,
151 const MCSubtargetInfo &STI);
152 void rewriteVASysOp(const MCInst &Inst, MCStreamer &Out,
153 const MCSubtargetInfo &STI);
154};
155
156/// Returns true if \p Opcode is a pre- or post-indexed memory access that the
157/// LFI rewriter expands with a base-register update (i.e. an extra
158/// instruction beyond the guard + access pair).
159bool isLFIPrePostMemAccess(unsigned Opcode);
160
161} // namespace llvm
162
163#endif // LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCLFIREWRITER_H
unsigned Imm
This file declares the MCLFIRewriter class, an abstract class that encapsulates the rewriting logic f...
uint64_t IntrinsicInst * II
void onLabel(const MCSymbol *Symbol, MCStreamer &Out) override
AArch64MCLFIRewriter(MCContext &Ctx, std::unique_ptr< MCRegisterInfo > &&RI, std::unique_ptr< MCInstrInfo > &&II)
bool rewriteInst(const MCInst &Inst, MCStreamer &Out, const MCSubtargetInfo &STI) override
void finish(MCStreamer &Out) override
Context object for machine code objects.
Definition MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
MCLFIRewriter(MCContext &Ctx, std::unique_ptr< MCRegisterInfo > &&RI, std::unique_ptr< MCInstrInfo > &&II)
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Streaming machine code generation interface.
Definition MCStreamer.h:222
Generic base class for all target subtargets.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
Target - Wrapper for Target specific information.
This is an optimization pass for GlobalISel generic memory operations.
bool isLFIPrePostMemAccess(unsigned Opcode)
Returns true if Opcode is a pre- or post-indexed memory access that the LFI rewriter expands with a b...
@ Global
Append to llvm.global_dtors.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878