Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[RISC-V][HWASAN] Add tag mismatch routines for HWASAN required for RI…
…SC-V Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D131341
- Loading branch information
1 parent
ab68929
commit f8b71a3
Showing
4 changed files
with
233 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
//===-- hwasan_setjmp_riscv64.S -------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file is a part of HWAddressSanitizer. | ||
// setjmp interceptor for risc-v. | ||
// HWAddressSanitizer runtime. | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "sanitizer_common/sanitizer_asm.h" | ||
#include "builtins/assembly.h" | ||
|
||
#if HWASAN_WITH_INTERCEPTORS && defined(__riscv) && (__riscv_xlen == 64) | ||
#include "sanitizer_common/sanitizer_platform.h" | ||
|
||
// We want to save the context of the calling function. | ||
// That requires | ||
// 1) No modification of the link register by this function. | ||
// 2) No modification of the stack pointer by this function. | ||
// 3) (no modification of any other saved register, but that's not really going | ||
// to occur, and hence isn't as much of a worry). | ||
// | ||
// There's essentially no way to ensure that the compiler will not modify the | ||
// stack pointer when compiling a C function. | ||
// Hence we have to write this function in assembly. | ||
|
||
.section .text | ||
.file "hwasan_setjmp_riscv64.S" | ||
|
||
.global __interceptor_setjmp | ||
ASM_TYPE_FUNCTION(__interceptor_setjmp) | ||
__interceptor_setjmp: | ||
CFI_STARTPROC | ||
addi x11, x0, 0 | ||
j __interceptor_sigsetjmp | ||
CFI_ENDPROC | ||
ASM_SIZE(__interceptor_setjmp) | ||
|
||
.global __interceptor_sigsetjmp | ||
ASM_TYPE_FUNCTION(__interceptor_sigsetjmp) | ||
__interceptor_sigsetjmp: | ||
CFI_STARTPROC | ||
sd ra, 0<<3(x10) | ||
sd s0, 1<<3(x10) | ||
sd s1, 2<<3(x10) | ||
sd s2, 3<<3(x10) | ||
sd s3, 4<<3(x10) | ||
sd s4, 5<<3(x10) | ||
sd s5, 6<<3(x10) | ||
sd s6, 7<<3(x10) | ||
sd s7, 8<<3(x10) | ||
sd s8, 9<<3(x10) | ||
sd s9, 10<<3(x10) | ||
sd s10, 11<<3(x10) | ||
sd s11, 12<<3(x10) | ||
sd sp, 13<<3(x10) | ||
#if __riscv_float_abi_double | ||
fsd fs0, 14<<3(x10) | ||
fsd fs1, 15<<3(x10) | ||
fsd fs2, 16<<3(x10) | ||
fsd fs3, 17<<3(x10) | ||
fsd fs4, 18<<3(x10) | ||
fsd fs5, 19<<3(x10) | ||
fsd fs6, 20<<3(x10) | ||
fsd fs7, 21<<3(x10) | ||
fsd fs8, 22<<3(x10) | ||
fsd fs9, 23<<3(x10) | ||
fsd fs10, 24<<3(x10) | ||
fsd fs11, 25<<3(x10) | ||
#elif __riscv_float_abi_soft | ||
#else | ||
# error "Unsupported case" | ||
#endif | ||
// We always have the second argument to __sigjmp_save (savemask) set, since | ||
// the _setjmp function above has set it for us as `false`. | ||
// This function is defined in hwasan_interceptors.cc | ||
tail __sigjmp_save | ||
CFI_ENDPROC | ||
ASM_SIZE(__interceptor_sigsetjmp) | ||
|
||
|
||
.macro WEAK_ALIAS first second | ||
.weak \second | ||
.equ \second\(), \first | ||
.endm | ||
|
||
WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp | ||
|
||
WEAK_ALIAS __interceptor_setjmp, _setjmp | ||
#endif | ||
|
||
// We do not need executable stack. | ||
NO_EXEC_STACK_DIRECTIVE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#include "sanitizer_common/sanitizer_asm.h" | ||
|
||
// The content of this file is RISCV64-only: | ||
#if defined(__riscv) && (__riscv_xlen == 64) | ||
|
||
// The responsibility of the HWASan entry point in compiler-rt is to primarily | ||
// readjust the stack from the callee and save the current register values to | ||
// the stack. | ||
// This entry point function should be called from a __hwasan_check_* symbol. | ||
// These are generated during a lowering pass in the backend, and are found in | ||
// RISCVAsmPrinter::EmitHwasanMemaccessSymbols(). Please look there for | ||
// further information. | ||
// The __hwasan_check_* caller of this function should have expanded the stack | ||
// and saved the previous values of x10(arg0), x11(arg1), x1(ra), and x8(fp). | ||
// This function will "consume" these saved values and treats it as part of its | ||
// own stack frame. In this sense, the __hwasan_check_* callee and this function | ||
// "share" a stack frame. This allows us to omit having unwinding information | ||
// (.cfi_*) present in every __hwasan_check_* function, therefore reducing binary size. | ||
// This is particularly important as hwasan_check_* instances are duplicated in every | ||
// translation unit where HWASan is enabled. | ||
// This function calls HwasanTagMismatch to step back into the C++ code that | ||
// completes the stack unwinding and error printing. This function is is not | ||
// permitted to return. | ||
|
||
|
||
// | ... | | ||
// | ... | | ||
// | Previous stack frames... | | ||
// +=================================+ | ||
// | ... | | ||
// | | | ||
// | Stack frame space for x12 - x31.| | ||
// | | | ||
// | ... | | ||
// +---------------------------------+ <-- [SP + 96] | ||
// | Saved x11(arg1), as | | ||
// | __hwasan_check_* clobbers it. | | ||
// +---------------------------------+ <-- [SP + 88] | ||
// | Saved x10(arg0), as | | ||
// | __hwasan_check_* clobbers it. | | ||
// +---------------------------------+ <-- [SP + 80] | ||
// | | | ||
// | Stack frame space for x9. | | ||
// +---------------------------------+ <-- [SP + 72] | ||
// | | | ||
// | Saved x8(fp), as | | ||
// | __hwasan_check_* clobbers it. | | ||
// +---------------------------------+ <-- [SP + 64] | ||
// | ... | | ||
// | | | ||
// | Stack frame space for x2 - x7. | | ||
// | | | ||
// | ... | | ||
// +---------------------------------+ <-- [SP + 16] | ||
// | Return address (x1) for caller | | ||
// | of __hwasan_check_*. | | ||
// +---------------------------------+ <-- [SP + 8] | ||
// | Reserved place for x0, possibly | | ||
// | junk, since we don't save it. | | ||
// +---------------------------------+ <-- [x2 / SP] | ||
|
||
// This function takes two arguments: | ||
// * x10/a0: The data address. | ||
// * x11/a1: The encoded access info for the failing access. | ||
|
||
.section .text | ||
.file "hwasan_tag_mismatch_riscv64.S" | ||
|
||
.global __hwasan_tag_mismatch_v2 | ||
ASM_TYPE_FUNCTION(__hwasan_tag_mismatch_v2) | ||
__hwasan_tag_mismatch_v2: | ||
CFI_STARTPROC | ||
|
||
// Set the CFA to be the return address for caller of __hwasan_check_*. Note | ||
// that we do not emit CFI predicates to describe the contents of this stack | ||
// frame, as this proxy entry point should never be debugged. The contents | ||
// are static and are handled by the unwinder after calling | ||
// __hwasan_tag_mismatch. The frame pointer is already correctly setup | ||
// by __hwasan_check_*. | ||
addi fp, sp, 256 | ||
CFI_DEF_CFA(fp, 0) | ||
CFI_OFFSET(ra, -248) | ||
CFI_OFFSET(fp, -192) | ||
|
||
// Save the rest of the registers into the preallocated space left by | ||
// __hwasan_check. | ||
sd x31, 248(sp) | ||
sd x30, 240(sp) | ||
sd x29, 232(sp) | ||
sd x28, 224(sp) | ||
sd x27, 216(sp) | ||
sd x26, 208(sp) | ||
sd x25, 200(sp) | ||
sd x24, 192(sp) | ||
sd x23, 184(sp) | ||
sd x22, 176(sp) | ||
sd x21, 168(sp) | ||
sd x20, 160(sp) | ||
sd x19, 152(sp) | ||
sd x18, 144(sp) | ||
sd x17, 136(sp) | ||
sd x16, 128(sp) | ||
sd x15, 120(sp) | ||
sd x14, 112(sp) | ||
sd x13, 104(sp) | ||
sd x12, 96(sp) | ||
// sd x11, 88(sp) ; already saved | ||
// sd x10, 80(sp) ; already saved | ||
sd x9, 72(sp) | ||
// sd x8, 64(sp) ; already saved | ||
sd x7, 56(sp) | ||
sd x6, 48(sp) | ||
sd x5, 40(sp) | ||
sd x4, 32(sp) | ||
sd x3, 24(sp) | ||
sd x2, 16(sp) | ||
// sd x1, 8(sp) ; already saved | ||
// sd x0, 0(sp) ; don't store zero register | ||
|
||
// Pass the address of the frame to __hwasan_tag_mismatch4, so that it can | ||
// extract the saved registers from this frame without having to worry about | ||
// finding this frame. | ||
mv x12, sp | ||
|
||
call __hwasan_tag_mismatch4 | ||
CFI_ENDPROC | ||
ASM_SIZE(__hwasan_tag_mismatch_v2) | ||
|
||
#endif // defined(__riscv) && (__riscv_xlen == 64) | ||
|
||
// We do not need executable stack. | ||
NO_EXEC_STACK_DIRECTIVE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters