1 | //===-- dfsan_platform.h ----------------------------------------*- C++ -*-===// |
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 DataFlowSanitizer. |
10 | // |
11 | // Platform specific information for DFSan. |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef DFSAN_PLATFORM_H |
15 | #define DFSAN_PLATFORM_H |
16 | |
17 | #include "sanitizer_common/sanitizer_common.h" |
18 | #include "sanitizer_common/sanitizer_platform.h" |
19 | |
20 | namespace __dfsan { |
21 | |
22 | using __sanitizer::uptr; |
23 | |
24 | // TODO: The memory mapping code to setup a 1:1 shadow is based on msan. |
25 | // Consider refactoring these into a shared implementation. |
26 | |
27 | struct MappingDesc { |
28 | uptr start; |
29 | uptr end; |
30 | enum Type { |
31 | INVALID = 1, |
32 | ALLOCATOR = 2, |
33 | APP = 4, |
34 | SHADOW = 8, |
35 | ORIGIN = 16, |
36 | } type; |
37 | const char *name; |
38 | }; |
39 | |
40 | // Note: MappingDesc::ALLOCATOR entries are only used to check for memory |
41 | // layout compatibility. The actual allocation settings are in |
42 | // dfsan_allocator.cpp, which need to be kept in sync. |
43 | #if SANITIZER_LINUX && SANITIZER_WORDSIZE == 64 |
44 | |
45 | # if defined(__aarch64__) |
46 | // The mapping assumes 48-bit VMA. AArch64 maps: |
47 | // - 0x0000000000000-0x0100000000000: 39/42/48-bits program own segments |
48 | // - 0x0a00000000000-0x0b00000000000: 48-bits PIE program segments |
49 | // Ideally, this would extend to 0x0c00000000000 (2^45 bytes - the |
50 | // maximum ASLR region for 48-bit VMA) but it is too hard to fit in |
51 | // the larger app/shadow/origin regions. |
52 | // - 0x0e00000000000-0x1000000000000: 48-bits libraries segments |
53 | const MappingDesc kMemoryLayout[] = { |
54 | {0X0000000000000, 0X0100000000000, MappingDesc::APP, "app-10-13" }, |
55 | {0X0100000000000, 0X0200000000000, MappingDesc::SHADOW, "shadow-14" }, |
56 | {0X0200000000000, 0X0300000000000, MappingDesc::INVALID, "invalid" }, |
57 | {0X0300000000000, 0X0400000000000, MappingDesc::ORIGIN, "origin-14" }, |
58 | {0X0400000000000, 0X0600000000000, MappingDesc::SHADOW, "shadow-15" }, |
59 | {0X0600000000000, 0X0800000000000, MappingDesc::ORIGIN, "origin-15" }, |
60 | {0X0800000000000, 0X0A00000000000, MappingDesc::INVALID, "invalid" }, |
61 | {0X0A00000000000, 0X0B00000000000, MappingDesc::APP, "app-14" }, |
62 | {0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13" }, |
63 | {0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid" }, |
64 | {0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13" }, |
65 | {0X0E00000000000, 0X0E40000000000, MappingDesc::ALLOCATOR, "allocator" }, |
66 | {0X0E40000000000, 0X1000000000000, MappingDesc::APP, "app-15" }, |
67 | }; |
68 | # define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL) |
69 | # define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL) |
70 | |
71 | # else |
72 | // All of the following configurations are supported. |
73 | // ASLR disabled: main executable and DSOs at 0x555550000000 |
74 | // PIE and ASLR: main executable and DSOs at 0x7f0000000000 |
75 | // non-PIE: main executable below 0x100000000, DSOs at 0x7f0000000000 |
76 | // Heap at 0x700000000000. |
77 | const MappingDesc kMemoryLayout[] = { |
78 | {.start: 0x000000000000ULL, .end: 0x010000000000ULL, .type: MappingDesc::APP, .name: "app-1" }, |
79 | {.start: 0x010000000000ULL, .end: 0x100000000000ULL, .type: MappingDesc::SHADOW, .name: "shadow-2" }, |
80 | {.start: 0x100000000000ULL, .end: 0x110000000000ULL, .type: MappingDesc::INVALID, .name: "invalid" }, |
81 | {.start: 0x110000000000ULL, .end: 0x200000000000ULL, .type: MappingDesc::ORIGIN, .name: "origin-2" }, |
82 | {.start: 0x200000000000ULL, .end: 0x300000000000ULL, .type: MappingDesc::SHADOW, .name: "shadow-3" }, |
83 | {.start: 0x300000000000ULL, .end: 0x400000000000ULL, .type: MappingDesc::ORIGIN, .name: "origin-3" }, |
84 | {.start: 0x400000000000ULL, .end: 0x500000000000ULL, .type: MappingDesc::INVALID, .name: "invalid" }, |
85 | {.start: 0x500000000000ULL, .end: 0x510000000000ULL, .type: MappingDesc::SHADOW, .name: "shadow-1" }, |
86 | {.start: 0x510000000000ULL, .end: 0x600000000000ULL, .type: MappingDesc::APP, .name: "app-2" }, |
87 | {.start: 0x600000000000ULL, .end: 0x610000000000ULL, .type: MappingDesc::ORIGIN, .name: "origin-1" }, |
88 | {.start: 0x610000000000ULL, .end: 0x700000000000ULL, .type: MappingDesc::INVALID, .name: "invalid" }, |
89 | {.start: 0x700000000000ULL, .end: 0x740000000000ULL, .type: MappingDesc::ALLOCATOR, .name: "allocator" }, |
90 | {.start: 0x740000000000ULL, .end: 0x800000000000ULL, .type: MappingDesc::APP, .name: "app-3" }}; |
91 | # define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL) |
92 | # define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL) |
93 | # endif |
94 | |
95 | #else |
96 | # error "Unsupported platform" |
97 | #endif |
98 | |
99 | const uptr kMemoryLayoutSize = sizeof(kMemoryLayout) / sizeof(kMemoryLayout[0]); |
100 | |
101 | #define MEM_TO_ORIGIN(mem) (SHADOW_TO_ORIGIN(MEM_TO_SHADOW((mem)))) |
102 | |
103 | #ifndef __clang__ |
104 | __attribute__((optimize("unroll-loops" ))) |
105 | #endif |
106 | inline bool |
107 | addr_is_type(uptr addr, int mapping_types) { |
108 | // It is critical for performance that this loop is unrolled (because then it is |
109 | // simplified into just a few constant comparisons). |
110 | #ifdef __clang__ |
111 | # pragma unroll |
112 | #endif |
113 | for (unsigned i = 0; i < kMemoryLayoutSize; ++i) |
114 | if ((kMemoryLayout[i].type & mapping_types) && |
115 | addr >= kMemoryLayout[i].start && addr < kMemoryLayout[i].end) |
116 | return true; |
117 | return false; |
118 | } |
119 | |
120 | #define MEM_IS_APP(mem) \ |
121 | (addr_is_type((uptr)(mem), MappingDesc::APP | MappingDesc::ALLOCATOR)) |
122 | #define MEM_IS_SHADOW(mem) addr_is_type((uptr)(mem), MappingDesc::SHADOW) |
123 | #define MEM_IS_ORIGIN(mem) addr_is_type((uptr)(mem), MappingDesc::ORIGIN) |
124 | |
125 | } // namespace __dfsan |
126 | |
127 | #endif |
128 | |