llvm.org GIT mirror llvm / 1513285
Introduce a "patchable-function" function attribute Summary: The `"patchable-function"` attribute can be used by an LLVM client to influence LLVM's code generation in ways that makes the generated code easily patchable at runtime (for instance, to redirect control). Right now only one patchability scheme is supported, `"prologue-short-redirect"`, but this can be expanded in the future. Reviewers: joker.eph, rnk, echristo, dberris Subscribers: joker.eph, echristo, mcrosier, llvm-commits Differential Revision: http://reviews.llvm.org/D19046 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266715 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 4 years ago
16 changed file(s) with 234 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
14041404 passes make choices that keep the code size of this function low,
14051405 and otherwise do optimizations specifically to reduce code size as
14061406 long as they do not significantly impact runtime performance.
1407 ``"patchable-function"``
1408 This attribute tells the code generator that the code
1409 generated for this function needs to follow certain conventions that
1410 make it possible for a runtime function to patch over it later.
1411 The exact effect of this attribute depends on its string value,
1412 for which there currently is one legal possiblity:
1413
1414 * ``"prologue-short-redirect"`` - This style of patchable
1415 function is intended to support patching a function prologue to
1416 redirect control away from the function in a thread safe
1417 manner. It guarantees that the first instruction of the
1418 function will be large enough to accommodate a short jump
1419 instruction, and will be sufficiently aligned to allow being
1420 fully changed via an atomic compare-and-swap instruction.
1421 While the first requirement can be satisfied by inserting large
1422 enough NOP, LLVM can and will try to re-purpose an existing
1423 instruction (i.e. one that would have to be emitted anyway) as
1424 the patchable instruction larger than a short jump.
1425
1426 ``"prologue-short-redirect"`` is currently only supported on
1427 x86-64.
1428
1429 This attribute by itself does not imply restrictions on
1430 inter-procedural optimizations. All of the semantic effects the
1431 patching may have to be separately conveyed via the linkage type.
14071432 ``readnone``
14081433 On a function, this attribute indicates that the function computes its
14091434 result (or decides to unwind an exception) based strictly on its arguments,
598598 /// \brief This pass lays out funclets contiguously.
599599 extern char &FuncletLayoutID;
600600
601 /// \brief This pass implements the "patchable-function" attribute.
602 extern char &PatchableFunctionID;
603
601604 /// createStackProtectorPass - This pass adds stack protectors to functions.
602605 ///
603606 FunctionPass *createStackProtectorPass(const TargetMachine *TM);
328328 void initializeFunctionImportPassPass(PassRegistry &);
329329 void initializeLoopVersioningPassPass(PassRegistry &);
330330 void initializeWholeProgramDevirtPass(PassRegistry &);
331 void initializePatchableFunctionPass(PassRegistry &);
331332 }
332333
333334 #endif
928928 let usesCustomInserter = 1;
929929 let mayLoad = 1;
930930 }
931 def PATCHABLE_OP : Instruction {
932 let OutOperandList = (outs unknown:$dst);
933 let InOperandList = (ins variable_ops);
934 let usesCustomInserter = 1;
935 let mayLoad = 1;
936 let mayStore = 1;
937 let hasSideEffects = 1;
938 }
931939
932940 // Generic opcodes used in GlobalISel.
933941 include "llvm/Target/GenericOpcodes.td"
132132 /// comparisons into existing memory operations.
133133 HANDLE_TARGET_OPCODE(FAULTING_LOAD_OP, 22)
134134
135 /// Wraps a machine instruction to add patchability constraints. An
136 /// instruction wrapped in PATCHABLE_OP has to either have a minimum
137 /// size or be preceded with a nop of that size. The first operand is
138 /// an immediate denoting the minimum size of the instruction, the
139 /// second operand is an immediate denoting the opcode of the original
140 /// instruction. The rest of the operands are the operands of the
141 /// original instruction.
142 HANDLE_TARGET_OPCODE(PATCHABLE_OP, 23)
143
135144 /// The following generic opcodes are not supposed to appear after ISel.
136145 /// This is something we might want to relax, but for now, this is convenient
137146 /// to produce diagnostics.
138147
139148 /// Generic ADD instruction. This is an integer add.
140 HANDLE_TARGET_OPCODE(G_ADD, 23)
149 HANDLE_TARGET_OPCODE(G_ADD, 24)
141150 HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_START, G_ADD)
142151
143152 /// Generic BRANCH instruction. This is an unconditional branch.
144 HANDLE_TARGET_OPCODE(G_BR, 24)
153 HANDLE_TARGET_OPCODE(G_BR, 25)
145154
146155 // TODO: Add more generic opcodes as we move along.
147156
7575 MachineSSAUpdater.cpp
7676 MachineTraceMetrics.cpp
7777 MachineVerifier.cpp
78 PatchableFunction.cpp
7879 MIRPrinter.cpp
7980 MIRPrintingPass.cpp
8081 OptimizePHIs.cpp
5454 initializeMachineSchedulerPass(Registry);
5555 initializeMachineSinkingPass(Registry);
5656 initializeMachineVerifierPassPass(Registry);
57 initializePatchableFunctionPass(Registry);
5758 initializeOptimizePHIsPass(Registry);
5859 initializePEIPass(Registry);
5960 initializePHIEliminationPass(Registry);
601601 addPass(&StackMapLivenessID, false);
602602 addPass(&LiveDebugValuesID, false);
603603
604 addPass(&PatchableFunctionID, false);
605
604606 AddingMachinePasses = false;
605607 }
606608
0 //===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements edits function bodies in place to support the
10 // "patchable-function" attribute.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/CodeGen/Passes.h"
15 #include "llvm/CodeGen/Analysis.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/Target/TargetFrameLowering.h"
20 #include "llvm/Target/TargetInstrInfo.h"
21 #include "llvm/Target/TargetSubtargetInfo.h"
22
23 using namespace llvm;
24
25 namespace {
26 struct PatchableFunction : public MachineFunctionPass {
27 static char ID; // Pass identification, replacement for typeid
28 PatchableFunction() : MachineFunctionPass(ID) {
29 initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
30 }
31
32 bool runOnMachineFunction(MachineFunction &F) override;
33 MachineFunctionProperties getRequiredProperties() const override {
34 return MachineFunctionProperties().set(
35 MachineFunctionProperties::Property::AllVRegsAllocated);
36 }
37 };
38 }
39
40 bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
41 if (!MF.getFunction()->hasFnAttribute("patchable-function"))
42 return false;
43
44 #ifndef NDEBUG
45 Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function");
46 StringRef PatchType = PatchAttr.getValueAsString();
47 assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
48 #endif
49
50 auto &FirstMBB = *MF.begin();
51 auto &FirstMI = *FirstMBB.begin();
52
53 auto *TII = MF.getSubtarget().getInstrInfo();
54 auto MIB = BuildMI(FirstMBB, FirstMBB.begin(), FirstMI.getDebugLoc(),
55 TII->get(TargetOpcode::PATCHABLE_OP))
56 .addImm(2)
57 .addImm(FirstMI.getOpcode());
58
59 for (auto &MO : FirstMI.operands())
60 MIB.addOperand(MO);
61
62 FirstMI.eraseFromParent();
63 MF.ensureAlignment(4);
64 return true;
65 }
66
67 char PatchableFunction::ID = 0;
68 char &llvm::PatchableFunctionID = PatchableFunction::ID;
69 INITIALIZE_PASS(PatchableFunction, "patchable-function", "", false, false)
2626 #include "llvm/IR/Module.h"
2727 #include "llvm/IR/Type.h"
2828 #include "llvm/MC/MCAsmInfo.h"
29 #include "llvm/MC/MCCodeEmitter.h"
2930 #include "llvm/MC/MCContext.h"
3031 #include "llvm/MC/MCExpr.h"
3132 #include "llvm/MC/MCSectionCOFF.h"
4849 Subtarget = &MF.getSubtarget();
4950
5051 SMShadowTracker.startFunction(MF);
52 CodeEmitter.reset(TM.getTarget().createMCCodeEmitter(
53 *MF.getSubtarget().getInstrInfo(), *MF.getSubtarget().getRegisterInfo(),
54 MF.getContext()));
5155
5256 SetupMachineFunction(MF);
5357
2828 const X86Subtarget *Subtarget;
2929 StackMaps SM;
3030 FaultMaps FM;
31 std::unique_ptr CodeEmitter;
3132
3233 // This utility class tracks the length of a stackmap instruction's 'shadow'.
3334 // It is used by the X86AsmPrinter to ensure that the stackmap shadow
3940 // few instruction bytes to cover the shadow are NOPs used for padding.
4041 class StackMapShadowTracker {
4142 public:
42 StackMapShadowTracker(TargetMachine &TM);
43 StackMapShadowTracker();
4344 ~StackMapShadowTracker();
4445 void startFunction(MachineFunction &MF);
45 void count(MCInst &Inst, const MCSubtargetInfo &STI);
46 void count(MCInst &Inst, const MCSubtargetInfo &STI,
47 MCCodeEmitter *CodeEmitter);
4648
4749 // Called to signal the start of a shadow of RequiredSize bytes.
4850 void reset(unsigned RequiredSize) {
5557 // to emit any necessary padding-NOPs.
5658 void emitShadowPadding(MCStreamer &OutStreamer, const MCSubtargetInfo &STI);
5759 private:
58 TargetMachine &TM;
5960 const MachineFunction *MF;
60 std::unique_ptr CodeEmitter;
6161 bool InShadow;
6262
6363 // RequiredShadowSize holds the length of the shadow specified in the most
8181 void LowerPATCHPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
8282 void LowerSTATEPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
8383 void LowerFAULTING_LOAD_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
84 void LowerPATCHABLE_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
8485
8586 void LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI);
8687
8788 public:
8889 explicit X86AsmPrinter(TargetMachine &TM,
8990 std::unique_ptr Streamer)
90 : AsmPrinter(TM, std::move(Streamer)), SM(*this), FM(*this),
91 SMShadowTracker(TM) {}
91 : AsmPrinter(TM, std::move(Streamer)), SM(*this), FM(*this) {}
9292
9393 const char *getPassName() const override {
9494 return "X86 Assembly / Object Emitter";
1919 #include "Utils/X86ShuffleDecode.h"
2020 #include "llvm/ADT/Optional.h"
2121 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/iterator_range.h"
2223 #include "llvm/CodeGen/MachineFunction.h"
2324 #include "llvm/CodeGen/MachineConstantPool.h"
2425 #include "llvm/CodeGen/MachineOperand.h"
6970
7071 // Emit a minimal sequence of nops spanning NumBytes bytes.
7172 static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit,
72 const MCSubtargetInfo &STI);
73 const MCSubtargetInfo &STI, bool OnlyOneNop = false);
7374
7475 namespace llvm {
75 X86AsmPrinter::StackMapShadowTracker::StackMapShadowTracker(TargetMachine &TM)
76 : TM(TM), InShadow(false), RequiredShadowSize(0), CurrentShadowSize(0) {}
76 X86AsmPrinter::StackMapShadowTracker::StackMapShadowTracker()
77 : InShadow(false), RequiredShadowSize(0), CurrentShadowSize(0) {}
7778
7879 X86AsmPrinter::StackMapShadowTracker::~StackMapShadowTracker() {}
7980
80 void
81 X86AsmPrinter::StackMapShadowTracker::startFunction(MachineFunction &F) {
81 void X86AsmPrinter::StackMapShadowTracker::startFunction(MachineFunction &F) {
8282 MF = &F;
83 CodeEmitter.reset(TM.getTarget().createMCCodeEmitter(
84 *MF->getSubtarget().getInstrInfo(),
85 *MF->getSubtarget().getRegisterInfo(), MF->getContext()));
8683 }
8784
8885 void X86AsmPrinter::StackMapShadowTracker::count(MCInst &Inst,
89 const MCSubtargetInfo &STI) {
86 const MCSubtargetInfo &STI,
87 MCCodeEmitter *CodeEmitter) {
9088 if (InShadow) {
9189 SmallString<256> Code;
9290 SmallVector Fixups;
109107
110108 void X86AsmPrinter::EmitAndCountInstruction(MCInst &Inst) {
111109 OutStreamer->EmitInstruction(Inst, getSubtargetInfo());
112 SMShadowTracker.count(Inst, getSubtargetInfo());
110 SMShadowTracker.count(Inst, getSubtargetInfo(), CodeEmitter.get());
113111 }
114112 } // end llvm namespace
115113
785783 }
786784
787785 /// \brief Emit the optimal amount of multi-byte nops on X86.
788 static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit, const MCSubtargetInfo &STI) {
786 static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit,
787 const MCSubtargetInfo &STI, bool OnlyOneNop) {
789788 // This works only for 64bit. For 32bit we have to do additional checking if
790789 // the CPU supports multi-byte nops.
791790 assert(Is64Bit && "EmitNops only supports X86-64");
832831 .addImm(Displacement).addReg(SegmentReg), STI);
833832 break;
834833 }
834
835 (void) OnlyOneNop;
836 assert((!OnlyOneNop || NumBytes == 0) &&
837 "Allowed only one nop instruction!");
835838 } // while (NumBytes)
836839 }
837840
914917 OutStreamer->EmitInstruction(LoadMI, getSubtargetInfo());
915918 }
916919
920 void X86AsmPrinter::LowerPATCHABLE_OP(const MachineInstr &MI,
921 X86MCInstLower &MCIL) {
922 // PATCHABLE_OP minsize, opcode, operands
923
924 unsigned MinSize = MI.getOperand(0).getImm();
925 unsigned Opcode = MI.getOperand(1).getImm();
926
927 MCInst MCI;
928 MCI.setOpcode(Opcode);
929 for (auto &MO : make_range(MI.operands_begin() + 2, MI.operands_end()))
930 if (auto MaybeOperand = MCIL.LowerMachineOperand(&MI, MO))
931 MCI.addOperand(MaybeOperand.getValue());
932
933 SmallString<256> Code;
934 SmallVector Fixups;
935 raw_svector_ostream VecOS(Code);
936 CodeEmitter->encodeInstruction(MCI, VecOS, Fixups, getSubtargetInfo());
937
938 if (Code.size() < MinSize) {
939 if (MinSize == 2 && Opcode == X86::PUSH64r) {
940 // This is an optimization that lets us get away without emitting a nop in
941 // many cases.
942 //
943 // NB! In some cases the encoding for PUSH64r (e.g. PUSH64r %R9) takes two
944 // bytes too, so the check on MinSize is important.
945 MCI.setOpcode(X86::PUSH64rmr);
946 } else {
947 EmitNops(*OutStreamer, MinSize, Subtarget->is64Bit(), getSubtargetInfo(),
948 /* OnlyOneNop = */ true);
949 }
950 }
951
952 OutStreamer->EmitInstruction(MCI, getSubtargetInfo());
953 }
954
917955 // Lower a stackmap of the form:
918956 // , , ...
919957 void X86AsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
12111249
12121250 case TargetOpcode::FAULTING_LOAD_OP:
12131251 return LowerFAULTING_LOAD_OP(*MI, MCInstLowering);
1252
1253 case TargetOpcode::PATCHABLE_OP:
1254 return LowerPATCHABLE_OP(*MI, MCInstLowering);
12141255
12151256 case TargetOpcode::STACKMAP:
12161257 return LowerSTACKMAP(*MI);
14741515 // is at the end of the shadow.
14751516 if (MI->isCall()) {
14761517 // Count then size of the call towards the shadow
1477 SMShadowTracker.count(TmpInst, getSubtargetInfo());
1518 SMShadowTracker.count(TmpInst, getSubtargetInfo(), CodeEmitter.get());
14781519 // Then flush the shadow so that we fill with nops before the call, not
14791520 // after it.
14801521 SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());
0 ; RUN: llc -filetype=obj -o - -mtriple=x86_64-apple-macosx < %s | llvm-objdump -triple x86_64-apple-macosx -disassemble - | FileCheck %s
1 ; RUN: llc -mtriple=x86_64-apple-macosx < %s | FileCheck %s --check-prefix=CHECK-ALIGN
2
3 declare void @callee(i64*)
4
5 define void @f0() "patchable-function"="prologue-short-redirect" {
6 ; CHECK-LABEL: _f0:
7 ; CHECK-NEXT: 66 90 nop
8
9 ; CHECK-ALIGN: .p2align 4, 0x90
10 ; CHECK-ALIGN: _f0:
11
12 ret void
13 }
14
15 define void @f1() "patchable-function"="prologue-short-redirect" "no-frame-pointer-elim"="true" {
16 ; CHECK-LABEL: _f1
17 ; CHECK-NEXT: ff f5 pushq %rbp
18
19 ; CHECK-ALIGN: .p2align 4, 0x90
20 ; CHECK-ALIGN: _f1:
21 ret void
22 }
23
24 define void @f2() "patchable-function"="prologue-short-redirect" {
25 ; CHECK-LABEL: _f2
26 ; CHECK-NEXT: 48 81 ec a8 00 00 00 subq $168, %rsp
27
28 ; CHECK-ALIGN: .p2align 4, 0x90
29 ; CHECK-ALIGN: _f2:
30 %ptr = alloca i64, i32 20
31 call void @callee(i64* %ptr)
32 ret void
33 }
34
35 define void @f3() "patchable-function"="prologue-short-redirect" optsize {
36 ; CHECK-LABEL: _f3
37 ; CHECK-NEXT: 66 90 nop
38
39 ; CHECK-ALIGN: .p2align 4, 0x90
40 ; CHECK-ALIGN: _f3:
41 ret void
42 }
3535 // CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
3636 // CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 14, 0, // Skip to: 21
3737 // CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 5, 0, // Skip to: 18
38 // CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 26, 0, 0, 0, // Opcode: InstB, skip to: 18
39 // CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 25, 1, // Opcode: InstA
38 // CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 27, 0, 0, 0, // Opcode: InstB, skip to: 18
39 // CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 26, 1, // Opcode: InstA
4040 // CHECK-NEXT: /* 21 */ MCD::OPC_Fail,
4141
4242 // CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
3434 // CHECK-NEXT: /* 7 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
3535 // CHECK-NEXT: /* 10 */ MCD::OPC_FilterValue, 0, 22, 0, // Skip to: 36
3636 // CHECK-NEXT: /* 14 */ MCD::OPC_CheckField, 0, 2, 3, 5, 0, // Skip to: 25
37 // CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, 26, 0, 0, 0, // Opcode: InstB, skip to: 25
37 // CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, 27, 0, 0, 0, // Opcode: InstB, skip to: 25
3838 // CHECK-NEXT: /* 25 */ MCD::OPC_CheckField, 3, 2, 0, 5, 0, // Skip to: 36
39 // CHECK-NEXT: /* 31 */ MCD::OPC_TryDecode, 25, 1, 0, 0, // Opcode: InstA, skip to: 36
39 // CHECK-NEXT: /* 31 */ MCD::OPC_TryDecode, 26, 1, 0, 0, // Opcode: InstA, skip to: 36
4040 // CHECK-NEXT: /* 36 */ MCD::OPC_Fail,
4141
4242 // CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
3636 // CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
3737 // CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 14, 0, // Skip to: 21
3838 // CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 5, 0, // Skip to: 18
39 // CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 26, 0, 0, 0, // Opcode: InstB, skip to: 18
40 // CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 25, 1, // Opcode: InstA
39 // CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 27, 0, 0, 0, // Opcode: InstB, skip to: 18
40 // CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 26, 1, // Opcode: InstA
4141 // CHECK-NEXT: /* 21 */ MCD::OPC_Fail,
4242
4343 // CHECK: if (DecodeInstBOp(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }