Chromium Code Reviews| 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 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1085 info->header_size = body - block; | 1085 info->header_size = body - block; |
| 1086 info->trailer_size = info->block_size - body_size - info->header_size; | 1086 info->trailer_size = info->block_size - body_size - info->header_size; |
| 1087 | 1087 |
| 1088 return true; | 1088 return true; |
| 1089 } | 1089 } |
| 1090 | 1090 |
| 1091 ShadowWalker::ShadowWalker(const Shadow* shadow, | 1091 ShadowWalker::ShadowWalker(const Shadow* shadow, |
| 1092 bool recursive, | 1092 bool recursive, |
| 1093 const void* lower_bound, | 1093 const void* lower_bound, |
| 1094 const void* upper_bound) | 1094 const void* upper_bound) |
| 1095 : shadow_(shadow), recursive_(recursive), lower_bound_(0), upper_bound_(0), | 1095 : shadow_(shadow), recursive_(recursive), lower_index_(0), upper_index_(0), |
| 1096 cursor_(nullptr), shadow_cursor_(nullptr), nesting_depth_(0) { | 1096 shadow_cursor_(nullptr), nesting_depth_(0) { |
| 1097 DCHECK_NE(static_cast<Shadow*>(nullptr), shadow); | 1097 DCHECK_NE(static_cast<Shadow*>(nullptr), shadow); |
| 1098 DCHECK_LE(Shadow::kAddressLowerBound, reinterpret_cast<size_t>(lower_bound)); | 1098 DCHECK_LE(Shadow::kAddressLowerBound, reinterpret_cast<size_t>(lower_bound)); |
| 1099 DCHECK_GE(shadow->memory_size(), reinterpret_cast<size_t>(upper_bound)); | |
| 1100 DCHECK_LE(lower_bound, upper_bound); | |
| 1101 | 1099 |
| 1102 lower_bound_ = ::common::AlignDown( | 1100 // Get the bounds as shadow indices, being careful to deal with overflow |
| 1103 reinterpret_cast<const uint8_t*>(lower_bound), kShadowRatio); | 1101 // of |upper_bound|. |
| 1104 upper_bound_ = ::common::AlignUp( | 1102 lower_index_ = reinterpret_cast<uintptr_t>(lower_bound) >> kShadowRatioLog; |
| 1105 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio); | 1103 upper_index_ = reinterpret_cast<size_t>(::common::AlignUp( |
| 1104 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio)); | |
| 1105 upper_index_--; | |
| 1106 upper_index_ >>= kShadowRatioLog; | |
| 1107 upper_index_++; | |
| 1108 | |
| 1109 DCHECK_LE(lower_index_, upper_index_); | |
| 1110 DCHECK_GE(shadow->length(), upper_index_); | |
| 1111 | |
| 1106 Reset(); | 1112 Reset(); |
| 1107 } | 1113 } |
| 1108 | 1114 |
| 1109 void ShadowWalker::Reset() { | 1115 void ShadowWalker::Reset() { |
| 1110 // Walk to the beginning of the first non-nested block, or to the end | |
| 1111 // of the range, whichever comes first. | |
| 1112 nesting_depth_ = -1; | 1116 nesting_depth_ = -1; |
| 1113 shadow_cursor_ = shadow_->GetShadowMemoryForAddress(lower_bound_); | 1117 shadow_cursor_ = shadow_->shadow() + lower_index_; |
| 1114 auto shadow_upper_bound = shadow_->GetShadowMemoryForAddress(upper_bound_); | |
| 1115 MEMORY_BASIC_INFORMATION memory_info = {}; | |
| 1116 const uint8_t* next_shadow_cursor = shadow_cursor_; | |
| 1117 | |
| 1118 while (shadow_cursor_ < shadow_upper_bound) { | |
| 1119 while (shadow_cursor_ < shadow_upper_bound) { | |
| 1120 size_t ret = ::VirtualQuery(shadow_cursor_, &memory_info, | |
| 1121 sizeof(memory_info)); | |
| 1122 DCHECK_GT(ret, 0u); | |
| 1123 next_shadow_cursor = static_cast<uint8_t*>(memory_info.BaseAddress) + | |
| 1124 memory_info.RegionSize; | |
| 1125 if (memory_info.State == MEM_COMMIT) | |
| 1126 break; | |
| 1127 shadow_cursor_ = next_shadow_cursor; | |
| 1128 } | |
| 1129 next_shadow_cursor = std::min(next_shadow_cursor, shadow_upper_bound); | |
| 1130 for (; shadow_cursor_ != next_shadow_cursor; ++shadow_cursor_) { | |
| 1131 uint8_t marker = *shadow_cursor_; | |
| 1132 if (ShadowMarkerHelper::IsBlockStart(marker) && | |
| 1133 !ShadowMarkerHelper::IsNestedBlockStart(marker)) { | |
| 1134 // Break both loops. | |
| 1135 shadow_upper_bound = shadow_cursor_; | |
| 1136 break; | |
| 1137 } | |
| 1138 } | |
| 1139 } | |
| 1140 | |
| 1141 cursor_ = reinterpret_cast<uint8_t*>((shadow_cursor_ - shadow_->shadow()) * | |
| 1142 kShadowRatio); | |
| 1143 } | 1118 } |
| 1144 | 1119 |
| 1145 bool ShadowWalker::Next(BlockInfo* info) { | 1120 bool ShadowWalker::Next(BlockInfo* info) { |
| 1146 DCHECK_NE(static_cast<BlockInfo*>(NULL), info); | 1121 DCHECK_NE(static_cast<BlockInfo*>(NULL), info); |
| 1147 | 1122 |
| 1148 auto shadow_upper_bound = shadow_->GetShadowMemoryForAddress(upper_bound_); | 1123 auto shadow_upper_bound = shadow_->shadow() + upper_index_; |
| 1149 MEMORY_BASIC_INFORMATION memory_info = {}; | |
| 1150 const uint8_t* next_shadow_cursor = shadow_cursor_; | |
| 1151 | 1124 |
| 1152 // Iterate until a reportable block is encountered, or the slab is exhausted. | 1125 while (shadow_cursor_ < shadow_upper_bound) { |
| 1153 while (cursor_ < upper_bound_) { | 1126 // Skip uncommitted ranges of memory. This is possible when using a sparse |
| 1154 // Find a range of commited pages in the shadow memory. | 1127 // shadow that maps its pages in on demand. |
| 1155 shadow_cursor_ = shadow_->GetShadowMemoryForAddress(cursor_); | 1128 MEMORY_BASIC_INFORMATION memory_info = {}; |
| 1156 while (shadow_cursor_ != shadow_upper_bound) { | 1129 size_t ret = ::VirtualQuery(shadow_cursor_, &memory_info, |
| 1157 size_t ret = ::VirtualQuery(shadow_cursor_, &memory_info, | 1130 sizeof(memory_info)); |
| 1158 sizeof(memory_info)); | 1131 DCHECK_GT(ret, 0u); |
|
chrisha
2016/09/29 14:12:10
Doing this at every step is quite wasteful. I've r
| |
| 1159 DCHECK_GT(ret, 0u); | 1132 auto start_of_region = |
| 1160 next_shadow_cursor = static_cast<uint8_t*>(memory_info.BaseAddress) + | 1133 static_cast<const uint8_t*>(memory_info.BaseAddress); |
| 1161 memory_info.RegionSize; | 1134 auto end_of_region = start_of_region + memory_info.RegionSize; |
| 1162 if (memory_info.State == MEM_COMMIT) | 1135 |
| 1163 break; | 1136 // If the region isn't committed and readable memory then skip it. |
| 1164 shadow_cursor_ = next_shadow_cursor; | 1137 if (memory_info.State != MEM_COMMIT) { |
| 1138 // If the next region is beyond the part of the shadow being scanned | |
| 1139 // then bail early (be careful to handle overflow here). | |
| 1140 if (end_of_region > shadow_upper_bound || end_of_region == nullptr) | |
| 1141 return false; | |
| 1142 | |
| 1143 // Step to the beginning of the next region and try again. | |
| 1144 shadow_cursor_ = start_of_region; | |
| 1145 continue; | |
| 1165 } | 1146 } |
| 1166 | 1147 |
| 1167 cursor_ = reinterpret_cast<uint8_t*>((shadow_cursor_ - shadow_->shadow()) * | 1148 // Getting here then |start_of_region| and |end_of_region| are a part of |
| 1168 kShadowRatio); | 1149 // the shadow that should be scanned. Calculate where to stop for this |
| 1150 // region, taking care to handle overflow. | |
| 1151 if (!end_of_region) { | |
| 1152 end_of_region = shadow_upper_bound; | |
| 1153 } else { | |
| 1154 end_of_region = std::min(shadow_upper_bound, end_of_region); | |
| 1155 } | |
| 1169 | 1156 |
| 1170 if (cursor_ >= upper_bound_) | 1157 // Scan this committed portion of the shadow. |
| 1171 break; | 1158 while (shadow_cursor_ < end_of_region) { |
| 1172 | 1159 uint8_t marker = *shadow_cursor_; |
| 1173 auto next_shadow_index = next_shadow_cursor - shadow_->shadow(); | |
| 1174 auto next_cursor = std::min(upper_bound_, | |
| 1175 reinterpret_cast<const uint8_t*>( | |
| 1176 next_shadow_index * kShadowRatio)); | |
| 1177 | |
| 1178 for (; cursor_ != next_cursor; cursor_ += kShadowRatio) { | |
| 1179 uint8_t marker = shadow_->GetShadowMarkerForAddress(cursor_); | |
| 1180 | 1160 |
| 1181 // Update the nesting depth when block end markers are encountered. | 1161 // Update the nesting depth when block end markers are encountered. |
| 1182 if (ShadowMarkerHelper::IsBlockEnd(marker)) { | 1162 if (ShadowMarkerHelper::IsBlockEnd(marker)) { |
| 1183 DCHECK_LE(0, nesting_depth_); | 1163 DCHECK_LE(0, nesting_depth_); |
| 1184 --nesting_depth_; | 1164 --nesting_depth_; |
| 1165 ++shadow_cursor_; | |
| 1185 continue; | 1166 continue; |
| 1186 } | 1167 } |
| 1187 | 1168 |
| 1188 // Look for a block start marker. | 1169 // Look for a block start marker. |
| 1189 if (ShadowMarkerHelper::IsBlockStart(marker)) { | 1170 if (ShadowMarkerHelper::IsBlockStart(marker)) { |
| 1190 // Update the nesting depth when block start bytes are encountered. | 1171 // Update the nesting depth when block start bytes are encountered. |
| 1191 ++nesting_depth_; | 1172 ++nesting_depth_; |
| 1192 | 1173 |
| 1193 // Non-nested blocks should only be encountered at depth 0. | 1174 // Non-nested blocks should only be encountered at depth 0. |
| 1194 bool is_nested = ShadowMarkerHelper::IsNestedBlockStart(marker); | 1175 bool is_nested = ShadowMarkerHelper::IsNestedBlockStart(marker); |
| 1195 DCHECK(is_nested || nesting_depth_ == 0); | 1176 DCHECK(is_nested || nesting_depth_ == 0); |
| 1196 | 1177 |
| 1197 // Determine if the block is to be reported. | 1178 // Determine if the block is to be reported. |
| 1198 if (!is_nested || recursive_) { | 1179 if (!is_nested || recursive_) { |
| 1199 // This can only fail if the shadow memory is malformed. | 1180 // This can only fail if the shadow memory is malformed. |
| 1200 CHECK(shadow_->BlockInfoFromShadow(cursor_, info)); | 1181 size_t block_index = shadow_cursor_ - shadow_->shadow(); |
| 1182 void* block_address = reinterpret_cast<void*>( | |
| 1183 block_index << kShadowRatioLog); | |
| 1184 CHECK(shadow_->BlockInfoFromShadow(block_address, info)); | |
| 1201 | 1185 |
| 1202 // In a recursive descent we have to process body contents. | 1186 // In a recursive descent we have to process body contents. |
| 1203 if (recursive_) { | 1187 if (recursive_) { |
| 1204 cursor_ += kShadowRatio; | 1188 // Jump straight to the body of the nested block. |
| 1189 shadow_cursor_ = shadow_->GetShadowMemoryForAddress( | |
| 1190 info->body); | |
| 1205 } else { | 1191 } else { |
| 1206 // Otherwise we can skip the body of the block we just reported. | 1192 // Otherwise we can skip the body of the block we just reported. |
| 1207 // We skip directly to the end marker (but not past it so that depth | 1193 // We skip directly to the end marker (but not past it so that depth |
| 1208 // bookkeeping works properly). | 1194 // bookkeeping works properly). |
| 1209 cursor_ += info->block_size - kShadowRatio; | 1195 auto block_end = reinterpret_cast<const uint8_t*>(info->header) + |
| 1196 info->block_size; | |
| 1197 shadow_cursor_ = shadow_->GetShadowMemoryForAddress(block_end) - 1; | |
| 1210 } | 1198 } |
| 1211 | 1199 |
| 1212 shadow_cursor_ = shadow_->GetShadowMemoryForAddress(cursor_); | 1200 // A block has been found and its |info| is parsed. Return to the |
| 1201 // caller. | |
| 1213 return true; | 1202 return true; |
| 1214 } | 1203 } |
| 1215 continue; | |
| 1216 } | 1204 } |
| 1217 } | 1205 |
| 1206 // Advance the shadow cursor. | |
| 1207 ++shadow_cursor_; | |
| 1208 } // while (shadow_cursor_ < end_of_region) | |
| 1218 } | 1209 } |
| 1219 | 1210 |
| 1220 return false; | 1211 return false; |
| 1221 } | 1212 } |
| 1222 | 1213 |
| 1223 } // namespace asan | 1214 } // namespace asan |
| 1224 } // namespace agent | 1215 } // namespace agent |
| OLD | NEW |