| #include "sanitizer_common/sanitizer_asm.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 address of read/write instruction that caused HWASan check fail. |
| // * x1: The tag size. |
| |
| .section .text |
| .file "hwasan_tag_mismatch_aarch64.S" |
| .global __hwasan_tag_mismatch |
| .type __hwasan_tag_mismatch, %function |
| __hwasan_tag_mismatch: |
| 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_*. |
| add x29, sp, #232 |
| CFI_DEF_CFA(w29, 16) |
| CFI_OFFSET(w30, -8) |
| CFI_OFFSET(w29, -16) |
| |
| // 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_mismatch_stub, 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_mismatch_stub |
| 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 |