1#include "sanitizer_common/sanitizer_asm.h" 2#include "builtins/assembly.h" 3 4// The content of this file is AArch64-only: 5#if defined(__aarch64__) 6 7// The responsibility of the HWASan entry point in compiler-rt is to primarily 8// readjust the stack from the callee and save the current register values to 9// the stack. 10// This entry point function should be called from a __hwasan_check_* symbol. 11// These are generated during a lowering pass in the backend, and are found in 12// AArch64AsmPrinter::EmitHwasanMemaccessSymbols(). Please look there for 13// further information. 14// The __hwasan_check_* caller of this function should have expanded the stack 15// and saved the previous values of x0, x1, x29, and x30. This function will 16// "consume" these saved values and treats it as part of its own stack frame. 17// In this sense, the __hwasan_check_* callee and this function "share" a stack 18// frame. This allows us to omit having unwinding information (.cfi_*) present 19// in every __hwasan_check_* function, therefore reducing binary size. This is 20// particularly important as hwasan_check_* instances are duplicated in every 21// translation unit where HWASan is enabled. 22// This function calls HwasanTagMismatch to step back into the C++ code that 23// completes the stack unwinding and error printing. This function is is not 24// permitted to return. 25 26 27// Frame from __hwasan_check_: 28// | ... | 29// | ... | 30// | Previous stack frames... | 31// +=================================+ 32// | Unused 8-bytes for maintaining | 33// | 16-byte SP alignment. | 34// +---------------------------------+ 35// | Return address (x30) for caller | 36// | of __hwasan_check_*. | 37// +---------------------------------+ 38// | Frame address (x29) for caller | 39// | of __hwasan_check_* | 40// +---------------------------------+ <-- [SP + 232] 41// | ... | 42// | | 43// | Stack frame space for x2 - x28. | 44// | | 45// | ... | 46// +---------------------------------+ <-- [SP + 16] 47// | | 48// | Saved x1, as __hwasan_check_* | 49// | clobbers it. | 50// +---------------------------------+ 51// | Saved x0, likewise above. | 52// +---------------------------------+ <-- [x30 / SP] 53 54// This function takes two arguments: 55// * x0: The data address. 56// * x1: The encoded access info for the failing access. 57 58// This function has two entry points. The first, __hwasan_tag_mismatch, is used 59// by clients that were compiled without short tag checks (i.e. binaries built 60// by older compilers and binaries targeting older runtimes). In this case the 61// outlined tag check will be missing the code handling short tags (which won't 62// be used in the binary's own stack variables but may be used on the heap 63// or stack variables in other binaries), so the check needs to be done here. 64// 65// The second, __hwasan_tag_mismatch_v2, is used by binaries targeting newer 66// runtimes. This entry point bypasses the short tag check since it will have 67// already been done as part of the outlined tag check. Since tag mismatches are 68// uncommon, there isn't a significant performance benefit to being able to 69// bypass the check; the main benefits are that we can sometimes avoid 70// clobbering the x17 register in error reports, and that the program will have 71// a runtime dependency on the __hwasan_tag_mismatch_v2 symbol therefore it will 72// fail to start up given an older (i.e. incompatible) runtime. 73.section .text 74.file "hwasan_tag_mismatch_aarch64.S" 75.global __hwasan_tag_mismatch 76.type __hwasan_tag_mismatch, %function 77__hwasan_tag_mismatch: 78 BTI_J 79 80 // Compute the granule position one past the end of the access. 81 mov x16, #1 82 and x17, x1, #0xf 83 lsl x16, x16, x17 84 and x17, x0, #0xf 85 add x17, x16, x17 86 87 // Load the shadow byte again and check whether it is a short tag within the 88 // range of the granule position computed above. 89 ubfx x16, x0, #4, #52 90 ldrb w16, [x9, x16] 91 cmp w16, #0xf 92 b.hi __hwasan_tag_mismatch_v2 93 cmp w16, w17 94 b.lo __hwasan_tag_mismatch_v2 95 96 // Load the real tag from the last byte of the granule and compare against 97 // the pointer tag. 98 orr x16, x0, #0xf 99 ldrb w16, [x16] 100 cmp x16, x0, lsr #56 101 b.ne __hwasan_tag_mismatch_v2 102 103 // Restore x0, x1 and sp to their values from before the __hwasan_tag_mismatch 104 // call and resume execution. 105 ldp x0, x1, [sp], #256 106 ret 107 108.global __hwasan_tag_mismatch_v2 109.type __hwasan_tag_mismatch_v2, %function 110__hwasan_tag_mismatch_v2: 111 CFI_STARTPROC 112 BTI_J 113 114 // Set the CFA to be the return address for caller of __hwasan_check_*. Note 115 // that we do not emit CFI predicates to describe the contents of this stack 116 // frame, as this proxy entry point should never be debugged. The contents 117 // are static and are handled by the unwinder after calling 118 // __hwasan_tag_mismatch. The frame pointer is already correctly setup 119 // by __hwasan_check_*. 120 add x29, sp, #232 121 CFI_DEF_CFA(w29, 24) 122 CFI_OFFSET(w30, -16) 123 CFI_OFFSET(w29, -24) 124 125 // Save the rest of the registers into the preallocated space left by 126 // __hwasan_check. 127 str x28, [sp, #224] 128 stp x26, x27, [sp, #208] 129 stp x24, x25, [sp, #192] 130 stp x22, x23, [sp, #176] 131 stp x20, x21, [sp, #160] 132 stp x18, x19, [sp, #144] 133 stp x16, x17, [sp, #128] 134 stp x14, x15, [sp, #112] 135 stp x12, x13, [sp, #96] 136 stp x10, x11, [sp, #80] 137 stp x8, x9, [sp, #64] 138 stp x6, x7, [sp, #48] 139 stp x4, x5, [sp, #32] 140 stp x2, x3, [sp, #16] 141 142 // Pass the address of the frame to __hwasan_tag_mismatch4, so that it can 143 // extract the saved registers from this frame without having to worry about 144 // finding this frame. 145 mov x2, sp 146 147 bl __hwasan_tag_mismatch4 148 CFI_ENDPROC 149 150.Lfunc_end0: 151 .size __hwasan_tag_mismatch, .Lfunc_end0-__hwasan_tag_mismatch 152 153#endif // defined(__aarch64__) 154 155// We do not need executable stack. 156NO_EXEC_STACK_DIRECTIVE 157 158GNU_PROPERTY_BTI_PAC 159