1//===-- xray_trampoline_x86.s -----------------------------------*- ASM -*-===// 2// 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 6// 7//===----------------------------------------------------------------------===// 8// 9// This file is a part of XRay, a dynamic runtime instrumentation system. 10// 11// This implements the X86-specific assembler for the trampolines. 12// 13//===----------------------------------------------------------------------===// 14 15#include "../builtins/assembly.h" 16#include "../sanitizer_common/sanitizer_asm.h" 17 18 19 20.macro SAVE_REGISTERS 21 pushfq 22 subq $240, %rsp 23 CFI_DEF_CFA_OFFSET(248) 24 movq %rbp, 232(%rsp) 25 movupd %xmm0, 216(%rsp) 26 movupd %xmm1, 200(%rsp) 27 movupd %xmm2, 184(%rsp) 28 movupd %xmm3, 168(%rsp) 29 movupd %xmm4, 152(%rsp) 30 movupd %xmm5, 136(%rsp) 31 movupd %xmm6, 120(%rsp) 32 movupd %xmm7, 104(%rsp) 33 movq %rdi, 96(%rsp) 34 movq %rax, 88(%rsp) 35 movq %rdx, 80(%rsp) 36 movq %rsi, 72(%rsp) 37 movq %rcx, 64(%rsp) 38 movq %r8, 56(%rsp) 39 movq %r9, 48(%rsp) 40 movq %r10, 40(%rsp) 41 movq %r11, 32(%rsp) 42 movq %r12, 24(%rsp) 43 movq %r13, 16(%rsp) 44 movq %r14, 8(%rsp) 45 movq %r15, 0(%rsp) 46.endm 47 48.macro RESTORE_REGISTERS 49 movq 232(%rsp), %rbp 50 movupd 216(%rsp), %xmm0 51 movupd 200(%rsp), %xmm1 52 movupd 184(%rsp), %xmm2 53 movupd 168(%rsp), %xmm3 54 movupd 152(%rsp), %xmm4 55 movupd 136(%rsp), %xmm5 56 movupd 120(%rsp) , %xmm6 57 movupd 104(%rsp) , %xmm7 58 movq 96(%rsp), %rdi 59 movq 88(%rsp), %rax 60 movq 80(%rsp), %rdx 61 movq 72(%rsp), %rsi 62 movq 64(%rsp), %rcx 63 movq 56(%rsp), %r8 64 movq 48(%rsp), %r9 65 movq 40(%rsp), %r10 66 movq 32(%rsp), %r11 67 movq 24(%rsp), %r12 68 movq 16(%rsp), %r13 69 movq 8(%rsp), %r14 70 movq 0(%rsp), %r15 71 addq $240, %rsp 72 popfq 73 CFI_DEF_CFA_OFFSET(8) 74.endm 75 76.macro ALIGNED_CALL_RAX 77 // Call the logging handler, after aligning the stack to a 16-byte boundary. 78 // The approach we're taking here uses additional stack space to stash the 79 // stack pointer twice before aligning the pointer to 16-bytes. If the stack 80 // was 8-byte aligned, it will become 16-byte aligned -- when restoring the 81 // pointer, we can always look -8 bytes from the current position to get 82 // either of the values we've stashed in the first place. 83 pushq %rsp 84 pushq (%rsp) 85 andq $-0x10, %rsp 86 callq *%rax 87 movq 8(%rsp), %rsp 88.endm 89 90 .text 91#if !defined(__APPLE__) 92 .section .text 93 .file "xray_trampoline_x86.S" 94#else 95 .section __TEXT,__text 96#endif 97 98//===----------------------------------------------------------------------===// 99 100 .globl ASM_SYMBOL(__xray_FunctionEntry) 101 .align 16, 0x90 102 ASM_TYPE_FUNCTION(__xray_FunctionEntry) 103# LLVM-MCA-BEGIN __xray_FunctionEntry 104ASM_SYMBOL(__xray_FunctionEntry): 105 CFI_STARTPROC 106 SAVE_REGISTERS 107 108 // This load has to be atomic, it's concurrent with __xray_patch(). 109 // On x86/amd64, a simple (type-aligned) MOV instruction is enough. 110 movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax 111 testq %rax, %rax 112 je .Ltmp0 113 114 // The patched function prologue puts its xray_instr_map index into %r10d. 115 movl %r10d, %edi 116 xor %esi,%esi 117 ALIGNED_CALL_RAX 118 119.Ltmp0: 120 RESTORE_REGISTERS 121 retq 122# LLVM-MCA-END 123 ASM_SIZE(__xray_FunctionEntry) 124 CFI_ENDPROC 125 126//===----------------------------------------------------------------------===// 127 128 .globl ASM_SYMBOL(__xray_FunctionExit) 129 .align 16, 0x90 130 ASM_TYPE_FUNCTION(__xray_FunctionExit) 131# LLVM-MCA-BEGIN __xray_FunctionExit 132ASM_SYMBOL(__xray_FunctionExit): 133 CFI_STARTPROC 134 // Save the important registers first. Since we're assuming that this 135 // function is only jumped into, we only preserve the registers for 136 // returning. 137 subq $56, %rsp 138 CFI_DEF_CFA_OFFSET(64) 139 movq %rbp, 48(%rsp) 140 movupd %xmm0, 32(%rsp) 141 movupd %xmm1, 16(%rsp) 142 movq %rax, 8(%rsp) 143 movq %rdx, 0(%rsp) 144 movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax 145 testq %rax,%rax 146 je .Ltmp2 147 148 movl %r10d, %edi 149 movl $1, %esi 150 ALIGNED_CALL_RAX 151 152.Ltmp2: 153 // Restore the important registers. 154 movq 48(%rsp), %rbp 155 movupd 32(%rsp), %xmm0 156 movupd 16(%rsp), %xmm1 157 movq 8(%rsp), %rax 158 movq 0(%rsp), %rdx 159 addq $56, %rsp 160 CFI_DEF_CFA_OFFSET(8) 161 retq 162# LLVM-MCA-END 163 ASM_SIZE(__xray_FunctionExit) 164 CFI_ENDPROC 165 166//===----------------------------------------------------------------------===// 167 168 .globl ASM_SYMBOL(__xray_FunctionTailExit) 169 .align 16, 0x90 170 ASM_TYPE_FUNCTION(__xray_FunctionTailExit) 171# LLVM-MCA-BEGIN __xray_FunctionTailExit 172ASM_SYMBOL(__xray_FunctionTailExit): 173 CFI_STARTPROC 174 SAVE_REGISTERS 175 176 movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax 177 testq %rax,%rax 178 je .Ltmp4 179 180 movl %r10d, %edi 181 movl $2, %esi 182 183 ALIGNED_CALL_RAX 184 185.Ltmp4: 186 RESTORE_REGISTERS 187 retq 188# LLVM-MCA-END 189 ASM_SIZE(__xray_FunctionTailExit) 190 CFI_ENDPROC 191 192//===----------------------------------------------------------------------===// 193 194 .globl ASM_SYMBOL(__xray_ArgLoggerEntry) 195 .align 16, 0x90 196 ASM_TYPE_FUNCTION(__xray_ArgLoggerEntry) 197# LLVM-MCA-BEGIN __xray_ArgLoggerEntry 198ASM_SYMBOL(__xray_ArgLoggerEntry): 199 CFI_STARTPROC 200 SAVE_REGISTERS 201 202 // Again, these function pointer loads must be atomic; MOV is fine. 203 movq ASM_SYMBOL(_ZN6__xray13XRayArgLoggerE)(%rip), %rax 204 testq %rax, %rax 205 jne .Larg1entryLog 206 207 // If [arg1 logging handler] not set, defer to no-arg logging. 208 movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax 209 testq %rax, %rax 210 je .Larg1entryFail 211 212.Larg1entryLog: 213 214 // First argument will become the third 215 movq %rdi, %rdx 216 217 // XRayEntryType::LOG_ARGS_ENTRY into the second 218 mov $0x3, %esi 219 220 // 32-bit function ID becomes the first 221 movl %r10d, %edi 222 ALIGNED_CALL_RAX 223 224.Larg1entryFail: 225 RESTORE_REGISTERS 226 retq 227# LLVM-MCA-END 228 ASM_SIZE(__xray_ArgLoggerEntry) 229 CFI_ENDPROC 230 231//===----------------------------------------------------------------------===// 232 233 .global ASM_SYMBOL(__xray_CustomEvent) 234 .align 16, 0x90 235 ASM_TYPE_FUNCTION(__xray_CustomEvent) 236# LLVM-MCA-BEGIN __xray_CustomEvent 237ASM_SYMBOL(__xray_CustomEvent): 238 CFI_STARTPROC 239 SAVE_REGISTERS 240 241 // We take two arguments to this trampoline, which should be in rdi and rsi 242 // already. 243 movq ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)(%rip), %rax 244 testq %rax,%rax 245 je .LcustomEventCleanup 246 247 ALIGNED_CALL_RAX 248 249.LcustomEventCleanup: 250 RESTORE_REGISTERS 251 retq 252# LLVM-MCA-END 253 ASM_SIZE(__xray_CustomEvent) 254 CFI_ENDPROC 255 256//===----------------------------------------------------------------------===// 257 258 .global ASM_SYMBOL(__xray_TypedEvent) 259 .align 16, 0x90 260 ASM_TYPE_FUNCTION(__xray_TypedEvent) 261# LLVM-MCA-BEGIN __xray_TypedEvent 262ASM_SYMBOL(__xray_TypedEvent): 263 CFI_STARTPROC 264 SAVE_REGISTERS 265 266 // We pass three arguments to this trampoline, which should be in rdi, rsi 267 // and rdx without our intervention. 268 movq ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE)(%rip), %rax 269 testq %rax,%rax 270 je .LtypedEventCleanup 271 272 ALIGNED_CALL_RAX 273 274.LtypedEventCleanup: 275 RESTORE_REGISTERS 276 retq 277# LLVM-MCA-END 278 ASM_SIZE(__xray_TypedEvent) 279 CFI_ENDPROC 280 281//===----------------------------------------------------------------------===// 282 283NO_EXEC_STACK_DIRECTIVE 284