aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer/sanitizer_common/sanitizer_asm.h
blob: 3af66a4e44998822dc300e308c53f9582cbd4088 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//===-- sanitizer_asm.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Various support for assembler.
//
//===----------------------------------------------------------------------===//

// Some toolchains do not support .cfi asm directives, so we have to hide
// them inside macros.
#if defined(__clang__) ||                                                      \
    (defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM))
  // GCC defined __GCC_HAVE_DWARF2_CFI_ASM if it supports CFI.
  // Clang seems to support CFI by default (or not?).
  // We need two versions of macros: for inline asm and standalone asm files.
# define CFI_INL_ADJUST_CFA_OFFSET(n) ".cfi_adjust_cfa_offset " #n ";"

# define CFI_STARTPROC .cfi_startproc
# define CFI_ENDPROC .cfi_endproc
# define CFI_ADJUST_CFA_OFFSET(n) .cfi_adjust_cfa_offset n
# define CFI_DEF_CFA_OFFSET(n) .cfi_def_cfa_offset n
# define CFI_REL_OFFSET(reg, n) .cfi_rel_offset reg, n
# define CFI_OFFSET(reg, n) .cfi_offset reg, n
# define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
# define CFI_DEF_CFA(reg, n) .cfi_def_cfa reg, n
# define CFI_RESTORE(reg) .cfi_restore reg

#else  // No CFI
# define CFI_INL_ADJUST_CFA_OFFSET(n)
# define CFI_STARTPROC
# define CFI_ENDPROC
# define CFI_ADJUST_CFA_OFFSET(n)
# define CFI_DEF_CFA_OFFSET(n)
# define CFI_REL_OFFSET(reg, n)
# define CFI_OFFSET(reg, n)
# define CFI_DEF_CFA_REGISTER(reg)
# define CFI_DEF_CFA(reg, n)
# define CFI_RESTORE(reg)
#endif

#if defined(__x86_64__) || defined(__i386__) || defined(__sparc__)
# define ASM_TAIL_CALL jmp
#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
    defined(__powerpc__) || defined(__loongarch_lp64)
# define ASM_TAIL_CALL b
#elif defined(__s390__)
# define ASM_TAIL_CALL jg
#elif defined(__riscv)
# define ASM_TAIL_CALL tail
#endif

// Currently, almost all of the shared libraries rely on the value of
// $t9 to get the address of current function, instead of PCREL, even
// on MIPSr6. To be compatiable with them, we have to set $t9 properly.
// MIPS uses GOT to get the address of preemptible functions.
#if defined(__mips64)
#  define C_ASM_TAIL_CALL(t_func, i_func)                       \
    "lui $t8, %hi(%neg(%gp_rel(" t_func ")))\n"                 \
    "daddu $t8, $t8, $t9\n"                                     \
    "daddiu $t8, $t8, %lo(%neg(%gp_rel(" t_func ")))\n"         \
    "ld $t9, %got_disp(" i_func ")($t8)\n"                      \
    "jr $t9\n"
#elif defined(__mips__)
#  define C_ASM_TAIL_CALL(t_func, i_func)                       \
    ".set    noreorder\n"                                       \
    ".cpload $t9\n"                                             \
    ".set    reorder\n"                                         \
    "lw $t9, %got(" i_func ")($gp)\n"                           \
    "jr $t9\n"
#elif defined(ASM_TAIL_CALL)
#  define C_ASM_TAIL_CALL(t_func, i_func)                       \
    SANITIZER_STRINGIFY(ASM_TAIL_CALL) " " i_func
#endif

#if defined(__ELF__) && defined(__x86_64__) || defined(__i386__) || \
    defined(__riscv)
# define ASM_PREEMPTIBLE_SYM(sym) sym@plt
#else
# define ASM_PREEMPTIBLE_SYM(sym) sym
#endif

#if !defined(__APPLE__)
# define ASM_HIDDEN(symbol) .hidden symbol
# if defined(__arm__) || defined(__aarch64__)
#  define ASM_TYPE_FUNCTION(symbol) .type symbol, %function
# else
#  define ASM_TYPE_FUNCTION(symbol) .type symbol, @function
# endif
# define ASM_SIZE(symbol) .size symbol, .-symbol
# define ASM_SYMBOL(symbol) symbol
# define ASM_SYMBOL_INTERCEPTOR(symbol) symbol
# if defined(__i386__) || defined(__powerpc__) || defined(__s390__) || \
     defined(__sparc__)
// For details, see interception.h
#  define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
#  define ASM_TRAMPOLINE_ALIAS(symbol, name)                                   \
         .weak symbol;                                                         \
         .set symbol, ASM_WRAPPER_NAME(name)
#  define ASM_INTERCEPTOR_TRAMPOLINE(name)
#  define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 0
# else  // Architecture supports interceptor trampoline
// Keep trampoline implementation in sync with interception/interception.h
#  define ASM_WRAPPER_NAME(symbol) ___interceptor_##symbol
#  define ASM_TRAMPOLINE_ALIAS(symbol, name)                                   \
         .weak symbol;                                                         \
         .set symbol, __interceptor_trampoline_##name
#  define ASM_INTERCEPTOR_TRAMPOLINE(name)                                     \
         .weak __interceptor_##name;                                           \
         .set __interceptor_##name, ASM_WRAPPER_NAME(name);                    \
         .globl __interceptor_trampoline_##name;                               \
         ASM_TYPE_FUNCTION(__interceptor_trampoline_##name);                   \
         __interceptor_trampoline_##name:                                      \
                 CFI_STARTPROC;                                                \
                 ASM_TAIL_CALL ASM_PREEMPTIBLE_SYM(__interceptor_##name);      \
                 CFI_ENDPROC;                                                  \
         ASM_SIZE(__interceptor_trampoline_##name)
#  define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 1
# endif  // Architecture supports interceptor trampoline
#else
# define ASM_HIDDEN(symbol)
# define ASM_TYPE_FUNCTION(symbol)
# define ASM_SIZE(symbol)
# define ASM_SYMBOL(symbol) _##symbol
# define ASM_SYMBOL_INTERCEPTOR(symbol) _wrap_##symbol
# define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
#endif

#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
                         defined(__Fuchsia__) || defined(__linux__))
// clang-format off
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
// clang-format on
#else
#define NO_EXEC_STACK_DIRECTIVE
#endif

#if (defined(__x86_64__) || defined(__i386__)) && defined(__has_include) && __has_include(<cet.h>)
#include <cet.h>
#endif
#ifndef _CET_ENDBR
#define _CET_ENDBR
#endif