@@ -48,14 +48,14 @@ static cl::opt<bool> NoLSEAtomics(
4848
4949namespace {
5050
51- static void getSystemFlag (MCInst &Inst, MCPhysReg RegName) {
51+ [[maybe_unused]] static void getSystemFlag (MCInst &Inst, MCPhysReg RegName) {
5252 Inst.setOpcode (AArch64::MRS);
5353 Inst.clear ();
5454 Inst.addOperand (MCOperand::createReg (RegName));
5555 Inst.addOperand (MCOperand::createImm (AArch64SysReg::NZCV));
5656}
5757
58- static void setSystemFlag (MCInst &Inst, MCPhysReg RegName) {
58+ [[maybe_unused]] static void setSystemFlag (MCInst &Inst, MCPhysReg RegName) {
5959 Inst.setOpcode (AArch64::MSR);
6060 Inst.clear ();
6161 Inst.addOperand (MCOperand::createImm (AArch64SysReg::NZCV));
@@ -2114,6 +2114,14 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
21142114 convertJmpToTailCall (Inst);
21152115 }
21162116
2117+ void createDirectBranch (MCInst &Inst, const MCSymbol *Target,
2118+ MCContext *Ctx) override {
2119+ Inst.setOpcode (AArch64::B);
2120+ Inst.clear ();
2121+ Inst.addOperand (MCOperand::createExpr (getTargetExprFor (
2122+ Inst, MCSymbolRefExpr::create (Target, *Ctx), *Ctx, 0 )));
2123+ }
2124+
21172125 bool analyzeBranch (InstructionIterator Begin, InstructionIterator End,
21182126 const MCSymbol *&TBB, const MCSymbol *&FBB,
21192127 MCInst *&CondBranch,
@@ -2471,21 +2479,14 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
24712479 }
24722480
24732481 InstructionListType createInstrumentedIndCallHandlerExitBB () const override {
2474- InstructionListType Insts (5 );
24752482 // Code sequence for instrumented indirect call handler:
2476- // msr nzcv, x1
2477- // ldp x0, x1, [sp], #16
2478- // ldr x16, [sp], #16
2479- // ldp x0, x1, [sp], #16
2480- // br x16
2481- setSystemFlag (Insts[0 ], AArch64::X1);
2482- createPopRegisters (Insts[1 ], AArch64::X0, AArch64::X1);
2483- // Here we load address of the next function which should be called in the
2484- // original binary to X16 register. Writing to X16 is permitted without
2485- // needing to restore.
2486- loadReg (Insts[2 ], AArch64::X16, AArch64::SP);
2487- createPopRegisters (Insts[3 ], AArch64::X0, AArch64::X1);
2488- createIndirectBranch (Insts[4 ], AArch64::X16, 0 );
2483+ // ret
2484+
2485+ InstructionListType Insts;
2486+
2487+ Insts.emplace_back ();
2488+ createReturn (Insts.back ());
2489+
24892490 return Insts;
24902491 }
24912492
@@ -2561,39 +2562,59 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
25612562 MCSymbol *HandlerFuncAddr,
25622563 int CallSiteID,
25632564 MCContext *Ctx) override {
2564- InstructionListType Insts;
25652565 // Code sequence used to enter indirect call instrumentation helper:
2566- // stp x0, x1, [sp, #-16]! createPushRegisters
2567- // mov target x0 convertIndirectCallToLoad -> orr x0 target xzr
2566+ // stp x0, x1, [sp, #-16]! createPushRegisters (1)
2567+ // mov target, x0 convertIndirectCallToLoad -> orr x0 target xzr
25682568 // mov x1 CallSiteID createLoadImmediate ->
25692569 // movk x1, #0x0, lsl #48
25702570 // movk x1, #0x0, lsl #32
25712571 // movk x1, #0x0, lsl #16
25722572 // movk x1, #0x0
2573- // stp x0, x1, [sp, #-16]!
2574- // bl *HandlerFuncAddr createIndirectCall ->
2573+ // stp x0, x30, [sp, #-16]! (2)
25752574 // adr x0 *HandlerFuncAddr -> adrp + add
2576- // blr x0
2575+ // blr x0 (__bolt_instr_ind_call_handler_func)
2576+ // ldp x0, x30, [sp], #16 (2)
2577+ // mov x0, target ; move target address to used register
2578+ // ldp x0, x1, [sp], #16 (1)
2579+
2580+ InstructionListType Insts;
25772581 Insts.emplace_back ();
2578- createPushRegisters (Insts.back (), AArch64::X0, AArch64::X1);
2582+ createPushRegisters (Insts.back (), getIntArgRegister (0 ),
2583+ getIntArgRegister (1 ));
25792584 Insts.emplace_back (CallInst);
2580- convertIndirectCallToLoad (Insts.back (), AArch64::X0 );
2585+ convertIndirectCallToLoad (Insts.back (), getIntArgRegister ( 0 ) );
25812586 InstructionListType LoadImm =
25822587 createLoadImmediate (getIntArgRegister (1 ), CallSiteID);
25832588 Insts.insert (Insts.end (), LoadImm.begin (), LoadImm.end ());
25842589 Insts.emplace_back ();
2585- createPushRegisters (Insts.back (), AArch64::X0 , AArch64::X1 );
2590+ createPushRegisters (Insts.back (), getIntArgRegister ( 0 ) , AArch64::LR );
25862591 Insts.resize (Insts.size () + 2 );
2587- InstructionListType Addr =
2588- materializeAddress ( HandlerFuncAddr, Ctx, AArch64::X0 );
2592+ InstructionListType Addr = materializeAddress (
2593+ HandlerFuncAddr, Ctx, CallInst. getOperand ( 0 ). getReg () );
25892594 assert (Addr.size () == 2 && " Invalid Addr size" );
25902595 std::copy (Addr.begin (), Addr.end (), Insts.end () - Addr.size ());
2596+
25912597 Insts.emplace_back ();
2592- createIndirectCallInst (Insts.back (), isTailCall (CallInst), AArch64::X0);
2598+ createIndirectCallInst (Insts.back (), false ,
2599+ CallInst.getOperand (0 ).getReg ());
25932600
2594- // Carry over metadata including tail call marker if present.
2595- stripAnnotations (Insts.back ());
2596- moveAnnotations (std::move (CallInst), Insts.back ());
2601+ Insts.emplace_back ();
2602+ createPopRegisters (Insts.back (), getIntArgRegister (0 ), AArch64::LR);
2603+
2604+ // move x0 to indirect call register
2605+ Insts.emplace_back ();
2606+ Insts.back ().setOpcode (AArch64::ORRXrs);
2607+ Insts.back ().insert (Insts.back ().begin (),
2608+ MCOperand::createReg (CallInst.getOperand (0 ).getReg ()));
2609+ Insts.back ().insert (Insts.back ().begin () + 1 ,
2610+ MCOperand::createReg (AArch64::XZR));
2611+ Insts.back ().insert (Insts.back ().begin () + 2 ,
2612+ MCOperand::createReg (getIntArgRegister (0 )));
2613+ Insts.back ().insert (Insts.back ().begin () + 3 , MCOperand::createImm (0 ));
2614+
2615+ Insts.emplace_back ();
2616+ createPopRegisters (Insts.back (), getIntArgRegister (0 ),
2617+ getIntArgRegister (1 ));
25972618
25982619 return Insts;
25992620 }
@@ -2602,43 +2623,53 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
26022623 createInstrumentedIndCallHandlerEntryBB (const MCSymbol *InstrTrampoline,
26032624 const MCSymbol *IndCallHandler,
26042625 MCContext *Ctx) override {
2605- // Code sequence used to check whether InstrTampoline was initialized
2626+ // Code sequence used to check whether InstrTrampoline was initialized
26062627 // and call it if so, returns via IndCallHandler
2607- // stp x0, x1, [sp, #-16]!
2608- // mrs x1, nzcv
2609- // adr x0, InstrTrampoline -> adrp + add
2610- // ldr x0, [x0]
2628+ // adrp x0, InstrTrampoline
2629+ // ldr x0, [x0, #lo12:InstrTrampoline]
26112630 // subs x0, x0, #0x0
26122631 // b.eq IndCallHandler
26132632 // str x30, [sp, #-16]!
26142633 // blr x0
26152634 // ldr x30, [sp], #16
26162635 // b IndCallHandler
26172636 InstructionListType Insts;
2637+
2638+ // load handler address
2639+ MCInst InstAdrp;
2640+ InstAdrp.setOpcode (AArch64::ADRP);
2641+ InstAdrp.addOperand (MCOperand::createReg (getIntArgRegister (0 )));
2642+ InstAdrp.addOperand (MCOperand::createImm (0 ));
2643+ setOperandToSymbolRef (InstAdrp, /* OpNum */ 1 , InstrTrampoline,
2644+ /* Addend */ 0 , Ctx, ELF::R_AARCH64_ADR_GOT_PAGE);
2645+ Insts.emplace_back (InstAdrp);
2646+
2647+ MCInst InstLoad;
2648+ InstLoad.setOpcode (AArch64::LDRXui);
2649+ InstLoad.addOperand (MCOperand::createReg (getIntArgRegister (0 )));
2650+ InstLoad.addOperand (MCOperand::createReg (getIntArgRegister (0 )));
2651+ InstLoad.addOperand (MCOperand::createImm (0 ));
2652+ setOperandToSymbolRef (InstLoad, /* OpNum */ 2 , InstrTrampoline,
2653+ /* Addend */ 0 , Ctx, ELF::R_AARCH64_LD64_GOT_LO12_NC);
2654+ Insts.emplace_back (InstLoad);
2655+
2656+ InstructionListType CmpJmp =
2657+ createCmpJE (getIntArgRegister (0 ), 0 , IndCallHandler, Ctx);
2658+ Insts.insert (Insts.end (), CmpJmp.begin (), CmpJmp.end ());
2659+
26182660 Insts.emplace_back ();
2619- createPushRegisters (Insts.back (), AArch64::X0, AArch64::X1);
2620- Insts.emplace_back ();
2621- getSystemFlag (Insts.back (), getIntArgRegister (1 ));
2622- Insts.emplace_back ();
2623- Insts.emplace_back ();
2624- InstructionListType Addr =
2625- materializeAddress (InstrTrampoline, Ctx, AArch64::X0);
2626- std::copy (Addr.begin (), Addr.end (), Insts.end () - Addr.size ());
2627- assert (Addr.size () == 2 && " Invalid Addr size" );
2628- Insts.emplace_back ();
2629- loadReg (Insts.back (), AArch64::X0, AArch64::X0);
2630- InstructionListType cmpJmp =
2631- createCmpJE (AArch64::X0, 0 , IndCallHandler, Ctx);
2632- Insts.insert (Insts.end (), cmpJmp.begin (), cmpJmp.end ());
2633- Insts.emplace_back ();
2634- storeReg (Insts.back (), AArch64::LR, AArch64::SP);
2661+ storeReg (Insts.back (), AArch64::LR, getSpRegister (/* Size*/ 8 ));
2662+
26352663 Insts.emplace_back ();
26362664 Insts.back ().setOpcode (AArch64::BLR);
2637- Insts.back ().addOperand (MCOperand::createReg (AArch64::X0));
2665+ Insts.back ().addOperand (MCOperand::createReg (getIntArgRegister (0 )));
2666+
26382667 Insts.emplace_back ();
2639- loadReg (Insts.back (), AArch64::LR, AArch64::SP);
2668+ loadReg (Insts.back (), AArch64::LR, getSpRegister (/* Size*/ 8 ));
2669+
26402670 Insts.emplace_back ();
2641- createDirectCall (Insts.back (), IndCallHandler, Ctx, /* IsTailCall*/ true );
2671+ createDirectBranch (Insts.back (), IndCallHandler, Ctx);
2672+
26422673 return Insts;
26432674 }
26442675
0 commit comments