10b57cec5SDimitry Andric //===-- sanitizer_asm.h -----------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 9349cc55cSDimitry Andric // Various support for assembler. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric // Some toolchains do not support .cfi asm directives, so we have to hide 140b57cec5SDimitry Andric // them inside macros. 150b57cec5SDimitry Andric #if defined(__clang__) || \ 160b57cec5SDimitry Andric (defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)) 170b57cec5SDimitry Andric // GCC defined __GCC_HAVE_DWARF2_CFI_ASM if it supports CFI. 180b57cec5SDimitry Andric // Clang seems to support CFI by default (or not?). 190b57cec5SDimitry Andric // We need two versions of macros: for inline asm and standalone asm files. 200b57cec5SDimitry Andric # define CFI_INL_ADJUST_CFA_OFFSET(n) ".cfi_adjust_cfa_offset " #n ";" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric # define CFI_STARTPROC .cfi_startproc 230b57cec5SDimitry Andric # define CFI_ENDPROC .cfi_endproc 240b57cec5SDimitry Andric # define CFI_ADJUST_CFA_OFFSET(n) .cfi_adjust_cfa_offset n 250b57cec5SDimitry Andric # define CFI_DEF_CFA_OFFSET(n) .cfi_def_cfa_offset n 260b57cec5SDimitry Andric # define CFI_REL_OFFSET(reg, n) .cfi_rel_offset reg, n 270b57cec5SDimitry Andric # define CFI_OFFSET(reg, n) .cfi_offset reg, n 280b57cec5SDimitry Andric # define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg 290b57cec5SDimitry Andric # define CFI_DEF_CFA(reg, n) .cfi_def_cfa reg, n 300b57cec5SDimitry Andric # define CFI_RESTORE(reg) .cfi_restore reg 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric #else // No CFI 330b57cec5SDimitry Andric # define CFI_INL_ADJUST_CFA_OFFSET(n) 340b57cec5SDimitry Andric # define CFI_STARTPROC 350b57cec5SDimitry Andric # define CFI_ENDPROC 360b57cec5SDimitry Andric # define CFI_ADJUST_CFA_OFFSET(n) 370b57cec5SDimitry Andric # define CFI_DEF_CFA_OFFSET(n) 380b57cec5SDimitry Andric # define CFI_REL_OFFSET(reg, n) 390b57cec5SDimitry Andric # define CFI_OFFSET(reg, n) 400b57cec5SDimitry Andric # define CFI_DEF_CFA_REGISTER(reg) 410b57cec5SDimitry Andric # define CFI_DEF_CFA(reg, n) 420b57cec5SDimitry Andric # define CFI_RESTORE(reg) 430b57cec5SDimitry Andric #endif 440b57cec5SDimitry Andric 45*0fca6ea1SDimitry Andric #if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT) 46*0fca6ea1SDimitry Andric # define ASM_STARTPROC CFI_STARTPROC; hint #34 47*0fca6ea1SDimitry Andric # define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC) "\nhint #34" 48*0fca6ea1SDimitry Andric #else 49*0fca6ea1SDimitry Andric # define ASM_STARTPROC CFI_STARTPROC 50*0fca6ea1SDimitry Andric # define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC) 51*0fca6ea1SDimitry Andric #endif 52*0fca6ea1SDimitry Andric #define ASM_ENDPROC CFI_ENDPROC 53*0fca6ea1SDimitry Andric #define C_ASM_ENDPROC SANITIZER_STRINGIFY(CFI_ENDPROC) 54*0fca6ea1SDimitry Andric 5506c3fb27SDimitry Andric #if defined(__x86_64__) || defined(__i386__) || defined(__sparc__) 5606c3fb27SDimitry Andric # define ASM_TAIL_CALL jmp 5706c3fb27SDimitry Andric #elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \ 5806c3fb27SDimitry Andric defined(__powerpc__) || defined(__loongarch_lp64) 5906c3fb27SDimitry Andric # define ASM_TAIL_CALL b 6006c3fb27SDimitry Andric #elif defined(__s390__) 6106c3fb27SDimitry Andric # define ASM_TAIL_CALL jg 6206c3fb27SDimitry Andric #elif defined(__riscv) 6306c3fb27SDimitry Andric # define ASM_TAIL_CALL tail 6406c3fb27SDimitry Andric #endif 6506c3fb27SDimitry Andric 667a6dacacSDimitry Andric // Currently, almost all of the shared libraries rely on the value of 677a6dacacSDimitry Andric // $t9 to get the address of current function, instead of PCREL, even 687a6dacacSDimitry Andric // on MIPSr6. To be compatiable with them, we have to set $t9 properly. 697a6dacacSDimitry Andric // MIPS uses GOT to get the address of preemptible functions. 707a6dacacSDimitry Andric #if defined(__mips64) 717a6dacacSDimitry Andric # define C_ASM_TAIL_CALL(t_func, i_func) \ 727a6dacacSDimitry Andric "lui $t8, %hi(%neg(%gp_rel(" t_func ")))\n" \ 737a6dacacSDimitry Andric "daddu $t8, $t8, $t9\n" \ 747a6dacacSDimitry Andric "daddiu $t8, $t8, %lo(%neg(%gp_rel(" t_func ")))\n" \ 757a6dacacSDimitry Andric "ld $t9, %got_disp(" i_func ")($t8)\n" \ 767a6dacacSDimitry Andric "jr $t9\n" 777a6dacacSDimitry Andric #elif defined(__mips__) 787a6dacacSDimitry Andric # define C_ASM_TAIL_CALL(t_func, i_func) \ 797a6dacacSDimitry Andric ".set noreorder\n" \ 807a6dacacSDimitry Andric ".cpload $t9\n" \ 817a6dacacSDimitry Andric ".set reorder\n" \ 827a6dacacSDimitry Andric "lw $t9, %got(" i_func ")($gp)\n" \ 837a6dacacSDimitry Andric "jr $t9\n" 847a6dacacSDimitry Andric #elif defined(ASM_TAIL_CALL) 857a6dacacSDimitry Andric # define C_ASM_TAIL_CALL(t_func, i_func) \ 867a6dacacSDimitry Andric SANITIZER_STRINGIFY(ASM_TAIL_CALL) " " i_func 877a6dacacSDimitry Andric #endif 887a6dacacSDimitry Andric 8906c3fb27SDimitry Andric #if defined(__ELF__) && defined(__x86_64__) || defined(__i386__) || \ 9006c3fb27SDimitry Andric defined(__riscv) 9106c3fb27SDimitry Andric # define ASM_PREEMPTIBLE_SYM(sym) sym@plt 9206c3fb27SDimitry Andric #else 9306c3fb27SDimitry Andric # define ASM_PREEMPTIBLE_SYM(sym) sym 9406c3fb27SDimitry Andric #endif 9506c3fb27SDimitry Andric 960b57cec5SDimitry Andric #if !defined(__APPLE__) 970b57cec5SDimitry Andric # define ASM_HIDDEN(symbol) .hidden symbol 985f757f3fSDimitry Andric # if defined(__arm__) || defined(__aarch64__) 990b57cec5SDimitry Andric # define ASM_TYPE_FUNCTION(symbol) .type symbol, %function 1005f757f3fSDimitry Andric # else 1015f757f3fSDimitry Andric # define ASM_TYPE_FUNCTION(symbol) .type symbol, @function 1025f757f3fSDimitry Andric # endif 1030b57cec5SDimitry Andric # define ASM_SIZE(symbol) .size symbol, .-symbol 1040b57cec5SDimitry Andric # define ASM_SYMBOL(symbol) symbol 1050b57cec5SDimitry Andric # define ASM_SYMBOL_INTERCEPTOR(symbol) symbol 10606c3fb27SDimitry Andric # if defined(__i386__) || defined(__powerpc__) || defined(__s390__) || \ 10706c3fb27SDimitry Andric defined(__sparc__) 10806c3fb27SDimitry Andric // For details, see interception.h 1090b57cec5SDimitry Andric # define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol 11006c3fb27SDimitry Andric # define ASM_TRAMPOLINE_ALIAS(symbol, name) \ 11106c3fb27SDimitry Andric .weak symbol; \ 11206c3fb27SDimitry Andric .set symbol, ASM_WRAPPER_NAME(name) 11306c3fb27SDimitry Andric # define ASM_INTERCEPTOR_TRAMPOLINE(name) 11406c3fb27SDimitry Andric # define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 0 11506c3fb27SDimitry Andric # else // Architecture supports interceptor trampoline 11606c3fb27SDimitry Andric // Keep trampoline implementation in sync with interception/interception.h 11706c3fb27SDimitry Andric # define ASM_WRAPPER_NAME(symbol) ___interceptor_##symbol 11806c3fb27SDimitry Andric # define ASM_TRAMPOLINE_ALIAS(symbol, name) \ 11906c3fb27SDimitry Andric .weak symbol; \ 12006c3fb27SDimitry Andric .set symbol, __interceptor_trampoline_##name 12106c3fb27SDimitry Andric # define ASM_INTERCEPTOR_TRAMPOLINE(name) \ 12206c3fb27SDimitry Andric .weak __interceptor_##name; \ 12306c3fb27SDimitry Andric .set __interceptor_##name, ASM_WRAPPER_NAME(name); \ 12406c3fb27SDimitry Andric .globl __interceptor_trampoline_##name; \ 12506c3fb27SDimitry Andric ASM_TYPE_FUNCTION(__interceptor_trampoline_##name); \ 12606c3fb27SDimitry Andric __interceptor_trampoline_##name: \ 127*0fca6ea1SDimitry Andric ASM_STARTPROC; \ 12806c3fb27SDimitry Andric ASM_TAIL_CALL ASM_PREEMPTIBLE_SYM(__interceptor_##name); \ 129*0fca6ea1SDimitry Andric ASM_ENDPROC; \ 13006c3fb27SDimitry Andric ASM_SIZE(__interceptor_trampoline_##name) 13106c3fb27SDimitry Andric # define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 1 13206c3fb27SDimitry Andric # endif // Architecture supports interceptor trampoline 1330b57cec5SDimitry Andric #else 1340b57cec5SDimitry Andric # define ASM_HIDDEN(symbol) 1350b57cec5SDimitry Andric # define ASM_TYPE_FUNCTION(symbol) 1360b57cec5SDimitry Andric # define ASM_SIZE(symbol) 1370b57cec5SDimitry Andric # define ASM_SYMBOL(symbol) _##symbol 1380b57cec5SDimitry Andric # define ASM_SYMBOL_INTERCEPTOR(symbol) _wrap_##symbol 1390b57cec5SDimitry Andric # define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol 1400b57cec5SDimitry Andric #endif 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric #if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \ 1430b57cec5SDimitry Andric defined(__Fuchsia__) || defined(__linux__)) 14468d75effSDimitry Andric // clang-format off 145349cc55cSDimitry Andric #define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits 14668d75effSDimitry Andric // clang-format on 1470b57cec5SDimitry Andric #else 1480b57cec5SDimitry Andric #define NO_EXEC_STACK_DIRECTIVE 1490b57cec5SDimitry Andric #endif 150349cc55cSDimitry Andric 151349cc55cSDimitry Andric #if (defined(__x86_64__) || defined(__i386__)) && defined(__has_include) && __has_include(<cet.h>) 152349cc55cSDimitry Andric #include <cet.h> 153349cc55cSDimitry Andric #endif 154349cc55cSDimitry Andric #ifndef _CET_ENDBR 155349cc55cSDimitry Andric #define _CET_ENDBR 156349cc55cSDimitry Andric #endif 157