Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1013)

Side by Side Diff: util/win/process_info.cc

Issue 1375313005: Use MEMORY_BASIC_INFORMATION64 rather than a custom MemoryInfo (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@save-peb-more-2
Patch Set: . Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « util/win/process_info.h ('k') | util/win/process_info_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. 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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "util/win/process_info.h" 15 #include "util/win/process_info.h"
16 16
17 #include <winternl.h> 17 #include <winternl.h>
18 18
19 #include <algorithm> 19 #include <algorithm>
20 #include <limits> 20 #include <limits>
21 #include <type_traits>
Mark Mentovai 2015/10/07 18:50:52 OK if this is guaranteed to be available in all of
scottmg 2015/10/07 19:22:31 Hmm, it is, but strictly speaking it's also a C++1
21 22
22 #include "base/logging.h" 23 #include "base/logging.h"
23 #include "base/strings/stringprintf.h" 24 #include "base/strings/stringprintf.h"
24 #include "build/build_config.h" 25 #include "build/build_config.h"
25 #include "util/numeric/safe_assignment.h" 26 #include "util/numeric/safe_assignment.h"
26 #include "util/win/ntstatus_logging.h" 27 #include "util/win/ntstatus_logging.h"
27 #include "util/win/process_structs.h" 28 #include "util/win/process_structs.h"
28 29
29 namespace crashpad { 30 namespace crashpad {
30 31
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 PLOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__; 101 PLOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__;
101 return false; 102 return false;
102 } 103 }
103 if (bytes_read != sizeof(T)) { 104 if (bytes_read != sizeof(T)) {
104 LOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__ << " incorrect size"; 105 LOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__ << " incorrect size";
105 return false; 106 return false;
106 } 107 }
107 return true; 108 return true;
108 } 109 }
109 110
110 bool RegionIsAccessible(const ProcessInfo::MemoryInfo& memory_info) { 111 bool RegionIsAccessible(const MEMORY_BASIC_INFORMATION64& memory_info) {
111 return memory_info.state == MEM_COMMIT && 112 return memory_info.State == MEM_COMMIT &&
112 (memory_info.protect & PAGE_NOACCESS) == 0 && 113 (memory_info.Protect & PAGE_NOACCESS) == 0 &&
113 (memory_info.protect & PAGE_GUARD) == 0; 114 (memory_info.Protect & PAGE_GUARD) == 0;
115 }
116
117 MEMORY_BASIC_INFORMATION64 MemoryBasicInformationToMemoryBasicInformation64(
118 const MEMORY_BASIC_INFORMATION& mbi) {
119 MEMORY_BASIC_INFORMATION64 mbi64 = {0};
120 mbi64.BaseAddress = reinterpret_cast<ULONGLONG>(mbi.BaseAddress);
121 mbi64.AllocationBase = reinterpret_cast<ULONGLONG>(mbi.AllocationBase);
122 mbi64.AllocationProtect = mbi.AllocationProtect;
123 mbi64.RegionSize = mbi.RegionSize;
124 mbi64.State = mbi.State;
125 mbi64.Protect = mbi.Protect;
126 mbi64.Type = mbi.Type;
127 return mbi64;
114 } 128 }
115 129
116 } // namespace 130 } // namespace
117 131
118 template <class Traits> 132 template <class Traits>
119 bool GetProcessBasicInformation(HANDLE process, 133 bool GetProcessBasicInformation(HANDLE process,
120 bool is_wow64, 134 bool is_wow64,
121 ProcessInfo* process_info, 135 ProcessInfo* process_info,
122 WinVMAddress* peb_address, 136 WinVMAddress* peb_address,
123 WinVMSize* peb_size) { 137 WinVMSize* peb_size) {
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 &memory_basic_information, 295 &memory_basic_information,
282 sizeof(memory_basic_information)); 296 sizeof(memory_basic_information));
283 if (result == 0) { 297 if (result == 0) {
284 if (GetLastError() == ERROR_INVALID_PARAMETER) 298 if (GetLastError() == ERROR_INVALID_PARAMETER)
285 break; 299 break;
286 PLOG(ERROR) << "VirtualQueryEx"; 300 PLOG(ERROR) << "VirtualQueryEx";
287 return false; 301 return false;
288 } 302 }
289 303
290 process_info->memory_info_.push_back( 304 process_info->memory_info_.push_back(
291 ProcessInfo::MemoryInfo(memory_basic_information)); 305 MemoryBasicInformationToMemoryBasicInformation64(
306 memory_basic_information));
292 307
293 if (memory_basic_information.RegionSize == 0) { 308 if (memory_basic_information.RegionSize == 0) {
294 LOG(ERROR) << "RegionSize == 0"; 309 LOG(ERROR) << "RegionSize == 0";
295 return false; 310 return false;
296 } 311 }
297 } 312 }
298 313
299 return true; 314 return true;
300 } 315 }
301 316
302 ProcessInfo::Module::Module() : name(), dll_base(0), size(0), timestamp() { 317 ProcessInfo::Module::Module() : name(), dll_base(0), size(0), timestamp() {
303 } 318 }
304 319
305 ProcessInfo::Module::~Module() { 320 ProcessInfo::Module::~Module() {
306 } 321 }
307 322
308 ProcessInfo::MemoryInfo::MemoryInfo(const MEMORY_BASIC_INFORMATION& mbi)
309 : base_address(reinterpret_cast<WinVMAddress>(mbi.BaseAddress)),
310 region_size(mbi.RegionSize),
311 allocation_base(reinterpret_cast<WinVMAddress>(mbi.AllocationBase)),
312 state(mbi.State),
313 allocation_protect(mbi.AllocationProtect),
314 protect(mbi.Protect),
315 type(mbi.Type) {
316 }
317
318 ProcessInfo::MemoryInfo::~MemoryInfo() {
319 }
320
321 ProcessInfo::ProcessInfo() 323 ProcessInfo::ProcessInfo()
322 : process_id_(), 324 : process_id_(),
323 inherited_from_process_id_(), 325 inherited_from_process_id_(),
324 command_line_(), 326 command_line_(),
325 peb_address_(0), 327 peb_address_(0),
326 peb_size_(0), 328 peb_size_(0),
327 modules_(), 329 modules_(),
328 memory_info_(), 330 memory_info_(),
329 is_64_bit_(false), 331 is_64_bit_(false),
330 is_wow64_(false), 332 is_wow64_(false),
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 *peb_address = peb_address_; 421 *peb_address = peb_address_;
420 *peb_size = peb_size_; 422 *peb_size = peb_size_;
421 } 423 }
422 424
423 bool ProcessInfo::Modules(std::vector<Module>* modules) const { 425 bool ProcessInfo::Modules(std::vector<Module>* modules) const {
424 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 426 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
425 *modules = modules_; 427 *modules = modules_;
426 return true; 428 return true;
427 } 429 }
428 430
429 const std::vector<ProcessInfo::MemoryInfo>& ProcessInfo::MemoryInformation() 431 const std::vector<MEMORY_BASIC_INFORMATION64>& ProcessInfo::MemoryInfo() const {
430 const {
431 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 432 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
432 return memory_info_; 433 return memory_info_;
433 } 434 }
434 435
435 std::vector<CheckedRange<WinVMAddress, WinVMSize>> 436 std::vector<CheckedRange<WinVMAddress, WinVMSize>>
436 ProcessInfo::GetReadableRanges( 437 ProcessInfo::GetReadableRanges(
437 const CheckedRange<WinVMAddress, WinVMSize>& range) const { 438 const CheckedRange<WinVMAddress, WinVMSize>& range) const {
438 return GetReadableRangesOfMemoryMap(range, MemoryInformation()); 439 return GetReadableRangesOfMemoryMap(range, MemoryInfo());
439 } 440 }
440 441
441 std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap( 442 std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap(
442 const CheckedRange<WinVMAddress, WinVMSize>& range, 443 const CheckedRange<WinVMAddress, WinVMSize>& range,
443 const std::vector<ProcessInfo::MemoryInfo>& memory_info) { 444 const std::vector<MEMORY_BASIC_INFORMATION64>& memory_info) {
444 using Range = CheckedRange<WinVMAddress, WinVMSize>; 445 using Range = CheckedRange<WinVMAddress, WinVMSize>;
445 446
446 // Find all the ranges that overlap the target range, maintaining their order. 447 // Find all the ranges that overlap the target range, maintaining their order.
447 std::vector<ProcessInfo::MemoryInfo> overlapping; 448 std::vector<MEMORY_BASIC_INFORMATION64> overlapping;
448 for (const auto& mi : memory_info) { 449 for (const auto& mi : memory_info) {
449 if (range.OverlapsRange(Range(mi.base_address, mi.region_size))) 450 static_assert(std::is_same<decltype(mi.BaseAddress), WinVMAddress>::value,
451 "expected range address to be WinVMAddress");
452 static_assert(std::is_same<decltype(mi.RegionSize), WinVMSize>::value,
453 "expected range size to be WinVMSize");
454 if (range.OverlapsRange(Range(mi.BaseAddress, mi.RegionSize)))
450 overlapping.push_back(mi); 455 overlapping.push_back(mi);
451 } 456 }
452 if (overlapping.empty()) 457 if (overlapping.empty())
453 return std::vector<Range>(); 458 return std::vector<Range>();
454 459
455 // For the first and last, trim to the boundary of the incoming range. 460 // For the first and last, trim to the boundary of the incoming range.
456 ProcessInfo::MemoryInfo& front = overlapping.front(); 461 MEMORY_BASIC_INFORMATION64& front = overlapping.front();
457 WinVMAddress original_front_base_address = front.base_address; 462 WinVMAddress original_front_base_address = front.BaseAddress;
458 front.base_address = std::max(front.base_address, range.base()); 463 front.BaseAddress = std::max(front.BaseAddress, range.base());
459 front.region_size = 464 front.RegionSize =
460 (original_front_base_address + front.region_size) - front.base_address; 465 (original_front_base_address + front.RegionSize) - front.BaseAddress;
461 466
462 ProcessInfo::MemoryInfo& back = overlapping.back(); 467 MEMORY_BASIC_INFORMATION64& back = overlapping.back();
463 WinVMAddress back_end = back.base_address + back.region_size; 468 WinVMAddress back_end = back.BaseAddress + back.RegionSize;
464 back.region_size = std::min(range.end(), back_end) - back.base_address; 469 back.RegionSize = std::min(range.end(), back_end) - back.BaseAddress;
465 470
466 // Discard all non-accessible. 471 // Discard all non-accessible.
467 overlapping.erase(std::remove_if(overlapping.begin(), 472 overlapping.erase(std::remove_if(overlapping.begin(),
468 overlapping.end(), 473 overlapping.end(),
469 [](const ProcessInfo::MemoryInfo& mi) { 474 [](const MEMORY_BASIC_INFORMATION64& mbi) {
470 return !RegionIsAccessible(mi); 475 return !RegionIsAccessible(mbi);
471 }), 476 }),
472 overlapping.end()); 477 overlapping.end());
473 if (overlapping.empty()) 478 if (overlapping.empty())
474 return std::vector<Range>(); 479 return std::vector<Range>();
475 480
476 // Convert to return type. 481 // Convert to return type.
477 std::vector<Range> as_ranges; 482 std::vector<Range> as_ranges;
478 for (const auto& mi : overlapping) { 483 for (const auto& mi : overlapping) {
479 as_ranges.push_back(Range(mi.base_address, mi.region_size)); 484 as_ranges.push_back(Range(mi.BaseAddress, mi.RegionSize));
480 DCHECK(as_ranges.back().IsValid()); 485 DCHECK(as_ranges.back().IsValid());
481 } 486 }
482 487
483 // Coalesce remaining regions. 488 // Coalesce remaining regions.
484 std::vector<Range> result; 489 std::vector<Range> result;
485 result.push_back(as_ranges[0]); 490 result.push_back(as_ranges[0]);
486 for (size_t i = 1; i < as_ranges.size(); ++i) { 491 for (size_t i = 1; i < as_ranges.size(); ++i) {
487 if (result.back().end() == as_ranges[i].base()) { 492 if (result.back().end() == as_ranges[i].base()) {
488 result.back().SetRange(result.back().base(), 493 result.back().SetRange(result.back().base(),
489 result.back().size() + as_ranges[i].size()); 494 result.back().size() + as_ranges[i].size());
490 } else { 495 } else {
491 result.push_back(as_ranges[i]); 496 result.push_back(as_ranges[i]);
492 } 497 }
493 DCHECK(result.back().IsValid()); 498 DCHECK(result.back().IsValid());
494 } 499 }
495 500
496 return result; 501 return result;
497 } 502 }
498 503
499 } // namespace crashpad 504 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/win/process_info.h ('k') | util/win/process_info_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698