1 //===-- xray_trampoline_x86.s -----------------------------------*- ASM -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of XRay, a dynamic runtime instrumentation system.
11 // This implements the X86-specific assembler for the trampolines.
13 //===----------------------------------------------------------------------===//
15 #include "../builtins/assembly.h"
16 #include "../sanitizer_common/sanitizer_asm.h"
18 // XRay trampolines which are not produced by intrinsics are not System V AMD64
19 // ABI compliant because they are called with a stack that is always misaligned
20 // by 8 bytes with respect to a 16 bytes alignment. This is because they are
21 // called immediately after the call to, or immediately before returning from,
22 // the function being instrumented. This saves space in the patch point, but
23 // misaligns the stack by 8 bytes.
25 .macro ALIGN_STACK_16B
26 #if defined(__APPLE__)
31 CFI_ADJUST_CFA_OFFSET(8)
34 .macro RESTORE_STACK_ALIGNMENT
35 #if defined(__APPLE__)
40 CFI_ADJUST_CFA_OFFSET(-8)
43 // This macro should lower the stack pointer by an odd multiple of 8.
46 CFI_ADJUST_CFA_OFFSET(8)
48 CFI_ADJUST_CFA_OFFSET(240)
50 movupd %xmm0, 216(%rsp)
51 movupd %xmm1, 200(%rsp)
52 movupd %xmm2, 184(%rsp)
53 movupd %xmm3, 168(%rsp)
54 movupd %xmm4, 152(%rsp)
55 movupd %xmm5, 136(%rsp)
56 movupd %xmm6, 120(%rsp)
57 movupd %xmm7, 104(%rsp)
73 .macro RESTORE_REGISTERS
75 movupd 216(%rsp), %xmm0
76 movupd 200(%rsp), %xmm1
77 movupd 184(%rsp), %xmm2
78 movupd 168(%rsp), %xmm3
79 movupd 152(%rsp), %xmm4
80 movupd 136(%rsp), %xmm5
81 movupd 120(%rsp) , %xmm6
82 movupd 104(%rsp) , %xmm7
97 CFI_ADJUST_CFA_OFFSET(-240)
99 CFI_ADJUST_CFA_OFFSET(-8)
103 #if !defined(__APPLE__)
105 .file "xray_trampoline_x86.S"
107 .section __TEXT,__text
110 .macro LOAD_HANDLER_ADDR handler
111 #if !defined(XRAY_PIC)
112 movq ASM_SYMBOL(\handler)(%rip), %rax
114 movq ASM_SYMBOL(\handler)@GOTPCREL(%rip), %rax
120 //===----------------------------------------------------------------------===//
122 .globl ASM_SYMBOL(__xray_FunctionEntry)
123 ASM_HIDDEN(__xray_FunctionEntry)
125 ASM_TYPE_FUNCTION(__xray_FunctionEntry)
126 # LLVM-MCA-BEGIN __xray_FunctionEntry
127 ASM_SYMBOL(__xray_FunctionEntry):
132 // This load has to be atomic, it's concurrent with __xray_patch().
133 // On x86/amd64, a simple (type-aligned) MOV instruction is enough.
134 LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE
138 // The patched function prologue puts its xray_instr_map index into %r10d.
144 RESTORE_STACK_ALIGNMENT
148 ASM_SIZE(__xray_FunctionEntry)
151 //===----------------------------------------------------------------------===//
153 .globl ASM_SYMBOL(__xray_FunctionExit)
154 ASM_HIDDEN(__xray_FunctionExit)
156 ASM_TYPE_FUNCTION(__xray_FunctionExit)
157 # LLVM-MCA-BEGIN __xray_FunctionExit
158 ASM_SYMBOL(__xray_FunctionExit):
162 // Save the important registers first. Since we're assuming that this
163 // function is only jumped into, we only preserve the registers for
166 CFI_ADJUST_CFA_OFFSET(64)
168 movupd %xmm0, 32(%rsp)
169 movupd %xmm1, 16(%rsp)
172 LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE
181 // Restore the important registers.
183 movupd 32(%rsp), %xmm0
184 movupd 16(%rsp), %xmm1
188 CFI_ADJUST_CFA_OFFSET(-64)
190 RESTORE_STACK_ALIGNMENT
193 ASM_SIZE(__xray_FunctionExit)
196 //===----------------------------------------------------------------------===//
198 .globl ASM_SYMBOL(__xray_FunctionTailExit)
199 ASM_HIDDEN(__xray_FunctionTailExit)
201 ASM_TYPE_FUNCTION(__xray_FunctionTailExit)
202 # LLVM-MCA-BEGIN __xray_FunctionTailExit
203 ASM_SYMBOL(__xray_FunctionTailExit):
208 LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE
217 RESTORE_STACK_ALIGNMENT
221 ASM_SIZE(__xray_FunctionTailExit)
224 //===----------------------------------------------------------------------===//
226 .globl ASM_SYMBOL(__xray_ArgLoggerEntry)
227 ASM_HIDDEN(__xray_ArgLoggerEntry)
229 ASM_TYPE_FUNCTION(__xray_ArgLoggerEntry)
230 # LLVM-MCA-BEGIN __xray_ArgLoggerEntry
231 ASM_SYMBOL(__xray_ArgLoggerEntry):
236 // Again, these function pointer loads must be atomic; MOV is fine.
237 LOAD_HANDLER_ADDR _ZN6__xray13XRayArgLoggerE
239 jne LOCAL_LABEL(arg1entryLog)
241 // If [arg1 logging handler] not set, defer to no-arg logging.
242 LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE
244 je LOCAL_LABEL(arg1entryFail)
246 LOCAL_LABEL(arg1entryLog):
248 // First argument will become the third
251 // XRayEntryType::LOG_ARGS_ENTRY into the second
254 // 32-bit function ID becomes the first
259 LOCAL_LABEL(arg1entryFail):
260 RESTORE_STACK_ALIGNMENT
264 ASM_SIZE(__xray_ArgLoggerEntry)
267 //===----------------------------------------------------------------------===//
269 // __xray_*Event have default visibility so that they can be referenced by user
270 // DSOs that do not link against the runtime.
271 .global ASM_SYMBOL(__xray_CustomEvent)
273 ASM_TYPE_FUNCTION(__xray_CustomEvent)
274 # LLVM-MCA-BEGIN __xray_CustomEvent
275 ASM_SYMBOL(__xray_CustomEvent):
279 // We take two arguments to this trampoline, which should be in rdi and rsi
281 LOAD_HANDLER_ADDR _ZN6__xray22XRayPatchedCustomEventE
283 je LOCAL_LABEL(customEventCleanup)
287 LOCAL_LABEL(customEventCleanup):
291 ASM_SIZE(__xray_CustomEvent)
294 //===----------------------------------------------------------------------===//
296 .global ASM_SYMBOL(__xray_TypedEvent)
298 ASM_TYPE_FUNCTION(__xray_TypedEvent)
299 # LLVM-MCA-BEGIN __xray_TypedEvent
300 ASM_SYMBOL(__xray_TypedEvent):
304 // We pass three arguments to this trampoline, which should be in rdi, rsi
305 // and rdx without our intervention.
306 LOAD_HANDLER_ADDR _ZN6__xray21XRayPatchedTypedEventE
308 je LOCAL_LABEL(typedEventCleanup)
312 LOCAL_LABEL(typedEventCleanup):
316 ASM_SIZE(__xray_TypedEvent)
319 //===----------------------------------------------------------------------===//
321 NO_EXEC_STACK_DIRECTIVE