1 | #include "sanitizer_common/sanitizer_asm.h" |
2 | |
3 | // The content of this file is RISCV64-only: |
4 | #if defined(__riscv) && (__riscv_xlen == 64) |
5 | |
6 | // The responsibility of the HWASan entry point in compiler-rt is to primarily |
7 | // readjust the stack from the callee and save the current register values to |
8 | // the stack. |
9 | // This entry point function should be called from a __hwasan_check_* symbol. |
10 | // These are generated during a lowering pass in the backend, and are found in |
11 | // RISCVAsmPrinter::EmitHwasanMemaccessSymbols(). Please look there for |
12 | // further information. |
13 | // The __hwasan_check_* caller of this function should have expanded the stack |
14 | // and saved the previous values of x10(arg0), x11(arg1), x1(ra), and x8(fp). |
15 | // This function will "consume" these saved values and treats it as part of its |
16 | // own stack frame. In this sense, the __hwasan_check_* callee and this function |
17 | // "share" a stack frame. This allows us to omit having unwinding information |
18 | // (.cfi_*) present in every __hwasan_check_* function, therefore reducing binary size. |
19 | // This is particularly important as hwasan_check_* instances are duplicated in every |
20 | // translation unit where HWASan is enabled. |
21 | // This function calls HwasanTagMismatch to step back into the C++ code that |
22 | // completes the stack unwinding and error printing. This function is is not |
23 | // permitted to return. |
24 | |
25 | |
26 | // | ... | |
27 | // | ... | |
28 | // | Previous stack frames... | |
29 | // +=================================+ |
30 | // | ... | |
31 | // | | |
32 | // | Stack frame space for x12 - x31.| |
33 | // | | |
34 | // | ... | |
35 | // +---------------------------------+ <-- [SP + 96] |
36 | // | Saved x11(arg1), as | |
37 | // | __hwasan_check_* clobbers it. | |
38 | // +---------------------------------+ <-- [SP + 88] |
39 | // | Saved x10(arg0), as | |
40 | // | __hwasan_check_* clobbers it. | |
41 | // +---------------------------------+ <-- [SP + 80] |
42 | // | | |
43 | // | Stack frame space for x9. | |
44 | // +---------------------------------+ <-- [SP + 72] |
45 | // | | |
46 | // | Saved x8(fp), as | |
47 | // | __hwasan_check_* clobbers it. | |
48 | // +---------------------------------+ <-- [SP + 64] |
49 | // | ... | |
50 | // | | |
51 | // | Stack frame space for x2 - x7. | |
52 | // | | |
53 | // | ... | |
54 | // +---------------------------------+ <-- [SP + 16] |
55 | // | Return address (x1) for caller | |
56 | // | of __hwasan_check_*. | |
57 | // +---------------------------------+ <-- [SP + 8] |
58 | // | Reserved place for x0, possibly | |
59 | // | junk, since we don't save it. | |
60 | // +---------------------------------+ <-- [x2 / SP] |
61 | |
62 | // This function takes two arguments: |
63 | // * x10/a0: The data address. |
64 | // * x11/a1: The encoded access info for the failing access. |
65 | |
66 | .section .text |
67 | .file "hwasan_tag_mismatch_riscv64.S" |
68 | |
69 | .global __hwasan_tag_mismatch_v2 |
70 | ASM_TYPE_FUNCTION(__hwasan_tag_mismatch_v2) |
71 | __hwasan_tag_mismatch_v2: |
72 | CFI_STARTPROC |
73 | |
74 | // Set the CFA to be the return address for caller of __hwasan_check_*. Note |
75 | // that we do not emit CFI predicates to describe the contents of this stack |
76 | // frame, as this proxy entry point should never be debugged. The contents |
77 | // are static and are handled by the unwinder after calling |
78 | // __hwasan_tag_mismatch. The frame pointer is already correctly setup |
79 | // by __hwasan_check_*. |
80 | addi fp, sp, 256 |
81 | CFI_DEF_CFA(fp, 0) |
82 | CFI_OFFSET(ra, -248) |
83 | CFI_OFFSET(fp, -192) |
84 | |
85 | // Save the rest of the registers into the preallocated space left by |
86 | // __hwasan_check. |
87 | sd x31, 248(sp) |
88 | sd x30, 240(sp) |
89 | sd x29, 232(sp) |
90 | sd x28, 224(sp) |
91 | sd x27, 216(sp) |
92 | sd x26, 208(sp) |
93 | sd x25, 200(sp) |
94 | sd x24, 192(sp) |
95 | sd x23, 184(sp) |
96 | sd x22, 176(sp) |
97 | sd x21, 168(sp) |
98 | sd x20, 160(sp) |
99 | sd x19, 152(sp) |
100 | sd x18, 144(sp) |
101 | sd x17, 136(sp) |
102 | sd x16, 128(sp) |
103 | sd x15, 120(sp) |
104 | sd x14, 112(sp) |
105 | sd x13, 104(sp) |
106 | sd x12, 96(sp) |
107 | // sd x11, 88(sp) ; already saved |
108 | // sd x10, 80(sp) ; already saved |
109 | sd x9, 72(sp) |
110 | // sd x8, 64(sp) ; already saved |
111 | sd x7, 56(sp) |
112 | sd x6, 48(sp) |
113 | sd x5, 40(sp) |
114 | sd x4, 32(sp) |
115 | sd x3, 24(sp) |
116 | sd x2, 16(sp) |
117 | // sd x1, 8(sp) ; already saved |
118 | // sd x0, 0(sp) ; don't store zero register |
119 | |
120 | // Pass the address of the frame to __hwasan_tag_mismatch4, so that it can |
121 | // extract the saved registers from this frame without having to worry about |
122 | // finding this frame. |
123 | mv x12, sp |
124 | |
125 | call __hwasan_tag_mismatch4 |
126 | CFI_ENDPROC |
127 | ASM_SIZE(__hwasan_tag_mismatch_v2) |
128 | |
129 | #endif // defined(__riscv) && (__riscv_xlen == 64) |
130 | |
131 | // We do not need executable stack. |
132 | NO_EXEC_STACK_DIRECTIVE |
133 | |