1 | //===-- hwasan_exceptions.cpp ---------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file is a part of HWAddressSanitizer. |
10 | // |
11 | // HWAddressSanitizer runtime. |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "hwasan_poisoning.h" |
15 | #include "sanitizer_common/sanitizer_common.h" |
16 | |
17 | #include <unwind.h> |
18 | |
19 | using namespace __hwasan; |
20 | using namespace __sanitizer; |
21 | |
22 | typedef _Unwind_Reason_Code PersonalityFn(int version, _Unwind_Action actions, |
23 | uint64_t exception_class, |
24 | _Unwind_Exception* unwind_exception, |
25 | _Unwind_Context* context); |
26 | |
27 | // Pointers to the _Unwind_GetGR and _Unwind_GetCFA functions are passed in |
28 | // instead of being called directly. This is to handle cases where the unwinder |
29 | // is statically linked and the sanitizer runtime and the program are linked |
30 | // against different unwinders. The _Unwind_Context data structure is opaque so |
31 | // it may be incompatible between unwinders. |
32 | typedef uintptr_t GetGRFn(_Unwind_Context* context, int index); |
33 | typedef uintptr_t GetCFAFn(_Unwind_Context* context); |
34 | |
35 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE _Unwind_Reason_Code |
36 | __hwasan_personality_wrapper(int version, _Unwind_Action actions, |
37 | uint64_t exception_class, |
38 | _Unwind_Exception* unwind_exception, |
39 | _Unwind_Context* context, |
40 | PersonalityFn* real_personality, GetGRFn* get_gr, |
41 | GetCFAFn* get_cfa) { |
42 | _Unwind_Reason_Code rc; |
43 | if (real_personality) |
44 | rc = real_personality(version, actions, exception_class, unwind_exception, |
45 | context); |
46 | else |
47 | rc = _URC_CONTINUE_UNWIND; |
48 | |
49 | // We only untag frames without a landing pad because landing pads are |
50 | // responsible for untagging the stack themselves if they resume. |
51 | // |
52 | // Here we assume that the frame record appears after any locals. This is not |
53 | // required by AAPCS but is a requirement for HWASAN instrumented functions. |
54 | if ((actions & _UA_CLEANUP_PHASE) && rc == _URC_CONTINUE_UNWIND) { |
55 | #if defined(__x86_64__) |
56 | uptr fp = get_gr(context, 6); // rbp |
57 | #elif defined(__aarch64__) |
58 | uptr fp = get_gr(context, 29); // x29 |
59 | #elif SANITIZER_RISCV64 |
60 | uptr fp = get_gr(context, 8); // x8 |
61 | #else |
62 | #error Unsupported architecture |
63 | #endif |
64 | uptr sp = get_cfa(context); |
65 | TagMemory(p: UntagAddr(tagged_addr: sp), size: UntagAddr(tagged_addr: fp) - UntagAddr(tagged_addr: sp), |
66 | tag: GetTagFromPointer(p: sp)); |
67 | } |
68 | |
69 | return rc; |
70 | } |
71 | |