Skip to content

Commit f9fd006

Browse files
committed
[XRay][AArch64] Suppport __xray_customevent/__xray_typedevent
`__xray_customevent` and `__xray_typedevent` are built-in functions in Clang. With -fxray-instrument, they are lowered to intrinsics llvm.xray.customevent and llvm.xray.typedevent, respectively. These intrinsics are then lowered to TargetOpcode::{PATCHABLE_EVENT_CALL,PATCHABLE_TYPED_EVENT_CALL}. The target is responsible for generating a code sequence that calls either `__xray_CustomEvent` (with 2 arguments) or `__xray_TypedEvent` (with 3 arguments). Before patching, the code sequence is prefixed by a branch instruction that skips the rest of the code sequence. After patching (compiler-rt/lib/xray/xray_AArch64.cpp), the branch instruction becomes a NOP and the function call will take effects. This patch implements the lowering process for {PATCHABLE_EVENT_CALL,PATCHABLE_TYPED_EVENT_CALL} and implements the runtime. ``` // Lowering of PATCHABLE_EVENT_CALL .Lxray_sled_N: b rust-lang#24 stp x0, x1, [sp, #-16]! x0 = reg of op0 x1 = reg of op1 bl __xray_CustomEvent ldrp x0, x1, [sp], rust-lang#16 ``` As a result, two updated tests in compiler-rt/test/xray/TestCases/Posix/ now pass on AArch64. Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D153320
1 parent b0f6fd2 commit f9fd006

File tree

9 files changed

+298
-13
lines changed

9 files changed

+298
-13
lines changed

compiler-rt/lib/xray/xray_AArch64.cpp

+25-3
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,37 @@ bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId,
105105
return patchSled(Enable, FuncId, Sled, __xray_FunctionTailExit);
106106
}
107107

108+
// AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL generates this code sequence:
109+
//
110+
// .Lxray_event_sled_N:
111+
// b 1f
112+
// save x0 and x1 (and also x2 for TYPED_EVENT_CALL)
113+
// set up x0 and x1 (and also x2 for TYPED_EVENT_CALL)
114+
// bl __xray_CustomEvent or __xray_TypedEvent
115+
// restore x0 and x1 (and also x2 for TYPED_EVENT_CALL)
116+
// 1f
117+
//
118+
// There are 6 instructions for EVENT_CALL and 9 for TYPED_EVENT_CALL.
119+
//
120+
// Enable: b .+24 => nop
121+
// Disable: nop => b .+24
108122
bool patchCustomEvent(const bool Enable, const uint32_t FuncId,
109-
const XRaySledEntry &Sled)
110-
XRAY_NEVER_INSTRUMENT { // FIXME: Implement in aarch64?
123+
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
124+
uint32_t Inst = Enable ? 0xd503201f : 0x14000006;
125+
std::atomic_store_explicit(
126+
reinterpret_cast<std::atomic<uint32_t> *>(Sled.address()), Inst,
127+
std::memory_order_release);
111128
return false;
112129
}
113130

131+
// Enable: b +36 => nop
132+
// Disable: nop => b +36
114133
bool patchTypedEvent(const bool Enable, const uint32_t FuncId,
115134
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
116-
// FIXME: Implement in aarch64?
135+
uint32_t Inst = Enable ? 0xd503201f : 0x14000009;
136+
std::atomic_store_explicit(
137+
reinterpret_cast<std::atomic<uint32_t> *>(Sled.address()), Inst,
138+
std::memory_order_release);
117139
return false;
118140
}
119141

compiler-rt/lib/xray/xray_trampoline_AArch64.S

+28
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,32 @@ ASM_SYMBOL(__xray_FunctionTailExit):
103103
RESTORE_REGISTERS
104104
ret
105105

106+
.global ASM_SYMBOL(__xray_CustomEvent)
107+
ASM_HIDDEN(__xray_CustomEvent)
108+
ASM_TYPE_FUNCTION(__xray_CustomEvent)
109+
ASM_SYMBOL(__xray_CustomEvent):
110+
SAVE_REGISTERS
111+
adrp x8, ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)
112+
ldr x8, [x8, #:lo12:ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)]
113+
cbz x8, 1f
114+
blr x8
115+
1:
116+
RESTORE_REGISTERS
117+
ret
118+
ASM_SIZE(__xray_CustomEvent)
119+
120+
.global ASM_SYMBOL(__xray_TypedEvent)
121+
ASM_HIDDEN(__xray_TypedEvent)
122+
ASM_TYPE_FUNCTION(__xray_TypedEvent)
123+
ASM_SYMBOL(__xray_TypedEvent):
124+
SAVE_REGISTERS
125+
adrp x8, ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE)
126+
ldr x8, [x8, #:lo12:ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE)]
127+
cbz x8, 1f
128+
blr x8
129+
1:
130+
RESTORE_REGISTERS
131+
ret
132+
ASM_SIZE(__xray_TypedEvent)
133+
106134
NO_EXEC_STACK_DIRECTIVE

compiler-rt/test/xray/TestCases/Posix/custom-event-logging.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// RUN: %clangxx_xray -std=c++11 -fpic -fpie %s -o %t
66
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_logfile_base=custom-event-logging.xray-" %run %t 2>&1 | FileCheck %s
77
// FIXME: Support this in non-x86_64 as well
8-
// REQUIRES: x86_64-linux
8+
// REQUIRES: target={{(aarch64|x86_64)-.*linux.*}}
99
// REQUIRES: built-in-llvm-tree
1010
#include <cstdio>
1111
#include "xray/xray_interface.h"

compiler-rt/test/xray/TestCases/Posix/typed-event-logging.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %clangxx_xray %s -o %t
22
// RUN: XRAY_OPTIONS=patch_premain=false:verbosity=1 %run %t 2>&1 | FileCheck %s
33

4-
// REQUIRES: target={{x86_64-.*linux.*}}
4+
// REQUIRES: target={{(aarch64|x86_64)-.*linux.*}}
55

66
#include <assert.h>
77
#include <stdio.h>

llvm/lib/CodeGen/SelectionDAG/FastISel.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ bool FastISel::selectPatchpoint(const CallInst *I) {
893893

894894
bool FastISel::selectXRayCustomEvent(const CallInst *I) {
895895
const auto &Triple = TM.getTargetTriple();
896-
if (Triple.getArch() != Triple::x86_64 || !Triple.isOSLinux())
896+
if (Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
897897
return true; // don't do anything to this instruction.
898898
SmallVector<MachineOperand, 8> Ops;
899899
Ops.push_back(MachineOperand::CreateReg(getRegForValue(I->getArgOperand(0)),
@@ -912,7 +912,7 @@ bool FastISel::selectXRayCustomEvent(const CallInst *I) {
912912

913913
bool FastISel::selectXRayTypedEvent(const CallInst *I) {
914914
const auto &Triple = TM.getTargetTriple();
915-
if (Triple.getArch() != Triple::x86_64 || !Triple.isOSLinux())
915+
if (Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
916916
return true; // don't do anything to this instruction.
917917
SmallVector<MachineOperand, 8> Ops;
918918
Ops.push_back(MachineOperand::CreateReg(getRegForValue(I->getArgOperand(0)),

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -7204,10 +7204,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
72047204
}
72057205
case Intrinsic::xray_customevent: {
72067206
// Here we want to make sure that the intrinsic behaves as if it has a
7207-
// specific calling convention, and only for x86_64.
7208-
// FIXME: Support other platforms later.
7207+
// specific calling convention.
72097208
const auto &Triple = DAG.getTarget().getTargetTriple();
7210-
if (Triple.getArch() != Triple::x86_64)
7209+
if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
72117210
return;
72127211

72137212
SmallVector<SDValue, 8> Ops;
@@ -7234,10 +7233,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
72347233
}
72357234
case Intrinsic::xray_typedevent: {
72367235
// Here we want to make sure that the intrinsic behaves as if it has a
7237-
// specific calling convention, and only for x86_64.
7238-
// FIXME: Support other platforms later.
7236+
// specific calling convention.
72397237
const auto &Triple = DAG.getTarget().getTargetTriple();
7240-
if (Triple.getArch() != Triple::x86_64)
7238+
if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
72417239
return;
72427240

72437241
SmallVector<SDValue, 8> Ops;

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

+99
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class AArch64AsmPrinter : public AsmPrinter {
107107
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
108108
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
109109
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
110+
void LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, bool Typed);
110111

111112
typedef std::tuple<unsigned, bool, uint32_t> HwasanMemaccessTuple;
112113
std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
@@ -323,6 +324,100 @@ void AArch64AsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
323324
recordSled(CurSled, MI, Kind, 2);
324325
}
325326

327+
// Emit the following code for Intrinsic::{xray_customevent,xray_typedevent}
328+
// (built-in functions __xray_customevent/__xray_typedevent).
329+
//
330+
// .Lxray_event_sled_N:
331+
// b 1f
332+
// save x0 and x1 (and also x2 for TYPED_EVENT_CALL)
333+
// set up x0 and x1 (and also x2 for TYPED_EVENT_CALL)
334+
// bl __xray_CustomEvent or __xray_TypedEvent
335+
// restore x0 and x1 (and also x2 for TYPED_EVENT_CALL)
336+
// 1:
337+
//
338+
// There are 6 instructions for EVENT_CALL and 9 for TYPED_EVENT_CALL.
339+
//
340+
// Then record a sled of kind CUSTOM_EVENT or TYPED_EVENT.
341+
// After patching, b .+N will become a nop.
342+
void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI,
343+
bool Typed) {
344+
auto &O = *OutStreamer;
345+
MCSymbol *CurSled = OutContext.createTempSymbol("xray_sled_", true);
346+
O.emitLabel(CurSled);
347+
MCInst MovX0Op0 = MCInstBuilder(AArch64::ORRXrs)
348+
.addReg(AArch64::X0)
349+
.addReg(AArch64::XZR)
350+
.addReg(MI.getOperand(0).getReg())
351+
.addImm(0);
352+
MCInst MovX1Op1 = MCInstBuilder(AArch64::ORRXrs)
353+
.addReg(AArch64::X1)
354+
.addReg(AArch64::XZR)
355+
.addReg(MI.getOperand(1).getReg())
356+
.addImm(0);
357+
bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
358+
auto *Sym = MCSymbolRefExpr::create(
359+
OutContext.getOrCreateSymbol(
360+
Twine(MachO ? "_" : "") +
361+
(Typed ? "__xray_TypedEvent" : "__xray_CustomEvent")),
362+
OutContext);
363+
if (Typed) {
364+
O.AddComment("Begin XRay typed event");
365+
EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
366+
EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
367+
.addReg(AArch64::SP)
368+
.addReg(AArch64::X0)
369+
.addReg(AArch64::X1)
370+
.addReg(AArch64::SP)
371+
.addImm(-4));
372+
EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
373+
.addReg(AArch64::X2)
374+
.addReg(AArch64::SP)
375+
.addImm(2));
376+
EmitToStreamer(O, MovX0Op0);
377+
EmitToStreamer(O, MovX1Op1);
378+
EmitToStreamer(O, MCInstBuilder(AArch64::ORRXrs)
379+
.addReg(AArch64::X2)
380+
.addReg(AArch64::XZR)
381+
.addReg(MI.getOperand(2).getReg())
382+
.addImm(0));
383+
EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
384+
EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
385+
.addReg(AArch64::X2)
386+
.addReg(AArch64::SP)
387+
.addImm(2));
388+
O.AddComment("End XRay typed event");
389+
EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
390+
.addReg(AArch64::SP)
391+
.addReg(AArch64::X0)
392+
.addReg(AArch64::X1)
393+
.addReg(AArch64::SP)
394+
.addImm(4));
395+
396+
recordSled(CurSled, MI, SledKind::TYPED_EVENT, 2);
397+
} else {
398+
O.AddComment("Begin XRay custom event");
399+
EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
400+
EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
401+
.addReg(AArch64::SP)
402+
.addReg(AArch64::X0)
403+
.addReg(AArch64::X1)
404+
.addReg(AArch64::SP)
405+
.addImm(-2));
406+
EmitToStreamer(O, MovX0Op0);
407+
EmitToStreamer(O, MovX1Op1);
408+
EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
409+
O.AddComment("End XRay custom event");
410+
EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
411+
.addReg(AArch64::SP)
412+
.addReg(AArch64::X0)
413+
.addReg(AArch64::X1)
414+
.addReg(AArch64::SP)
415+
.addImm(2));
416+
417+
recordSled(CurSled, MI, SledKind::CUSTOM_EVENT, 2);
418+
}
419+
}
420+
326421
void AArch64AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
327422
Register AddrReg = MI.getOperand(0).getReg();
328423
assert(std::next(MI.getIterator())->isCall() &&
@@ -1552,6 +1647,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
15521647
case TargetOpcode::PATCHABLE_TAIL_CALL:
15531648
LowerPATCHABLE_TAIL_CALL(*MI);
15541649
return;
1650+
case TargetOpcode::PATCHABLE_EVENT_CALL:
1651+
return LowerPATCHABLE_EVENT_CALL(*MI, false);
1652+
case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
1653+
return LowerPATCHABLE_EVENT_CALL(*MI, true);
15551654

15561655
case AArch64::KCFI_CHECK:
15571656
LowerKCFI_CHECK(*MI);

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -2757,6 +2757,10 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
27572757
case TargetOpcode::PATCHPOINT:
27582758
return emitPatchPoint(MI, BB);
27592759

2760+
case TargetOpcode::PATCHABLE_EVENT_CALL:
2761+
case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
2762+
return BB;
2763+
27602764
case AArch64::CATCHRET:
27612765
return EmitLoweredCatchRet(MI, BB);
27622766
case AArch64::LD1_MXIPXX_H_PSEUDO_B:

0 commit comments

Comments
 (0)