mirror of
https://github.com/autc04/Retro68.git
synced 2024-06-14 00:29:39 +00:00
159 lines
6.0 KiB
ArmAsm
159 lines
6.0 KiB
ArmAsm
#include "sanitizer_common/sanitizer_asm.h"
|
|
#include "builtins/assembly.h"
|
|
|
|
// The content of this file is AArch64-only:
|
|
#if defined(__aarch64__)
|
|
|
|
// 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
|
|
// AArch64AsmPrinter::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 x0, x1, x29, and x30. 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.
|
|
|
|
|
|
// Frame from __hwasan_check_:
|
|
// | ... |
|
|
// | ... |
|
|
// | Previous stack frames... |
|
|
// +=================================+
|
|
// | Unused 8-bytes for maintaining |
|
|
// | 16-byte SP alignment. |
|
|
// +---------------------------------+
|
|
// | Return address (x30) for caller |
|
|
// | of __hwasan_check_*. |
|
|
// +---------------------------------+
|
|
// | Frame address (x29) for caller |
|
|
// | of __hwasan_check_* |
|
|
// +---------------------------------+ <-- [SP + 232]
|
|
// | ... |
|
|
// | |
|
|
// | Stack frame space for x2 - x28. |
|
|
// | |
|
|
// | ... |
|
|
// +---------------------------------+ <-- [SP + 16]
|
|
// | |
|
|
// | Saved x1, as __hwasan_check_* |
|
|
// | clobbers it. |
|
|
// +---------------------------------+
|
|
// | Saved x0, likewise above. |
|
|
// +---------------------------------+ <-- [x30 / SP]
|
|
|
|
// This function takes two arguments:
|
|
// * x0: The data address.
|
|
// * x1: The encoded access info for the failing access.
|
|
|
|
// This function has two entry points. The first, __hwasan_tag_mismatch, is used
|
|
// by clients that were compiled without short tag checks (i.e. binaries built
|
|
// by older compilers and binaries targeting older runtimes). In this case the
|
|
// outlined tag check will be missing the code handling short tags (which won't
|
|
// be used in the binary's own stack variables but may be used on the heap
|
|
// or stack variables in other binaries), so the check needs to be done here.
|
|
//
|
|
// The second, __hwasan_tag_mismatch_v2, is used by binaries targeting newer
|
|
// runtimes. This entry point bypasses the short tag check since it will have
|
|
// already been done as part of the outlined tag check. Since tag mismatches are
|
|
// uncommon, there isn't a significant performance benefit to being able to
|
|
// bypass the check; the main benefits are that we can sometimes avoid
|
|
// clobbering the x17 register in error reports, and that the program will have
|
|
// a runtime dependency on the __hwasan_tag_mismatch_v2 symbol therefore it will
|
|
// fail to start up given an older (i.e. incompatible) runtime.
|
|
.section .text
|
|
.file "hwasan_tag_mismatch_aarch64.S"
|
|
.global __hwasan_tag_mismatch
|
|
.type __hwasan_tag_mismatch, %function
|
|
__hwasan_tag_mismatch:
|
|
BTI_J
|
|
|
|
// Compute the granule position one past the end of the access.
|
|
mov x16, #1
|
|
and x17, x1, #0xf
|
|
lsl x16, x16, x17
|
|
and x17, x0, #0xf
|
|
add x17, x16, x17
|
|
|
|
// Load the shadow byte again and check whether it is a short tag within the
|
|
// range of the granule position computed above.
|
|
ubfx x16, x0, #4, #52
|
|
ldrb w16, [x9, x16]
|
|
cmp w16, #0xf
|
|
b.hi __hwasan_tag_mismatch_v2
|
|
cmp w16, w17
|
|
b.lo __hwasan_tag_mismatch_v2
|
|
|
|
// Load the real tag from the last byte of the granule and compare against
|
|
// the pointer tag.
|
|
orr x16, x0, #0xf
|
|
ldrb w16, [x16]
|
|
cmp x16, x0, lsr #56
|
|
b.ne __hwasan_tag_mismatch_v2
|
|
|
|
// Restore x0, x1 and sp to their values from before the __hwasan_tag_mismatch
|
|
// call and resume execution.
|
|
ldp x0, x1, [sp], #256
|
|
ret
|
|
|
|
.global __hwasan_tag_mismatch_v2
|
|
.type __hwasan_tag_mismatch_v2, %function
|
|
__hwasan_tag_mismatch_v2:
|
|
CFI_STARTPROC
|
|
BTI_J
|
|
|
|
// 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_*.
|
|
add x29, sp, #232
|
|
CFI_DEF_CFA(w29, 24)
|
|
CFI_OFFSET(w30, -16)
|
|
CFI_OFFSET(w29, -24)
|
|
|
|
// Save the rest of the registers into the preallocated space left by
|
|
// __hwasan_check.
|
|
str x28, [sp, #224]
|
|
stp x26, x27, [sp, #208]
|
|
stp x24, x25, [sp, #192]
|
|
stp x22, x23, [sp, #176]
|
|
stp x20, x21, [sp, #160]
|
|
stp x18, x19, [sp, #144]
|
|
stp x16, x17, [sp, #128]
|
|
stp x14, x15, [sp, #112]
|
|
stp x12, x13, [sp, #96]
|
|
stp x10, x11, [sp, #80]
|
|
stp x8, x9, [sp, #64]
|
|
stp x6, x7, [sp, #48]
|
|
stp x4, x5, [sp, #32]
|
|
stp x2, x3, [sp, #16]
|
|
|
|
// 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.
|
|
mov x2, sp
|
|
|
|
bl __hwasan_tag_mismatch4
|
|
CFI_ENDPROC
|
|
|
|
.Lfunc_end0:
|
|
.size __hwasan_tag_mismatch, .Lfunc_end0-__hwasan_tag_mismatch
|
|
|
|
#endif // defined(__aarch64__)
|
|
|
|
// We do not need executable stack.
|
|
NO_EXEC_STACK_DIRECTIVE
|
|
|
|
GNU_PROPERTY_BTI_PAC
|