OLD | NEW |
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 15 matching lines...) Expand all Loading... |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 #ifdef _WIN64 | 29 #ifdef _WIN64 |
30 // A lock under which the shadow instance is modified. | 30 // A lock under which the shadow instance is modified. |
31 base::Lock shadow_instance_lock; | 31 base::Lock shadow_instance_lock; |
32 | 32 |
33 // The pointer for the exception handler to know what shadow object is | 33 // The pointer for the exception handler to know what shadow object is |
34 // currently used. Under shadow_instance_lock. | 34 // currently used. Under shadow_instance_lock. |
35 // TODO(loskutov): eliminate this by enforcing Shadow to be a singleton. | 35 // TODO(loskutov): eliminate this by enforcing Shadow to be a singleton. |
36 const Shadow* shadow_instance; | 36 const Shadow* shadow_instance = nullptr; |
37 | 37 |
38 // The exception handler, intended to map the pages for shadow and page_bits | 38 // The exception handler, intended to map the pages for shadow and page_bits |
39 // on demand. When a page fault happens, the operating systems calls | 39 // on demand. When a page fault happens, the operating systems calls |
40 // this handler, and if the page is inside shadow or page_bits, it gets | 40 // this handler, and if the page is inside shadow or page_bits, it gets |
41 // commited seamlessly for the caller, and then execution continues. | 41 // commited seamlessly for the caller, and then execution continues. |
42 // Otherwise, the OS keeps searching for an appropriate handler. | 42 // Otherwise, the OS keeps searching for an appropriate handler. |
43 LONG NTAPI ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) { | 43 LONG NTAPI ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) { |
| 44 DCHECK_NE(static_cast<const Shadow*>(nullptr), shadow_instance); |
44 // Only handle access violations. | 45 // Only handle access violations. |
45 if (exception_pointers->ExceptionRecord->ExceptionCode != | 46 if (exception_pointers->ExceptionRecord->ExceptionCode != |
46 EXCEPTION_ACCESS_VIOLATION) { | 47 EXCEPTION_ACCESS_VIOLATION) { |
47 return EXCEPTION_CONTINUE_SEARCH; | 48 return EXCEPTION_CONTINUE_SEARCH; |
48 } | 49 } |
49 | 50 |
50 // Only handle access violations that land within the shadow memory | 51 // Only handle access violations that land within the shadow memory |
51 // or the page bits. | 52 // or the page bits. |
52 | 53 |
53 void* addr = reinterpret_cast<void*>( | 54 void* addr = reinterpret_cast<void*>( |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 } | 209 } |
209 | 210 |
210 auto cursor = shadow_ + i; | 211 auto cursor = shadow_ + i; |
211 MEMORY_BASIC_INFORMATION info = {}; | 212 MEMORY_BASIC_INFORMATION info = {}; |
212 while (i < length_) { | 213 while (i < length_) { |
213 auto next_cursor = cursor; | 214 auto next_cursor = cursor; |
214 while (cursor < shadow_ + length_) { | 215 while (cursor < shadow_ + length_) { |
215 auto ret = ::VirtualQuery(cursor, &info, sizeof(info)); | 216 auto ret = ::VirtualQuery(cursor, &info, sizeof(info)); |
216 DCHECK_GT(ret, 0u); | 217 DCHECK_GT(ret, 0u); |
217 next_cursor = static_cast<uint8_t*>(info.BaseAddress) + info.RegionSize; | 218 next_cursor = static_cast<uint8_t*>(info.BaseAddress) + info.RegionSize; |
218 if (info.Type == MEM_COMMIT) | 219 if (info.State == MEM_COMMIT) |
219 break; | 220 break; |
220 cursor = next_cursor; | 221 cursor = next_cursor; |
221 } | 222 } |
222 i = cursor - shadow_; | 223 i = cursor - shadow_; |
223 next_cursor = std::min(next_cursor, shadow_ + length_); | 224 next_cursor = std::min(next_cursor, shadow_ + length_); |
224 auto next_i = next_cursor - shadow_; | 225 auto next_i = next_cursor - shadow_; |
225 for (; i < next_i; ++i) { | 226 for (; i < next_i; ++i) { |
226 if ((i >= shadow_begin && i < shadow_end) || | 227 if ((i >= shadow_begin && i < shadow_end) || |
227 (i >= page_bits_begin && i < page_bits_end) || | 228 (i >= page_bits_begin && i < page_bits_end) || |
228 (i >= this_begin && i < this_end)) { | 229 (i >= this_begin && i < this_end)) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 Init(true, mem, length); | 278 Init(true, mem, length); |
278 } | 279 } |
279 | 280 |
280 void Shadow::Init(bool own_memory, void* shadow, size_t length) { | 281 void Shadow::Init(bool own_memory, void* shadow, size_t length) { |
281 #ifdef _WIN64 | 282 #ifdef _WIN64 |
282 { | 283 { |
283 base::AutoLock lock(shadow_instance_lock); | 284 base::AutoLock lock(shadow_instance_lock); |
284 shadow_instance = this; | 285 shadow_instance = this; |
285 } | 286 } |
286 exception_handler_ = | 287 exception_handler_ = |
287 AddVectoredExceptionHandler(TRUE, ShadowExceptionHandler); | 288 ::AddVectoredExceptionHandler(TRUE, ShadowExceptionHandler); |
288 #endif | 289 #endif |
289 | 290 |
290 // Handle the case of a failed allocation. | 291 // Handle the case of a failed allocation. |
291 if (shadow == nullptr) { | 292 if (shadow == nullptr) { |
292 own_memory_ = false; | 293 own_memory_ = false; |
293 shadow_ = nullptr; | 294 shadow_ = nullptr; |
294 length = 0; | 295 length = 0; |
295 return; | 296 return; |
296 } | 297 } |
297 | 298 |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 } | 878 } |
878 | 879 |
879 bool Shadow::ScanLeftForBracketingBlockStart( | 880 bool Shadow::ScanLeftForBracketingBlockStart( |
880 size_t initial_nesting_depth, size_t cursor, size_t* location) const { | 881 size_t initial_nesting_depth, size_t cursor, size_t* location) const { |
881 DCHECK_NE(static_cast<size_t*>(NULL), location); | 882 DCHECK_NE(static_cast<size_t*>(NULL), location); |
882 | 883 |
883 static const size_t kLowerBound = kAddressLowerBound / kShadowRatio; | 884 static const size_t kLowerBound = kAddressLowerBound / kShadowRatio; |
884 | 885 |
885 size_t left = cursor; | 886 size_t left = cursor; |
886 int nesting_depth = static_cast<int>(initial_nesting_depth); | 887 int nesting_depth = static_cast<int>(initial_nesting_depth); |
| 888 |
| 889 MEMORY_BASIC_INFORMATION memory_info = {}; |
| 890 SIZE_T ret = |
| 891 ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); |
| 892 DCHECK_GT(ret, 0u); |
| 893 if (memory_info.State != MEM_COMMIT) |
| 894 return false; |
| 895 |
887 if (ShadowMarkerHelper::IsBlockEnd(shadow_[left])) | 896 if (ShadowMarkerHelper::IsBlockEnd(shadow_[left])) |
888 --nesting_depth; | 897 --nesting_depth; |
889 while (true) { | 898 while (true) { |
| 899 if (&shadow_[left] < static_cast<const uint8_t*>(memory_info.BaseAddress)) { |
| 900 ret = ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); |
| 901 DCHECK_GT(ret, 0u); |
| 902 if (memory_info.State != MEM_COMMIT) |
| 903 return false; |
| 904 } |
890 if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) { | 905 if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) { |
891 if (nesting_depth == 0) { | 906 if (nesting_depth == 0) { |
892 *location = left; | 907 *location = left; |
893 return true; | 908 return true; |
894 } | 909 } |
895 // If this is not a nested block then there's no hope of finding a | 910 // If this is not a nested block then there's no hope of finding a |
896 // block containing the original cursor. | 911 // block containing the original cursor. |
897 if (!ShadowMarkerHelper::IsNestedBlockStart(shadow_[left])) | 912 if (!ShadowMarkerHelper::IsNestedBlockStart(shadow_[left])) |
898 return false; | 913 return false; |
899 --nesting_depth; | 914 --nesting_depth; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 // Get the bounds as shadow indices, being careful to deal with overflow | 1115 // Get the bounds as shadow indices, being careful to deal with overflow |
1101 // of |upper_bound|. | 1116 // of |upper_bound|. |
1102 lower_index_ = reinterpret_cast<uintptr_t>(lower_bound) >> kShadowRatioLog; | 1117 lower_index_ = reinterpret_cast<uintptr_t>(lower_bound) >> kShadowRatioLog; |
1103 upper_index_ = reinterpret_cast<size_t>(::common::AlignUp( | 1118 upper_index_ = reinterpret_cast<size_t>(::common::AlignUp( |
1104 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio)); | 1119 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio)); |
1105 upper_index_--; | 1120 upper_index_--; |
1106 upper_index_ >>= kShadowRatioLog; | 1121 upper_index_ >>= kShadowRatioLog; |
1107 upper_index_++; | 1122 upper_index_++; |
1108 | 1123 |
1109 DCHECK_LE(lower_index_, upper_index_); | 1124 DCHECK_LE(lower_index_, upper_index_); |
1110 DCHECK_GE(shadow->length(), upper_index_); | 1125 DCHECK_GE(shadow->length(), upper_index_ - lower_index_); |
1111 | 1126 |
1112 Reset(); | 1127 Reset(); |
1113 } | 1128 } |
1114 | 1129 |
1115 void ShadowWalker::Reset() { | 1130 void ShadowWalker::Reset() { |
1116 nesting_depth_ = -1; | 1131 nesting_depth_ = -1; |
1117 shadow_cursor_ = shadow_->shadow() + lower_index_; | 1132 shadow_cursor_ = shadow_->shadow() + lower_index_; |
1118 } | 1133 } |
1119 | 1134 |
1120 bool ShadowWalker::Next(BlockInfo* info) { | 1135 bool ShadowWalker::Next(BlockInfo* info) { |
(...skipping 13 matching lines...) Expand all Loading... |
1134 auto end_of_region = start_of_region + memory_info.RegionSize; | 1149 auto end_of_region = start_of_region + memory_info.RegionSize; |
1135 | 1150 |
1136 // If the region isn't committed and readable memory then skip it. | 1151 // If the region isn't committed and readable memory then skip it. |
1137 if (memory_info.State != MEM_COMMIT) { | 1152 if (memory_info.State != MEM_COMMIT) { |
1138 // If the next region is beyond the part of the shadow being scanned | 1153 // If the next region is beyond the part of the shadow being scanned |
1139 // then bail early (be careful to handle overflow here). | 1154 // then bail early (be careful to handle overflow here). |
1140 if (end_of_region > shadow_upper_bound || end_of_region == nullptr) | 1155 if (end_of_region > shadow_upper_bound || end_of_region == nullptr) |
1141 return false; | 1156 return false; |
1142 | 1157 |
1143 // Step to the beginning of the next region and try again. | 1158 // Step to the beginning of the next region and try again. |
1144 shadow_cursor_ = start_of_region; | 1159 shadow_cursor_ = end_of_region; |
1145 continue; | 1160 continue; |
1146 } | 1161 } |
1147 | 1162 |
1148 // Getting here then |start_of_region| and |end_of_region| are a part of | 1163 // Getting here then |start_of_region| and |end_of_region| are a part of |
1149 // the shadow that should be scanned. Calculate where to stop for this | 1164 // the shadow that should be scanned. Calculate where to stop for this |
1150 // region, taking care to handle overflow. | 1165 // region, taking care to handle overflow. |
1151 if (!end_of_region) { | 1166 if (!end_of_region) { |
1152 end_of_region = shadow_upper_bound; | 1167 end_of_region = shadow_upper_bound; |
1153 } else { | 1168 } else { |
1154 end_of_region = std::min(shadow_upper_bound, end_of_region); | 1169 end_of_region = std::min(shadow_upper_bound, end_of_region); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1206 // Advance the shadow cursor. | 1221 // Advance the shadow cursor. |
1207 ++shadow_cursor_; | 1222 ++shadow_cursor_; |
1208 } // while (shadow_cursor_ < end_of_region) | 1223 } // while (shadow_cursor_ < end_of_region) |
1209 } | 1224 } |
1210 | 1225 |
1211 return false; | 1226 return false; |
1212 } | 1227 } |
1213 | 1228 |
1214 } // namespace asan | 1229 } // namespace asan |
1215 } // namespace agent | 1230 } // namespace agent |
OLD | NEW |