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

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

Issue 1372183002: win: Add memory map range intersection helper (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: const 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
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>
20
19 #include "base/logging.h" 21 #include "base/logging.h"
20 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
21 #include "build/build_config.h" 23 #include "build/build_config.h"
22 #include "util/numeric/safe_assignment.h" 24 #include "util/numeric/safe_assignment.h"
23 #include "util/win/ntstatus_logging.h" 25 #include "util/win/ntstatus_logging.h"
24 #include "util/win/process_structs.h" 26 #include "util/win/process_structs.h"
25 27
26 namespace crashpad { 28 namespace crashpad {
27 29
28 namespace { 30 namespace {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 PLOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__; 99 PLOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__;
98 return false; 100 return false;
99 } 101 }
100 if (bytes_read != sizeof(T)) { 102 if (bytes_read != sizeof(T)) {
101 LOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__ << " incorrect size"; 103 LOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__ << " incorrect size";
102 return false; 104 return false;
103 } 105 }
104 return true; 106 return true;
105 } 107 }
106 108
109 bool PageIsReadable(const ProcessInfo::MemoryInfo& memory_info) {
Mark Mentovai 2015/10/01 17:38:58 The function name, PageIsReadable(), doesn’t match
Mark Mentovai 2015/10/01 17:38:58 This operates on MemoryInfo objects, which represe
scottmg 2015/10/01 18:10:02 Done.
scottmg 2015/10/01 18:10:02 Done.
110 return memory_info.state == MEM_FREE ||
111 (memory_info.state == MEM_COMMIT &&
112 ((memory_info.protect & PAGE_NOACCESS) ||
113 (memory_info.protect & PAGE_GUARD)));
114 }
115
107 } // namespace 116 } // namespace
108 117
109 template <class Traits> 118 template <class Traits>
110 bool GetProcessBasicInformation(HANDLE process, 119 bool GetProcessBasicInformation(HANDLE process,
111 bool is_wow64, 120 bool is_wow64,
112 ProcessInfo* process_info, 121 ProcessInfo* process_info,
113 WinVMAddress* peb_address, 122 WinVMAddress* peb_address,
114 WinVMSize* peb_size) { 123 WinVMSize* peb_size) {
115 ULONG bytes_returned; 124 ULONG bytes_returned;
116 process_types::PROCESS_BASIC_INFORMATION<Traits> process_basic_information; 125 process_types::PROCESS_BASIC_INFORMATION<Traits> process_basic_information;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 294
286 return true; 295 return true;
287 } 296 }
288 297
289 ProcessInfo::Module::Module() : name(), dll_base(0), size(0), timestamp() { 298 ProcessInfo::Module::Module() : name(), dll_base(0), size(0), timestamp() {
290 } 299 }
291 300
292 ProcessInfo::Module::~Module() { 301 ProcessInfo::Module::~Module() {
293 } 302 }
294 303
304 ProcessInfo::MemoryInfo::MemoryInfo()
305 : base_address(0),
306 region_size(0),
307 allocation_base(0),
308 state(0),
309 allocation_protect(0),
310 protect(0),
311 type(0) {
312 }
313
295 ProcessInfo::MemoryInfo::MemoryInfo(const MEMORY_BASIC_INFORMATION& mbi) 314 ProcessInfo::MemoryInfo::MemoryInfo(const MEMORY_BASIC_INFORMATION& mbi)
296 : base_address(reinterpret_cast<WinVMAddress>(mbi.BaseAddress)), 315 : base_address(reinterpret_cast<WinVMAddress>(mbi.BaseAddress)),
297 region_size(mbi.RegionSize), 316 region_size(mbi.RegionSize),
298 allocation_base(reinterpret_cast<WinVMAddress>(mbi.AllocationBase)), 317 allocation_base(reinterpret_cast<WinVMAddress>(mbi.AllocationBase)),
299 state(mbi.State), 318 state(mbi.State),
300 allocation_protect(mbi.AllocationProtect), 319 allocation_protect(mbi.AllocationProtect),
301 protect(mbi.Protect), 320 protect(mbi.Protect),
302 type(mbi.Type) { 321 type(mbi.Type) {
303 } 322 }
304 323
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 } 427 }
409 428
410 bool ProcessInfo::Modules(std::vector<Module>* modules) const { 429 bool ProcessInfo::Modules(std::vector<Module>* modules) const {
411 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 430 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
412 *modules = modules_; 431 *modules = modules_;
413 return true; 432 return true;
414 } 433 }
415 434
416 const std::vector<ProcessInfo::MemoryInfo>& ProcessInfo::MemoryInformation() 435 const std::vector<ProcessInfo::MemoryInfo>& ProcessInfo::MemoryInformation()
417 const { 436 const {
437 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
418 return memory_info_; 438 return memory_info_;
419 } 439 }
420 440
441 std::vector<CheckedRange<WinVMAddress, WinVMSize>>
442 ProcessInfo::GetReadableRanges(
443 const CheckedRange<WinVMAddress, WinVMSize>& range) const {
444 return GetReadableRangesOfMemoryMap(range, MemoryInformation());
445 }
446
447 std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap(
448 const CheckedRange<WinVMAddress, WinVMSize>& range,
449 const std::vector<ProcessInfo::MemoryInfo>& memory_info) {
450 using Range = CheckedRange<WinVMAddress, WinVMSize>;
451
452 // Find all the ranges that overlap the target range, maintaining their order.
453 std::vector<ProcessInfo::MemoryInfo> overlapping;
454 for (const auto& mi : memory_info) {
455 if (range.OverlapsRange(Range(mi.base_address, mi.region_size)))
456 overlapping.push_back(mi);
457 }
458 if (overlapping.empty())
459 return std::vector<Range>();
460
461 // For the first and last, trim to the boundary of the incoming range.
462 ProcessInfo::MemoryInfo& front = overlapping.front();
463 WinVMAddress original_base = front.base_address;
Mark Mentovai 2015/10/01 17:38:58 Since there are several ranges in play here, this
scottmg 2015/10/01 18:10:02 Done.
464 front.base_address = range.base();
Mark Mentovai 2015/10/01 17:38:59 Since this requires that front.base_address <= ran
scottmg 2015/10/01 18:10:02 Good catch. Done and added test.
465 front.region_size = (original_base + front.region_size) - range.base();
Mark Mentovai 2015/10/01 17:38:58 and then this one will need to become - front.base
scottmg 2015/10/01 18:10:02 Done.
466
467 ProcessInfo::MemoryInfo& back = overlapping.back();
468 back.region_size = range.end() - back.base_address;
Mark Mentovai 2015/10/01 17:38:58 The same kind of problem might show up here if the
scottmg 2015/10/01 18:10:02 Done and added test.
469
470 // Discard all non-accessible.
471 overlapping.erase(std::remove_if(overlapping.begin(),
472 overlapping.end(),
473 [](const ProcessInfo::MemoryInfo& mi) {
474 return PageIsReadable(mi);
475 }),
476 overlapping.end());
477 if (overlapping.empty())
478 return std::vector<Range>();
479
480 // Convert to return type.
481 std::vector<Range> as_ranges;
482 for (const auto& mi : overlapping) {
483 as_ranges.push_back(Range(mi.base_address, mi.region_size));
484 DCHECK(as_ranges.back().IsValid());
485 }
486
487 // Coalesce remaining regions.
488 std::vector<Range> result;
489 result.push_back(as_ranges[0]);
490 for (size_t i = 1; i < as_ranges.size(); ++i) {
491 if (result.back().end() == as_ranges[i].base()) {
492 result.back().SetRange(result.back().base(),
493 result.back().size() + as_ranges[i].size());
494 } else {
495 result.push_back(as_ranges[i]);
496 }
497 DCHECK(result.back().IsValid());
498 }
499
500 return result;
501 }
502
421 } // namespace crashpad 503 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698