1 | //===-- hwasan_setjmp_x86_64.S --------------------------------------------===// |
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 | // setjmp interceptor for x86_64. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "sanitizer_common/sanitizer_asm.h" |
14 | |
15 | #if HWASAN_WITH_INTERCEPTORS && defined(__x86_64__) |
16 | #include "sanitizer_common/sanitizer_platform.h" |
17 | |
18 | // We want to save the context of the calling function. |
19 | // That requires |
20 | // 1) No modification of the return address by this function. |
21 | // 2) No modification of the stack pointer by this function. |
22 | // 3) (no modification of any other saved register, but that's not really going |
23 | // to occur, and hence isn't as much of a worry). |
24 | // |
25 | // There's essentially no way to ensure that the compiler will not modify the |
26 | // stack pointer when compiling a C function. |
27 | // Hence we have to write this function in assembly. |
28 | // |
29 | // TODO: Handle Intel CET. |
30 | |
31 | .section .text |
32 | .file "hwasan_setjmp_x86_64.S" |
33 | |
34 | .global ASM_WRAPPER_NAME(setjmp) |
35 | ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(setjmp)) |
36 | ASM_WRAPPER_NAME(setjmp): |
37 | CFI_STARTPROC |
38 | _CET_ENDBR |
39 | xorl %esi, %esi |
40 | jmp .Linterceptor_sigsetjmp |
41 | CFI_ENDPROC |
42 | ASM_SIZE(ASM_WRAPPER_NAME(setjmp)) |
43 | |
44 | .global ASM_WRAPPER_NAME(sigsetjmp) |
45 | ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(sigsetjmp)) |
46 | ASM_WRAPPER_NAME(sigsetjmp): |
47 | .Linterceptor_sigsetjmp: |
48 | CFI_STARTPROC |
49 | _CET_ENDBR |
50 | |
51 | // Save callee save registers. |
52 | mov %rbx, (0*8)(%rdi) |
53 | mov %rbp, (1*8)(%rdi) |
54 | mov %r12, (2*8)(%rdi) |
55 | mov %r13, (3*8)(%rdi) |
56 | mov %r14, (4*8)(%rdi) |
57 | mov %r15, (5*8)(%rdi) |
58 | |
59 | // Save SP as it was in caller's frame. |
60 | lea 8(%rsp), %rdx |
61 | mov %rdx, (6*8)(%rdi) |
62 | |
63 | // Save return address. |
64 | mov (%rsp), %rax |
65 | mov %rax, (7*8)(%rdi) |
66 | |
67 | jmp __sigjmp_save |
68 | |
69 | CFI_ENDPROC |
70 | ASM_SIZE(ASM_WRAPPER_NAME(sigsetjmp)) |
71 | |
72 | ASM_INTERCEPTOR_TRAMPOLINE(sigsetjmp) |
73 | ASM_TRAMPOLINE_ALIAS(__sigsetjmp, sigsetjmp) |
74 | ASM_INTERCEPTOR_TRAMPOLINE(setjmp) |
75 | ASM_TRAMPOLINE_ALIAS(_setjmp, setjmp) |
76 | #endif |
77 | |
78 | // We do not need executable stack. |
79 | NO_EXEC_STACK_DIRECTIVE |
80 | |