1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : #include "syzygy/agent/asan/asan_shadow.h"
15 :
16 : #include "base/logging.h"
17 : #include "base/stringprintf.h"
18 :
19 : namespace agent {
20 : namespace asan {
21 :
22 : uint8 Shadow::shadow_[kShadowSize];
23 :
24 E : void Shadow::Reset() {
25 E : memset(shadow_, 0, kShadowSize);
26 E : }
27 :
28 E : void Shadow::Poison(const void* addr, size_t size, ShadowMarker shadow_val) {
29 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
30 E : uintptr_t start = index & 0x7;
31 E : DCHECK_EQ(0U, (index + size) & 0x7);
32 :
33 E : index >>= 3;
34 E : if (start)
35 E : shadow_[index++] = start;
36 :
37 E : size >>= 3;
38 E : DCHECK_GT(arraysize(shadow_), index + size);
39 E : memset(shadow_ + index, shadow_val, size);
40 E : }
41 :
42 E : void Shadow::Unpoison(const void* addr, size_t size) {
43 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
44 E : DCHECK_EQ(0U, index & 0x7);
45 :
46 E : uint8 remainder = size & 0x7;
47 E : index >>= 3;
48 E : size >>= 3;
49 E : DCHECK_GT(arraysize(shadow_), index + size);
50 E : memset(shadow_ + index, kHeapAddressableByte, size);
51 :
52 E : if (remainder != 0)
53 E : shadow_[index + size] = remainder;
54 E : }
55 :
56 E : void Shadow::MarkAsFreed(const void* addr, size_t size) {
57 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
58 E : uintptr_t start = index & 0x7;
59 :
60 E : index >>= 3;
61 E : if (start)
62 i : shadow_[index++] = kHeapFreedByte;
63 :
64 E : size_t size_shadow = size >> 3;
65 E : DCHECK_GT(arraysize(shadow_), index + size_shadow);
66 E : memset(shadow_ + index, kHeapFreedByte, size_shadow);
67 E : if ((size & 0x7) != 0)
68 E : shadow_[index + size_shadow] = kHeapFreedByte;
69 E : }
70 :
71 E : bool __stdcall Shadow::IsAccessible(const void* addr) {
72 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
73 E : uintptr_t start = index & 0x7;
74 :
75 E : index >>= 3;
76 :
77 E : DCHECK_GT(arraysize(shadow_), index);
78 E : uint8 shadow = shadow_[index];
79 E : if (shadow == 0)
80 E : return true;
81 :
82 E : if ((shadow & kHeapNonAccessibleByteMask) != 0)
83 E : return false;
84 :
85 E : return start < shadow;
86 E : }
87 :
88 : void Shadow::AppendShadowByteText(const char *prefix,
89 : uintptr_t index,
90 : std::string* output,
91 E : size_t bug_index) {
92 : base::StringAppendF(
93 E : output, "%s0x%08x:", prefix, reinterpret_cast<void*>(index << 3));
94 E : char separator = ' ';
95 E : for (uint32 i = 0; i < 8; i++) {
96 E : if (index + i == bug_index)
97 E : separator = '[';
98 E : uint8 shadow_value = shadow_[index + i];
99 : base::StringAppendF(
100 E : output, "%c%x%x", separator, shadow_value >> 4, shadow_value & 15);
101 E : if (separator == '[')
102 E : separator = ']';
103 E : else if (separator == ']')
104 E : separator = ' ';
105 E : }
106 E : if (separator == ']')
107 E : base::StringAppendF(output, "]");
108 E : base::StringAppendF(output, "\n");
109 E : }
110 :
111 : void Shadow::AppendShadowMemoryText(const void* addr,
112 E : std::string* output) {
113 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
114 E : index >>= 3;
115 E : base::StringAppendF(output, "Shadow bytes around the buggy address:\n");
116 E : size_t index_start = index;
117 E : index_start &= ~0x7;
118 E : for (int i = -4; i <= 4; i++) {
119 E : const char * const prefix = (i == 0) ? "=>" : " ";
120 E : AppendShadowByteText(prefix, (index_start + i * 8), output, index);
121 E : }
122 : base::StringAppendF(output,
123 E : "Shadow byte legend (one shadow byte represents 8 application bytes):\n");
124 : base::StringAppendF(output, " Addressable: %x%x\n",
125 E : kHeapAddressableByte >> 4, kHeapAddressableByte & 15);
126 : base::StringAppendF(output,
127 E : " Partially addressable: 01 02 03 04 05 06 07\n");
128 : base::StringAppendF(output, " Heap left redzone: %x%x\n",
129 E : kHeapLeftRedzone >> 4, kHeapLeftRedzone & 15);
130 : base::StringAppendF(output, " Heap righ redzone: %x%x\n",
131 E : kHeapRightRedzone >> 4, kHeapRightRedzone & 15);
132 : base::StringAppendF(output, " Freed Heap region: %x%x\n",
133 E : kHeapFreedByte >> 4, kHeapFreedByte & 15);
134 E : }
135 :
136 i : void Shadow::PrintShadowMemoryForAddress(const void* addr) {
137 i : std::string output;
138 i : AppendShadowMemoryText(addr, &output);
139 i : fprintf(stderr, "%s", output.c_str());
140 i : }
141 :
142 : } // namespace asan
143 : } // namespace agent
|