2017-03-16 05:18:47 +08:00
|
|
|
#include "../builtins/assembly.h"
|
|
|
|
|
2016-11-21 11:20:43 +08:00
|
|
|
.text
|
|
|
|
/* The variable containing the handler function pointer */
|
|
|
|
.global _ZN6__xray19XRayPatchedFunctionE
|
|
|
|
/* Word-aligned function entry point */
|
|
|
|
.p2align 2
|
|
|
|
/* Let C/C++ see the symbol */
|
|
|
|
.global __xray_FunctionEntry
|
2020-04-22 06:18:23 +08:00
|
|
|
.hidden __xray_FunctionEntry
|
2016-11-21 11:20:43 +08:00
|
|
|
.type __xray_FunctionEntry, %function
|
|
|
|
/* In C++ it is void extern "C" __xray_FunctionEntry(uint32_t FuncId) with
|
|
|
|
FuncId passed in W0 register. */
|
|
|
|
__xray_FunctionEntry:
|
|
|
|
/* Move the return address beyond the end of sled data. The 12 bytes of
|
|
|
|
data are inserted in the code of the runtime patch, between the call
|
|
|
|
instruction and the instruction returned into. The data contains 32
|
|
|
|
bits of instrumented function ID and 64 bits of the address of
|
|
|
|
the current trampoline. */
|
|
|
|
ADD X30, X30, #12
|
|
|
|
/* Push the registers which may be modified by the handler function */
|
|
|
|
STP X1, X2, [SP, #-16]!
|
|
|
|
STP X3, X4, [SP, #-16]!
|
|
|
|
STP X5, X6, [SP, #-16]!
|
|
|
|
STP X7, X30, [SP, #-16]!
|
|
|
|
STP Q0, Q1, [SP, #-32]!
|
|
|
|
STP Q2, Q3, [SP, #-32]!
|
|
|
|
STP Q4, Q5, [SP, #-32]!
|
|
|
|
STP Q6, Q7, [SP, #-32]!
|
2020-04-22 06:44:19 +08:00
|
|
|
/* X8 is the indirect result register and needs to be preserved for the body
|
|
|
|
of the function to use */
|
|
|
|
STP X8, X0, [SP, #-16]!
|
|
|
|
|
2020-04-22 06:37:39 +08:00
|
|
|
/* Load the page address of _ZN6__xray19XRayPatchedFunctionE into X1 */
|
|
|
|
ADRP X1, _ZN6__xray19XRayPatchedFunctionE
|
2016-11-21 11:20:43 +08:00
|
|
|
/* Load the handler function pointer into X2 */
|
2020-04-22 06:37:39 +08:00
|
|
|
LDR X2, [X1, #:lo12:_ZN6__xray19XRayPatchedFunctionE]
|
2016-11-21 11:20:43 +08:00
|
|
|
/* Handler address is nullptr if handler is not set */
|
|
|
|
CMP X2, #0
|
|
|
|
BEQ FunctionEntry_restore
|
|
|
|
/* Function ID is already in W0 (the first parameter).
|
|
|
|
X1=0 means that we are tracing an entry event */
|
|
|
|
MOV X1, #0
|
|
|
|
/* Call the handler with 2 parameters in W0 and X1 */
|
|
|
|
BLR X2
|
|
|
|
FunctionEntry_restore:
|
|
|
|
/* Pop the saved registers */
|
2020-04-22 06:44:19 +08:00
|
|
|
LDP X8, X0, [SP], #16
|
2016-11-21 11:20:43 +08:00
|
|
|
LDP Q6, Q7, [SP], #32
|
|
|
|
LDP Q4, Q5, [SP], #32
|
|
|
|
LDP Q2, Q3, [SP], #32
|
|
|
|
LDP Q0, Q1, [SP], #32
|
|
|
|
LDP X7, X30, [SP], #16
|
|
|
|
LDP X5, X6, [SP], #16
|
|
|
|
LDP X3, X4, [SP], #16
|
|
|
|
LDP X1, X2, [SP], #16
|
|
|
|
RET
|
|
|
|
|
|
|
|
/* Word-aligned function entry point */
|
|
|
|
.p2align 2
|
|
|
|
/* Let C/C++ see the symbol */
|
|
|
|
.global __xray_FunctionExit
|
2020-04-22 06:18:23 +08:00
|
|
|
.hidden __xray_FunctionExit
|
2016-11-21 11:20:43 +08:00
|
|
|
.type __xray_FunctionExit, %function
|
|
|
|
/* In C++ it is void extern "C" __xray_FunctionExit(uint32_t FuncId) with
|
|
|
|
FuncId passed in W0 register. */
|
|
|
|
__xray_FunctionExit:
|
|
|
|
/* Move the return address beyond the end of sled data. The 12 bytes of
|
|
|
|
data are inserted in the code of the runtime patch, between the call
|
|
|
|
instruction and the instruction returned into. The data contains 32
|
|
|
|
bits of instrumented function ID and 64 bits of the address of
|
|
|
|
the current trampoline. */
|
|
|
|
ADD X30, X30, #12
|
|
|
|
/* Push the registers which may be modified by the handler function */
|
|
|
|
STP X1, X2, [SP, #-16]!
|
|
|
|
STP X3, X4, [SP, #-16]!
|
|
|
|
STP X5, X6, [SP, #-16]!
|
|
|
|
STP X7, X30, [SP, #-16]!
|
2020-04-22 06:44:19 +08:00
|
|
|
STP Q0, Q1, [SP, #-32]!
|
|
|
|
STP Q2, Q3, [SP, #-32]!
|
|
|
|
STP Q4, Q5, [SP, #-32]!
|
|
|
|
STP Q6, Q7, [SP, #-32]!
|
|
|
|
/* X8 is the indirect result register and needs to be preserved for the body
|
|
|
|
of the function to use */
|
|
|
|
STP X8, X0, [SP, #-16]!
|
|
|
|
|
2020-04-22 06:37:39 +08:00
|
|
|
/* Load the page address of _ZN6__xray19XRayPatchedFunctionE into X1 */
|
|
|
|
ADRP X1, _ZN6__xray19XRayPatchedFunctionE
|
2016-11-21 11:20:43 +08:00
|
|
|
/* Load the handler function pointer into X2 */
|
2020-04-22 06:37:39 +08:00
|
|
|
LDR X2, [X1, #:lo12:_ZN6__xray19XRayPatchedFunctionE]
|
2016-11-21 11:20:43 +08:00
|
|
|
/* Handler address is nullptr if handler is not set */
|
|
|
|
CMP X2, #0
|
|
|
|
BEQ FunctionExit_restore
|
|
|
|
/* Function ID is already in W0 (the first parameter).
|
|
|
|
X1=1 means that we are tracing an exit event */
|
|
|
|
MOV X1, #1
|
|
|
|
/* Call the handler with 2 parameters in W0 and X1 */
|
|
|
|
BLR X2
|
|
|
|
FunctionExit_restore:
|
2020-04-22 06:44:19 +08:00
|
|
|
LDP X8, X0, [SP], #16
|
|
|
|
LDP Q6, Q7, [SP], #32
|
|
|
|
LDP Q4, Q5, [SP], #32
|
|
|
|
LDP Q2, Q3, [SP], #32
|
|
|
|
LDP Q0, Q1, [SP], #32
|
2016-11-21 11:20:43 +08:00
|
|
|
LDP X7, X30, [SP], #16
|
|
|
|
LDP X5, X6, [SP], #16
|
|
|
|
LDP X3, X4, [SP], #16
|
|
|
|
LDP X1, X2, [SP], #16
|
|
|
|
RET
|
2017-01-26 04:27:19 +08:00
|
|
|
|
|
|
|
/* Word-aligned function entry point */
|
|
|
|
.p2align 2
|
|
|
|
/* Let C/C++ see the symbol */
|
|
|
|
.global __xray_FunctionTailExit
|
2020-04-22 06:18:23 +08:00
|
|
|
.hidden __xray_FunctionTailExit
|
2017-01-26 04:27:19 +08:00
|
|
|
.type __xray_FunctionTailExit, %function
|
|
|
|
/* In C++ it is void extern "C" __xray_FunctionTailExit(uint32_t FuncId)
|
|
|
|
with FuncId passed in W0 register. */
|
|
|
|
__xray_FunctionTailExit:
|
|
|
|
/* Move the return address beyond the end of sled data. The 12 bytes of
|
|
|
|
data are inserted in the code of the runtime patch, between the call
|
|
|
|
instruction and the instruction returned into. The data contains 32
|
|
|
|
bits of instrumented function ID and 64 bits of the address of
|
|
|
|
the current trampoline. */
|
|
|
|
ADD X30, X30, #12
|
|
|
|
/* Push the registers which may be modified by the handler function */
|
|
|
|
STP X1, X2, [SP, #-16]!
|
|
|
|
STP X3, X4, [SP, #-16]!
|
|
|
|
STP X5, X6, [SP, #-16]!
|
|
|
|
STP X7, X30, [SP, #-16]!
|
|
|
|
/* Push the parameters of the tail called function */
|
|
|
|
STP Q0, Q1, [SP, #-32]!
|
|
|
|
STP Q2, Q3, [SP, #-32]!
|
|
|
|
STP Q4, Q5, [SP, #-32]!
|
|
|
|
STP Q6, Q7, [SP, #-32]!
|
2020-04-22 06:37:39 +08:00
|
|
|
/* Load the page address of _ZN6__xray19XRayPatchedFunctionE into X1 */
|
|
|
|
ADRP X1, _ZN6__xray19XRayPatchedFunctionE
|
2017-01-26 04:27:19 +08:00
|
|
|
/* Load the handler function pointer into X2 */
|
2020-04-22 06:37:39 +08:00
|
|
|
LDR X2, [X1, #:lo12:_ZN6__xray19XRayPatchedFunctionE]
|
2017-01-26 04:27:19 +08:00
|
|
|
/* Handler address is nullptr if handler is not set */
|
|
|
|
CMP X2, #0
|
|
|
|
BEQ FunctionTailExit_restore
|
|
|
|
/* Function ID is already in W0 (the first parameter).
|
|
|
|
X1=2 means that we are tracing a tail exit event, but before the
|
|
|
|
logging part of XRay is ready, we pretend that here a normal function
|
|
|
|
exit happens, so we give the handler code 1 */
|
|
|
|
MOV X1, #1
|
|
|
|
/* Call the handler with 2 parameters in W0 and X1 */
|
|
|
|
BLR X2
|
|
|
|
FunctionTailExit_restore:
|
|
|
|
/* Pop the parameters of the tail called function */
|
|
|
|
LDP Q6, Q7, [SP], #32
|
|
|
|
LDP Q4, Q5, [SP], #32
|
|
|
|
LDP Q2, Q3, [SP], #32
|
|
|
|
LDP Q0, Q1, [SP], #32
|
|
|
|
/* Pop the registers which may be modified by the handler function */
|
|
|
|
LDP X7, X30, [SP], #16
|
|
|
|
LDP X5, X6, [SP], #16
|
|
|
|
LDP X3, X4, [SP], #16
|
|
|
|
LDP X1, X2, [SP], #16
|
|
|
|
RET
|
2017-03-16 05:18:47 +08:00
|
|
|
|
|
|
|
NO_EXEC_STACK_DIRECTIVE
|