mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-10 18:11:26 +00:00

Summary: Based on two patches by Michael Mueller. This is a target attribute that causes a function marked with it to be emitted as "hotpatchable". This particular mechanism was originally devised by Microsoft for patching their binaries (which they are constantly updating to stay ahead of crackers, script kiddies, and other ne'er-do-wells on the Internet), but is now commonly abused by Windows programs to hook API functions. This mechanism is target-specific. For x86, a two-byte no-op instruction is emitted at the function's entry point; the entry point must be immediately preceded by 64 (32-bit) or 128 (64-bit) bytes of padding. This padding is where the patch code is written. The two byte no-op is then overwritten with a short jump into this code. The no-op is usually a `movl %edi, %edi` instruction; this is used as a magic value indicating that this is a hotpatchable function. Reviewers: majnemer, sanjoy, rnk Subscribers: dberris, llvm-commits Differential Revision: https://reviews.llvm.org/D19908 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278048 91177308-0d34-0410-b5e6-96231b3b80d8
87 lines
3.0 KiB
C++
87 lines
3.0 KiB
C++
//===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements edits function bodies in place to support the
|
|
// "patchable-function" attribute.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
|
#include "llvm/CodeGen/Analysis.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/Target/TargetFrameLowering.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
struct PatchableFunction : public MachineFunctionPass {
|
|
static char ID; // Pass identification, replacement for typeid
|
|
PatchableFunction() : MachineFunctionPass(ID) {
|
|
initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
|
bool runOnMachineFunction(MachineFunction &F) override;
|
|
MachineFunctionProperties getRequiredProperties() const override {
|
|
return MachineFunctionProperties().set(
|
|
MachineFunctionProperties::Property::AllVRegsAllocated);
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Returns true if instruction \p MI will not result in actual machine code
|
|
/// instructions.
|
|
static bool doesNotGeneratecode(const MachineInstr &MI) {
|
|
// TODO: Introduce an MCInstrDesc flag for this
|
|
switch (MI.getOpcode()) {
|
|
default: return false;
|
|
case TargetOpcode::IMPLICIT_DEF:
|
|
case TargetOpcode::KILL:
|
|
case TargetOpcode::CFI_INSTRUCTION:
|
|
case TargetOpcode::EH_LABEL:
|
|
case TargetOpcode::GC_LABEL:
|
|
case TargetOpcode::DBG_VALUE:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void PatchableFunction::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
AU.addRequired<TargetTransformInfoWrapperPass>();
|
|
}
|
|
|
|
bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
|
|
if (!MF.getFunction()->hasFnAttribute("patchable-function"))
|
|
return false;
|
|
|
|
Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function");
|
|
StringRef PatchType = PatchAttr.getValueAsString();
|
|
assert((PatchType == "prologue-short-redirect" ||
|
|
PatchType == "ms-hotpatch") && "Only possibilities today!");
|
|
|
|
auto &FirstMBB = *MF.begin();
|
|
MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
|
|
for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
|
|
assert(FirstActualI != FirstMBB.end());
|
|
|
|
const TargetTransformInfo &TTI =
|
|
getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*MF.getFunction());
|
|
TTI.emitPatchableOp(PatchType, FirstMBB, FirstActualI);
|
|
|
|
MF.ensureAlignment(4);
|
|
return true;
|
|
}
|
|
|
|
char PatchableFunction::ID = 0;
|
|
char &llvm::PatchableFunctionID = PatchableFunction::ID;
|
|
INITIALIZE_PASS(PatchableFunction, "patchable-function",
|
|
"Implement the 'patchable-function' attribute", false, false)
|