xref: /freebsd/contrib/llvm-project/compiler-rt/lib/xray/xray_trampoline_AArch64.S (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1#include "../builtins/assembly.h"
2
3    .text
4    /* The variable containing the handler function pointer */
5    .global _ZN6__xray19XRayPatchedFunctionE
6    /* Word-aligned function entry point */
7    .p2align 2
8    /* Let C/C++ see the symbol */
9    .global __xray_FunctionEntry
10    .hidden __xray_FunctionEntry
11    .type __xray_FunctionEntry, %function
12    /* In C++ it is void extern "C" __xray_FunctionEntry(uint32_t FuncId) with
13         FuncId passed in W0 register. */
14__xray_FunctionEntry:
15    /* Move the return address beyond the end of sled data. The 12 bytes of
16         data are inserted in the code of the runtime patch, between the call
17         instruction and the instruction returned into. The data contains 32
18         bits of instrumented function ID and 64 bits of the address of
19         the current trampoline. */
20    ADD X30, X30, #12
21    /* Push the registers which may be modified by the handler function */
22    STP X1, X2, [SP, #-16]!
23    STP X3, X4, [SP, #-16]!
24    STP X5, X6, [SP, #-16]!
25    STP X7, X30, [SP, #-16]!
26    STP Q0, Q1, [SP, #-32]!
27    STP Q2, Q3, [SP, #-32]!
28    STP Q4, Q5, [SP, #-32]!
29    STP Q6, Q7, [SP, #-32]!
30    /* X8 is the indirect result register and needs to be preserved for the body
31     of the function to use */
32    STP X8, X0, [SP, #-16]!
33
34    /* Load the page address of _ZN6__xray19XRayPatchedFunctionE into X1 */
35    ADRP X1, _ZN6__xray19XRayPatchedFunctionE
36    /* Load the handler function pointer into X2 */
37    LDR X2, [X1, #:lo12:_ZN6__xray19XRayPatchedFunctionE]
38    /* Handler address is nullptr if handler is not set */
39    CMP X2, #0
40    BEQ FunctionEntry_restore
41    /* Function ID is already in W0 (the first parameter).
42         X1=0 means that we are tracing an entry event */
43    MOV X1, #0
44    /* Call the handler with 2 parameters in W0 and X1 */
45    BLR X2
46FunctionEntry_restore:
47    /* Pop the saved registers */
48    LDP X8, X0, [SP], #16
49    LDP Q6, Q7, [SP], #32
50    LDP Q4, Q5, [SP], #32
51    LDP Q2, Q3, [SP], #32
52    LDP Q0, Q1, [SP], #32
53    LDP X7, X30, [SP], #16
54    LDP X5, X6, [SP], #16
55    LDP X3, X4, [SP], #16
56    LDP X1, X2, [SP], #16
57    RET
58
59    /* Word-aligned function entry point */
60    .p2align 2
61    /* Let C/C++ see the symbol */
62    .global __xray_FunctionExit
63    .hidden __xray_FunctionExit
64    .type __xray_FunctionExit, %function
65    /* In C++ it is void extern "C" __xray_FunctionExit(uint32_t FuncId) with
66         FuncId passed in W0 register. */
67__xray_FunctionExit:
68    /* Move the return address beyond the end of sled data. The 12 bytes of
69         data are inserted in the code of the runtime patch, between the call
70         instruction and the instruction returned into. The data contains 32
71         bits of instrumented function ID and 64 bits of the address of
72         the current trampoline. */
73    ADD X30, X30, #12
74    /* Push the registers which may be modified by the handler function */
75    STP X1, X2, [SP, #-16]!
76    STP X3, X4, [SP, #-16]!
77    STP X5, X6, [SP, #-16]!
78    STP X7, X30, [SP, #-16]!
79    STP Q0, Q1, [SP, #-32]!
80    STP Q2, Q3, [SP, #-32]!
81    STP Q4, Q5, [SP, #-32]!
82    STP Q6, Q7, [SP, #-32]!
83    /* X8 is the indirect result register and needs to be preserved for the body
84     of the function to use */
85    STP X8, X0, [SP, #-16]!
86
87    /* Load the page address of _ZN6__xray19XRayPatchedFunctionE into X1 */
88    ADRP X1, _ZN6__xray19XRayPatchedFunctionE
89    /* Load the handler function pointer into X2 */
90    LDR X2, [X1, #:lo12:_ZN6__xray19XRayPatchedFunctionE]
91    /* Handler address is nullptr if handler is not set */
92    CMP X2, #0
93    BEQ FunctionExit_restore
94    /* Function ID is already in W0 (the first parameter).
95         X1=1 means that we are tracing an exit event */
96    MOV X1, #1
97    /* Call the handler with 2 parameters in W0 and X1 */
98    BLR X2
99FunctionExit_restore:
100    LDP X8, X0, [SP], #16
101    LDP Q6, Q7, [SP], #32
102    LDP Q4, Q5, [SP], #32
103    LDP Q2, Q3, [SP], #32
104    LDP Q0, Q1, [SP], #32
105    LDP X7, X30, [SP], #16
106    LDP X5, X6, [SP], #16
107    LDP X3, X4, [SP], #16
108    LDP X1, X2, [SP], #16
109    RET
110
111    /* Word-aligned function entry point */
112    .p2align 2
113    /* Let C/C++ see the symbol */
114    .global __xray_FunctionTailExit
115    .hidden __xray_FunctionTailExit
116    .type __xray_FunctionTailExit, %function
117    /* In C++ it is void extern "C" __xray_FunctionTailExit(uint32_t FuncId)
118         with FuncId passed in W0 register. */
119__xray_FunctionTailExit:
120    /* Move the return address beyond the end of sled data. The 12 bytes of
121         data are inserted in the code of the runtime patch, between the call
122         instruction and the instruction returned into. The data contains 32
123         bits of instrumented function ID and 64 bits of the address of
124         the current trampoline. */
125    ADD X30, X30, #12
126    /* Push the registers which may be modified by the handler function */
127    STP X1, X2, [SP, #-16]!
128    STP X3, X4, [SP, #-16]!
129    STP X5, X6, [SP, #-16]!
130    STP X7, X30, [SP, #-16]!
131    /* Push the parameters of the tail called function */
132    STP Q0, Q1, [SP, #-32]!
133    STP Q2, Q3, [SP, #-32]!
134    STP Q4, Q5, [SP, #-32]!
135    STP Q6, Q7, [SP, #-32]!
136    /* Load the page address of _ZN6__xray19XRayPatchedFunctionE into X1 */
137    ADRP X1, _ZN6__xray19XRayPatchedFunctionE
138    /* Load the handler function pointer into X2 */
139    LDR X2, [X1, #:lo12:_ZN6__xray19XRayPatchedFunctionE]
140    /* Handler address is nullptr if handler is not set */
141    CMP X2, #0
142    BEQ FunctionTailExit_restore
143    /* Function ID is already in W0 (the first parameter).
144         X1=2 means that we are tracing a tail exit event, but before the
145         logging part of XRay is ready, we pretend that here a normal function
146         exit happens, so we give the handler code 1 */
147    MOV X1, #1
148    /* Call the handler with 2 parameters in W0 and X1 */
149    BLR X2
150FunctionTailExit_restore:
151    /* Pop the parameters of the tail called function */
152    LDP Q6, Q7, [SP], #32
153    LDP Q4, Q5, [SP], #32
154    LDP Q2, Q3, [SP], #32
155    LDP Q0, Q1, [SP], #32
156    /* Pop the registers which may be modified by the handler function */
157    LDP X7, X30, [SP], #16
158    LDP X5, X6, [SP], #16
159    LDP X3, X4, [SP], #16
160    LDP X1, X2, [SP], #16
161    RET
162
163NO_EXEC_STACK_DIRECTIVE
164