| 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 |