Skip to content

Commit

Permalink
[RISC-V][HWASAN] Add tag mismatch routines for HWASAN required for RI…
Browse files Browse the repository at this point in the history
…SC-V

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D131341
  • Loading branch information
spacemonkeydelivers committed Aug 28, 2022
1 parent ab68929 commit f8b71a3
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 0 deletions.
2 changes: 2 additions & 0 deletions compiler-rt/lib/hwasan/CMakeLists.txt
Expand Up @@ -16,8 +16,10 @@ set(HWASAN_RTL_SOURCES
hwasan_poisoning.cpp
hwasan_report.cpp
hwasan_setjmp_aarch64.S
hwasan_setjmp_riscv64.S
hwasan_setjmp_x86_64.S
hwasan_tag_mismatch_aarch64.S
hwasan_tag_mismatch_riscv64.S
hwasan_thread.cpp
hwasan_thread_list.cpp
hwasan_type_test.cpp
Expand Down
97 changes: 97 additions & 0 deletions compiler-rt/lib/hwasan/hwasan_setjmp_riscv64.S
@@ -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
132 changes: 132 additions & 0 deletions compiler-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S
@@ -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
2 changes: 2 additions & 0 deletions llvm/utils/gn/secondary/compiler-rt/lib/hwasan/BUILD.gn
Expand Up @@ -68,8 +68,10 @@ source_set("sources") {
"hwasan_report.cpp",
"hwasan_report.h",
"hwasan_setjmp_aarch64.S",
"hwasan_setjmp_riscv64.S",
"hwasan_setjmp_x86_64.S",
"hwasan_tag_mismatch_aarch64.S",
"hwasan_tag_mismatch_riscv64.S",
"hwasan_thread.cpp",
"hwasan_thread.h",
"hwasan_thread_list.cpp",
Expand Down

0 comments on commit f8b71a3

Please sign in to comment.