Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion bolt/include/bolt/Core/MCPlusBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,11 @@ class MCPlusBuilder {
llvm_unreachable("not implemented");
}

virtual void createDirectBranch(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) {
llvm_unreachable("not implemented");
}

virtual MCPhysReg getX86R11() const { llvm_unreachable("not implemented"); }

virtual unsigned getShortBranchOpcode(unsigned Opcode) const {
Expand Down Expand Up @@ -2399,7 +2404,7 @@ class MCPlusBuilder {

virtual InstructionListType
createInstrumentedIndirectCall(MCInst &&CallInst, MCSymbol *HandlerFuncAddr,
int CallSiteID, MCContext *Ctx) {
size_t CallSiteID, MCContext *Ctx) {
llvm_unreachable("not implemented");
return InstructionListType();
}
Expand Down
178 changes: 105 additions & 73 deletions bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ static cl::opt<bool> NoLSEAtomics(

namespace {

static void getSystemFlag(MCInst &Inst, MCPhysReg RegName) {
[[maybe_unused]] static void getSystemFlag(MCInst &Inst, MCPhysReg RegName) {
Inst.setOpcode(AArch64::MRS);
Inst.clear();
Inst.addOperand(MCOperand::createReg(RegName));
Inst.addOperand(MCOperand::createImm(AArch64SysReg::NZCV));
}

static void setSystemFlag(MCInst &Inst, MCPhysReg RegName) {
[[maybe_unused]] static void setSystemFlag(MCInst &Inst, MCPhysReg RegName) {
Inst.setOpcode(AArch64::MSR);
Inst.clear();
Inst.addOperand(MCOperand::createImm(AArch64SysReg::NZCV));
Expand Down Expand Up @@ -2413,6 +2413,14 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
return isCompAndBranch(Inst);
}

void createDirectBranch(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override {
Inst.setOpcode(AArch64::B);
Inst.clear();
Inst.addOperand(MCOperand::createExpr(getTargetExprFor(
Inst, MCSymbolRefExpr::create(Target, *Ctx), *Ctx, 0)));
}

bool analyzeBranch(InstructionIterator Begin, InstructionIterator End,
const MCSymbol *&TBB, const MCSymbol *&FBB,
MCInst *&CondBranch,
Expand Down Expand Up @@ -2770,21 +2778,14 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
}

InstructionListType createInstrumentedIndCallHandlerExitBB() const override {
InstructionListType Insts(5);
// Code sequence for instrumented indirect call handler:
// msr nzcv, x1
// ldp x0, x1, [sp], #16
// ldr x16, [sp], #16
// ldp x0, x1, [sp], #16
// br x16
setSystemFlag(Insts[0], AArch64::X1);
createPopRegisters(Insts[1], AArch64::X0, AArch64::X1);
// Here we load address of the next function which should be called in the
// original binary to X16 register. Writing to X16 is permitted without
// needing to restore.
loadReg(Insts[2], AArch64::X16, AArch64::SP);
createPopRegisters(Insts[3], AArch64::X0, AArch64::X1);
createIndirectBranch(Insts[4], AArch64::X16, 0);
// ret

InstructionListType Insts;

Insts.emplace_back();
createReturn(Insts.back());

return Insts;
}

Expand Down Expand Up @@ -2837,14 +2838,28 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {

InstructionListType createLoadImmediate(const MCPhysReg Dest,
uint64_t Imm) const override {
InstructionListType Insts(4);
int Shift = 48;
for (int I = 0; I < 4; I++, Shift -= 16) {
Insts[I].setOpcode(AArch64::MOVKXi);
Insts[I].addOperand(MCOperand::createReg(Dest));
Insts[I].addOperand(MCOperand::createReg(Dest));
Insts[I].addOperand(MCOperand::createImm((Imm >> Shift) & 0xFFFF));
Insts[I].addOperand(MCOperand::createImm(Shift));
InstructionListType Insts;

Insts.emplace_back();
MCInst &Inst = Insts.back();
Inst.clear();
Inst.setOpcode(AArch64::MOVZXi);
Inst.addOperand(MCOperand::createReg(Dest));
Inst.addOperand(MCOperand::createImm(Imm & 0xFFFF));
Inst.addOperand(MCOperand::createImm(0));

int Shift = 16;
for (int I = 0; I < 3; I++, Shift += 16) {
const uint64_t ImmVal = (Imm >> Shift) & 0xFFFF;
if (!ImmVal)
continue;
Insts.emplace_back();
MCInst &Inst = Insts.back();
Inst.setOpcode(AArch64::MOVKXi);
Inst.addOperand(MCOperand::createReg(Dest));
Inst.addOperand(MCOperand::createReg(Dest));
Inst.addOperand(MCOperand::createImm(ImmVal));
Inst.addOperand(MCOperand::createImm(Shift));
}
return Insts;
}
Expand All @@ -2858,41 +2873,48 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {

InstructionListType createInstrumentedIndirectCall(MCInst &&CallInst,
MCSymbol *HandlerFuncAddr,
int CallSiteID,
size_t CallSiteID,
MCContext *Ctx) override {
InstructionListType Insts;
// Code sequence used to enter indirect call instrumentation helper:
// stp x0, x1, [sp, #-16]! createPushRegisters
// mov target x0 convertIndirectCallToLoad -> orr x0 target xzr
// mov x1 CallSiteID createLoadImmediate ->
// movk x1, #0x0, lsl #48
// movk x1, #0x0, lsl #32
// movk x1, #0x0, lsl #16
// movk x1, #0x0
// stp x0, x1, [sp, #-16]!
// bl *HandlerFuncAddr createIndirectCall ->
// adr x0 *HandlerFuncAddr -> adrp + add
// blr x0
// snippet requires 2 registers: target address and call site id
// stp CallIDReg, x30, [sp, #-16]!
// movz/k CallIDReg, CallSiteID
// stp TAReg, CallIDReg, [sp, #-16]! ; push address and id for lib
// adr + add TAReg, *HandlerFuncAddr ; __bolt_instr_ind_call_handler_func
// blr TAReg
// ldr TAReg, [sp], #16 ; restore target address
// ldp CallIDReg, x30, [sp], #16
// blr TAReg

const MCRegister TAReg = CallInst.getOperand(0).getReg();
const MCRegister CallIDReg =
TAReg != AArch64::X0 ? AArch64::X0 : AArch64::X1;

InstructionListType Insts;
Insts.emplace_back();
createPushRegisters(Insts.back(), AArch64::X0, AArch64::X1);
Insts.emplace_back(CallInst);
convertIndirectCallToLoad(Insts.back(), AArch64::X0);
InstructionListType LoadImm =
createLoadImmediate(getIntArgRegister(1), CallSiteID);
createPushRegisters(Insts.back(), CallIDReg, AArch64::LR);

InstructionListType LoadImm = createLoadImmediate(CallIDReg, CallSiteID);
Insts.insert(Insts.end(), LoadImm.begin(), LoadImm.end());

Insts.emplace_back();
createPushRegisters(Insts.back(), AArch64::X0, AArch64::X1);
createPushRegisters(Insts.back(), TAReg, CallIDReg);

Insts.resize(Insts.size() + 2);
InstructionListType Addr =
materializeAddress(HandlerFuncAddr, Ctx, AArch64::X0);
InstructionListType Addr = materializeAddress(HandlerFuncAddr, Ctx, TAReg);
assert(Addr.size() == 2 && "Invalid Addr size");
std::copy(Addr.begin(), Addr.end(), Insts.end() - Addr.size());

Insts.emplace_back();
createIndirectCallInst(Insts.back(), false, TAReg);

Insts.emplace_back();
loadReg(Insts.back(), TAReg, getStackPointer());

Insts.emplace_back();
createIndirectCallInst(Insts.back(), isTailCall(CallInst), AArch64::X0);
createPopRegisters(Insts.back(), CallIDReg, AArch64::LR);

// Carry over metadata including tail call marker if present.
stripAnnotations(Insts.back());
moveAnnotations(std::move(CallInst), Insts.back());
Insts.emplace_back(CallInst);

return Insts;
}
Expand All @@ -2901,43 +2923,53 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
createInstrumentedIndCallHandlerEntryBB(const MCSymbol *InstrTrampoline,
const MCSymbol *IndCallHandler,
MCContext *Ctx) override {
// Code sequence used to check whether InstrTampoline was initialized
// Code sequence used to check whether InstrTrampoline was initialized
// and call it if so, returns via IndCallHandler
// stp x0, x1, [sp, #-16]!
// mrs x1, nzcv
// adr x0, InstrTrampoline -> adrp + add
// ldr x0, [x0]
// adrp x0, InstrTrampoline
// ldr x0, [x0, #lo12:InstrTrampoline]
// subs x0, x0, #0x0
// b.eq IndCallHandler
// str x30, [sp, #-16]!
// blr x0
// ldr x30, [sp], #16
// b IndCallHandler
InstructionListType Insts;

// load handler address
MCInst InstAdrp;
InstAdrp.setOpcode(AArch64::ADRP);
InstAdrp.addOperand(MCOperand::createReg(getIntArgRegister(0)));
InstAdrp.addOperand(MCOperand::createImm(0));
setOperandToSymbolRef(InstAdrp, /* OpNum */ 1, InstrTrampoline,
/* Addend */ 0, Ctx, ELF::R_AARCH64_ADR_GOT_PAGE);
Insts.emplace_back(InstAdrp);

MCInst InstLoad;
InstLoad.setOpcode(AArch64::LDRXui);
InstLoad.addOperand(MCOperand::createReg(getIntArgRegister(0)));
InstLoad.addOperand(MCOperand::createReg(getIntArgRegister(0)));
InstLoad.addOperand(MCOperand::createImm(0));
setOperandToSymbolRef(InstLoad, /* OpNum */ 2, InstrTrampoline,
/* Addend */ 0, Ctx, ELF::R_AARCH64_LD64_GOT_LO12_NC);
Insts.emplace_back(InstLoad);

InstructionListType CmpJmp =
createCmpJE(getIntArgRegister(0), 0, IndCallHandler, Ctx);
Insts.insert(Insts.end(), CmpJmp.begin(), CmpJmp.end());

Insts.emplace_back();
createPushRegisters(Insts.back(), AArch64::X0, AArch64::X1);
Insts.emplace_back();
getSystemFlag(Insts.back(), getIntArgRegister(1));
Insts.emplace_back();
Insts.emplace_back();
InstructionListType Addr =
materializeAddress(InstrTrampoline, Ctx, AArch64::X0);
std::copy(Addr.begin(), Addr.end(), Insts.end() - Addr.size());
assert(Addr.size() == 2 && "Invalid Addr size");
Insts.emplace_back();
loadReg(Insts.back(), AArch64::X0, AArch64::X0);
InstructionListType cmpJmp =
createCmpJE(AArch64::X0, 0, IndCallHandler, Ctx);
Insts.insert(Insts.end(), cmpJmp.begin(), cmpJmp.end());
Insts.emplace_back();
storeReg(Insts.back(), AArch64::LR, AArch64::SP);
storeReg(Insts.back(), AArch64::LR, getStackPointer());

Insts.emplace_back();
Insts.back().setOpcode(AArch64::BLR);
Insts.back().addOperand(MCOperand::createReg(AArch64::X0));
Insts.back().addOperand(MCOperand::createReg(getIntArgRegister(0)));

Insts.emplace_back();
loadReg(Insts.back(), AArch64::LR, AArch64::SP);
loadReg(Insts.back(), AArch64::LR, getStackPointer());

Insts.emplace_back();
createDirectCall(Insts.back(), IndCallHandler, Ctx, /*IsTailCall*/ true);
createDirectBranch(Insts.back(), IndCallHandler, Ctx);

return Insts;
}

Expand Down
2 changes: 1 addition & 1 deletion bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {

InstructionListType createInstrumentedIndirectCall(MCInst &&CallInst,
MCSymbol *HandlerFuncAddr,
int CallSiteID,
size_t CallSiteID,
MCContext *Ctx) override {
// Code sequence used to enter indirect call instrumentation helper:
// addi sp, sp, -0x10
Expand Down
2 changes: 1 addition & 1 deletion bolt/lib/Target/X86/X86MCPlusBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3123,7 +3123,7 @@ class X86MCPlusBuilder : public MCPlusBuilder {

InstructionListType createInstrumentedIndirectCall(MCInst &&CallInst,
MCSymbol *HandlerFuncAddr,
int CallSiteID,
size_t CallSiteID,
MCContext *Ctx) override {
// Check if the target address expression used in the original indirect call
// uses the stack pointer, which we are going to clobber.
Expand Down
4 changes: 2 additions & 2 deletions bolt/runtime/instr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1696,7 +1696,7 @@ extern "C" __attribute((naked)) void __bolt_instr_indirect_call()
#if defined(__aarch64__)
// clang-format off
__asm__ __volatile__(SAVE_ALL
"ldp x0, x1, [sp, #288]\n"
"ldp x0, x1, [sp, #272]\n"
"bl instrumentIndirectCall\n"
RESTORE_ALL
"ret\n"
Expand Down Expand Up @@ -1733,7 +1733,7 @@ extern "C" __attribute((naked)) void __bolt_instr_indirect_tailcall()
#if defined(__aarch64__)
// clang-format off
__asm__ __volatile__(SAVE_ALL
"ldp x0, x1, [sp, #288]\n"
"ldp x0, x1, [sp, #272]\n"
"bl instrumentIndirectCall\n"
RESTORE_ALL
"ret\n"
Expand Down
6 changes: 4 additions & 2 deletions bolt/runtime/sys_aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
"stp x24, x25, [sp, #-16]!\n" \
"stp x26, x27, [sp, #-16]!\n" \
"stp x28, x29, [sp, #-16]!\n" \
"str x30, [sp,#-16]!\n"
"mrs x29, nzcv\n" \
"stp x29, x30, [sp, #-16]!\n"
// Mirrors SAVE_ALL
#define RESTORE_ALL \
"ldr x30, [sp], #16\n" \
"ldp x29, x30, [sp], #16\n" \
"msr nzcv, x29\n" \
"ldp x28, x29, [sp], #16\n" \
"ldp x26, x27, [sp], #16\n" \
"ldp x24, x25, [sp], #16\n" \
Expand Down
Loading
Loading