]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/hwasan/hwasan_checks.h
Merge LLVM libunwind trunk r351319, from just before upstream's
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / hwasan / hwasan_checks.h
1 //===-- hwasan_checks.h -----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of HWAddressSanitizer.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef HWASAN_CHECKS_H
15 #define HWASAN_CHECKS_H
16
17 #include "hwasan_mapping.h"
18
19 namespace __hwasan {
20 template <unsigned X>
21 __attribute__((always_inline)) static void SigTrap(uptr p) {
22 #if defined(__aarch64__)
23   (void)p;
24   // 0x900 is added to do not interfere with the kernel use of lower values of
25   // brk immediate.
26   // FIXME: Add a constraint to put the pointer into x0, the same as x86 branch.
27   asm("brk %0\n\t" ::"n"(0x900 + X));
28 #elif defined(__x86_64__)
29   // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes
30   // total. The pointer is passed via rdi.
31   // 0x40 is added as a safeguard, to help distinguish our trap from others and
32   // to avoid 0 offsets in the command (otherwise it'll be reduced to a
33   // different nop command, the three bytes one).
34   asm volatile(
35       "int3\n"
36       "nopl %c0(%%rax)\n" ::"n"(0x40 + X),
37       "D"(p));
38 #else
39   // FIXME: not always sigill.
40   __builtin_trap();
41 #endif
42   // __builtin_unreachable();
43 }
44
45 enum class ErrorAction { Abort, Recover };
46 enum class AccessType { Load, Store };
47
48 template <ErrorAction EA, AccessType AT, unsigned LogSize>
49 __attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) {
50   tag_t ptr_tag = GetTagFromPointer(p);
51   uptr ptr_raw = p & ~kAddressTagMask;
52   tag_t mem_tag = *(tag_t *)MemToShadow(ptr_raw);
53   if (UNLIKELY(ptr_tag != mem_tag)) {
54     SigTrap<0x20 * (EA == ErrorAction::Recover) +
55             0x10 * (AT == AccessType::Store) + LogSize>(p);
56     if (EA == ErrorAction::Abort)
57       __builtin_unreachable();
58   }
59 }
60
61 template <ErrorAction EA, AccessType AT>
62 __attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
63                                                                       uptr sz) {
64   if (sz == 0)
65     return;
66   tag_t ptr_tag = GetTagFromPointer(p);
67   uptr ptr_raw = p & ~kAddressTagMask;
68   tag_t *shadow_first = (tag_t *)MemToShadow(ptr_raw);
69   tag_t *shadow_last = (tag_t *)MemToShadow(ptr_raw + sz - 1);
70   for (tag_t *t = shadow_first; t <= shadow_last; ++t)
71     if (UNLIKELY(ptr_tag != *t)) {
72       SigTrap<0x20 * (EA == ErrorAction::Recover) +
73               0x10 * (AT == AccessType::Store) + 0xf>(p);
74       if (EA == ErrorAction::Abort)
75         __builtin_unreachable();
76     }
77 }
78 }  // end namespace __hwasan
79
80 #endif  // HWASAN_CHECKS_H