mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-14 01:08:01 +08:00
Linux: capture memory pointed to by context
This adds support for capturing memory snippets for addresses currently stored in registers to Linux/Android/CrOS. Modeled after the existing support on Windows. Bug: crashpad:30 Change-Id: Ib7cb523555a6e8e4d70145c205d67dcfbc9c7fcc Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3273712 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
afeb19f1d2
commit
d62cc6fdbd
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,6 +19,7 @@
|
||||
*.xcodeproj
|
||||
*~
|
||||
.*.sw?
|
||||
.cache
|
||||
.DS_Store
|
||||
.gdb_history
|
||||
.gdbinit
|
||||
|
@ -128,6 +128,8 @@ crashpad_static_library("snapshot") {
|
||||
|
||||
if (crashpad_is_linux || crashpad_is_android) {
|
||||
sources += [
|
||||
"linux/capture_memory_delegate_linux.cc",
|
||||
"linux/capture_memory_delegate_linux.h",
|
||||
"linux/cpu_context_linux.cc",
|
||||
"linux/cpu_context_linux.h",
|
||||
"linux/debug_rendezvous.cc",
|
||||
|
77
snapshot/linux/capture_memory_delegate_linux.cc
Normal file
77
snapshot/linux/capture_memory_delegate_linux.cc
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2021 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "snapshot/linux/capture_memory_delegate_linux.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "snapshot/memory_snapshot_generic.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace internal {
|
||||
|
||||
CaptureMemoryDelegateLinux::CaptureMemoryDelegateLinux(
|
||||
ProcessReaderLinux* process_reader,
|
||||
const ProcessReaderLinux::Thread* thread_opt,
|
||||
std::vector<std::unique_ptr<MemorySnapshotGeneric>>* snapshots,
|
||||
uint32_t* budget_remaining)
|
||||
: stack_(thread_opt ? thread_opt->stack_region_address : 0,
|
||||
thread_opt ? thread_opt->stack_region_size : 0),
|
||||
process_reader_(process_reader),
|
||||
snapshots_(snapshots),
|
||||
budget_remaining_(budget_remaining) {}
|
||||
|
||||
bool CaptureMemoryDelegateLinux::Is64Bit() const {
|
||||
return process_reader_->Is64Bit();
|
||||
}
|
||||
|
||||
bool CaptureMemoryDelegateLinux::ReadMemory(uint64_t at,
|
||||
uint64_t num_bytes,
|
||||
void* into) const {
|
||||
return process_reader_->Memory()->Read(
|
||||
at, base::checked_cast<size_t>(num_bytes), into);
|
||||
}
|
||||
|
||||
std::vector<CheckedRange<uint64_t>>
|
||||
CaptureMemoryDelegateLinux::GetReadableRanges(
|
||||
const CheckedRange<uint64_t, uint64_t>& range) const {
|
||||
return process_reader_->GetMemoryMap()->GetReadableRanges(range);
|
||||
}
|
||||
|
||||
void CaptureMemoryDelegateLinux::AddNewMemorySnapshot(
|
||||
const CheckedRange<uint64_t, uint64_t>& range) {
|
||||
// Don't bother storing this memory if it points back into the stack.
|
||||
if (stack_.ContainsRange(range))
|
||||
return;
|
||||
if (range.size() == 0)
|
||||
return;
|
||||
if (budget_remaining_ && *budget_remaining_ == 0)
|
||||
return;
|
||||
snapshots_->push_back(std::make_unique<internal::MemorySnapshotGeneric>());
|
||||
internal::MemorySnapshotGeneric* snapshot = snapshots_->back().get();
|
||||
snapshot->Initialize(process_reader_->Memory(), range.base(), range.size());
|
||||
if (budget_remaining_) {
|
||||
if (!base::IsValueInRangeForNumericType<int64_t>(range.size())) {
|
||||
*budget_remaining_ = 0;
|
||||
} else {
|
||||
int64_t temp = *budget_remaining_;
|
||||
temp -= range.size();
|
||||
*budget_remaining_ = base::saturated_cast<uint32_t>(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
70
snapshot/linux/capture_memory_delegate_linux.h
Normal file
70
snapshot/linux/capture_memory_delegate_linux.h
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2021 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CRASHPAD_SNAPSHOT_LINUX_CAPTURE_MEMORY_DELEGATE_LINUX_H_
|
||||
#define CRASHPAD_SNAPSHOT_LINUX_CAPTURE_MEMORY_DELEGATE_LINUX_H_
|
||||
|
||||
#include "snapshot/capture_memory.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "snapshot/linux/process_reader_linux.h"
|
||||
#include "util/numeric/checked_range.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace internal {
|
||||
|
||||
class MemorySnapshotGeneric;
|
||||
|
||||
class CaptureMemoryDelegateLinux : public CaptureMemory::Delegate {
|
||||
public:
|
||||
//! \brief A MemoryCaptureDelegate for Linux.
|
||||
//!
|
||||
//! \param[in] process_reader A ProcessReaderLinux for the target process.
|
||||
//! \param[in] thread_opt The thread being inspected. Memory ranges
|
||||
//! overlapping this thread's stack will be ignored on the assumption
|
||||
//! that they're already captured elsewhere. May be nullptr.
|
||||
//! \param[in] snapshots A vector of MemorySnapshotGeneric to which the
|
||||
//! captured memory will be added.
|
||||
//! \param[in] budget_remaining If non-null, a pointer to the remaining number
|
||||
//! of bytes to capture. If this is `0`, no further memory will be
|
||||
//! captured.
|
||||
CaptureMemoryDelegateLinux(
|
||||
ProcessReaderLinux* process_reader,
|
||||
const ProcessReaderLinux::Thread* thread_opt,
|
||||
std::vector<std::unique_ptr<MemorySnapshotGeneric>>* snapshots,
|
||||
uint32_t* budget_remaining);
|
||||
|
||||
// MemoryCaptureDelegate:
|
||||
bool Is64Bit() const override;
|
||||
bool ReadMemory(uint64_t at, uint64_t num_bytes, void* into) const override;
|
||||
std::vector<CheckedRange<uint64_t>> GetReadableRanges(
|
||||
const CheckedRange<uint64_t, uint64_t>& range) const override;
|
||||
void AddNewMemorySnapshot(
|
||||
const CheckedRange<uint64_t, uint64_t>& range) override;
|
||||
|
||||
private:
|
||||
CheckedRange<uint64_t, uint64_t> stack_;
|
||||
ProcessReaderLinux* process_reader_; // weak
|
||||
std::vector<std::unique_ptr<MemorySnapshotGeneric>>* snapshots_; // weak
|
||||
uint32_t* budget_remaining_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_SNAPSHOT_LINUX_CAPTURE_MEMORY_DELEGATE_LINUX_H_
|
@ -17,6 +17,7 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "snapshot/linux/capture_memory_delegate_linux.h"
|
||||
#include "snapshot/linux/cpu_context_linux.h"
|
||||
#include "snapshot/linux/process_reader_linux.h"
|
||||
#include "snapshot/linux/signal_context.h"
|
||||
@ -332,6 +333,18 @@ bool ExceptionSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
|
||||
thread_id_ = thread_id;
|
||||
const ProcessReaderLinux::Thread* thread = nullptr;
|
||||
for (const auto& loop_thread : process_reader->Threads()) {
|
||||
if (thread_id == loop_thread.tid) {
|
||||
thread = &loop_thread;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!thread) {
|
||||
// This is allowed until {ProcessReaderLinux::InitializeThreads()} is
|
||||
// improved to support target threads in the same thread group.
|
||||
LOG(WARNING) << "thread ID " << thread_id << " not found in process";
|
||||
}
|
||||
|
||||
if (process_reader->Is64Bit()) {
|
||||
if (!ReadContext<ContextTraits64>(process_reader, context_address) ||
|
||||
@ -345,6 +358,10 @@ bool ExceptionSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
|
||||
}
|
||||
}
|
||||
|
||||
CaptureMemoryDelegateLinux capture_memory_delegate(
|
||||
process_reader, thread, &extra_memory_, nullptr);
|
||||
CaptureMemory::PointedToByContext(context_, &capture_memory_delegate);
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
@ -462,7 +479,12 @@ const std::vector<uint64_t>& ExceptionSnapshotLinux::Codes() const {
|
||||
|
||||
std::vector<const MemorySnapshot*> ExceptionSnapshotLinux::ExtraMemory() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return std::vector<const MemorySnapshot*>();
|
||||
std::vector<const MemorySnapshot*> result;
|
||||
result.reserve(extra_memory_.size());
|
||||
for (const auto& em : extra_memory_) {
|
||||
result.push_back(em.get());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "snapshot/exception_snapshot.h"
|
||||
#include "snapshot/linux/process_reader_linux.h"
|
||||
#include "snapshot/memory_snapshot.h"
|
||||
#include "snapshot/memory_snapshot_generic.h"
|
||||
#include "util/linux/address_types.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
|
||||
@ -91,6 +92,7 @@ class ExceptionSnapshotLinux final : public ExceptionSnapshot {
|
||||
} context_union_;
|
||||
CPUContext context_;
|
||||
std::vector<uint64_t> codes_;
|
||||
std::vector<std::unique_ptr<internal::MemorySnapshotGeneric>> extra_memory_;
|
||||
uint64_t thread_id_;
|
||||
uint64_t exception_address_;
|
||||
uint32_t signal_number_;
|
||||
|
@ -41,6 +41,8 @@ bool ProcessSnapshotLinux::Initialize(PtraceConnection* connection) {
|
||||
|
||||
system_.Initialize(&process_reader_, &snapshot_time_);
|
||||
|
||||
GetCrashpadOptionsInternal((&options_));
|
||||
|
||||
InitializeThreads();
|
||||
InitializeModules();
|
||||
InitializeAnnotations();
|
||||
@ -100,7 +102,7 @@ bool ProcessSnapshotLinux::InitializeException(
|
||||
|
||||
auto exc_thread_snapshot =
|
||||
std::make_unique<internal::ThreadSnapshotLinux>();
|
||||
if (!exc_thread_snapshot->Initialize(&process_reader_, thread)) {
|
||||
if (!exc_thread_snapshot->Initialize(&process_reader_, thread, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -124,7 +126,11 @@ bool ProcessSnapshotLinux::InitializeException(
|
||||
void ProcessSnapshotLinux::GetCrashpadOptions(
|
||||
CrashpadInfoClientOptions* options) {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
*options = options_;
|
||||
}
|
||||
|
||||
void ProcessSnapshotLinux::GetCrashpadOptionsInternal(
|
||||
CrashpadInfoClientOptions* options) {
|
||||
CrashpadInfoClientOptions local_options;
|
||||
|
||||
for (const auto& module : modules_) {
|
||||
@ -262,10 +268,17 @@ const ProcessMemory* ProcessSnapshotLinux::Memory() const {
|
||||
void ProcessSnapshotLinux::InitializeThreads() {
|
||||
const std::vector<ProcessReaderLinux::Thread>& process_reader_threads =
|
||||
process_reader_.Threads();
|
||||
uint32_t* budget_remaining_pointer = nullptr;
|
||||
uint32_t budget_remaining = options_.indirectly_referenced_memory_cap;
|
||||
if (options_.gather_indirectly_referenced_memory == TriState::kEnabled) {
|
||||
budget_remaining_pointer = &budget_remaining;
|
||||
}
|
||||
for (const ProcessReaderLinux::Thread& process_reader_thread :
|
||||
process_reader_threads) {
|
||||
auto thread = std::make_unique<internal::ThreadSnapshotLinux>();
|
||||
if (thread->Initialize(&process_reader_, process_reader_thread)) {
|
||||
if (thread->Initialize(&process_reader_,
|
||||
process_reader_thread,
|
||||
budget_remaining_pointer)) {
|
||||
threads_.push_back(std::move(thread));
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +139,9 @@ class ProcessSnapshotLinux final : public ProcessSnapshot {
|
||||
void InitializeModules();
|
||||
void InitializeAnnotations();
|
||||
|
||||
// Initializes options_ on behalf of Initialize().
|
||||
void GetCrashpadOptionsInternal(CrashpadInfoClientOptions* options);
|
||||
|
||||
std::map<std::string, std::string> annotations_simple_map_;
|
||||
timeval snapshot_time_;
|
||||
UUID report_id_;
|
||||
@ -149,6 +152,7 @@ class ProcessSnapshotLinux final : public ProcessSnapshot {
|
||||
internal::SystemSnapshotLinux system_;
|
||||
ProcessReaderLinux process_reader_;
|
||||
ProcessMemoryRange memory_range_;
|
||||
CrashpadInfoClientOptions options_;
|
||||
InitializationStateDcheck initialized_;
|
||||
};
|
||||
|
||||
|
@ -47,7 +47,9 @@ TEST(SystemSnapshotLinux, Basic) {
|
||||
|
||||
uint64_t current_hz, max_hz;
|
||||
system.CPUFrequency(¤t_hz, &max_hz);
|
||||
EXPECT_GE(max_hz, current_hz);
|
||||
// For short-term loads, modern CPUs can boost single-core frequency beyond
|
||||
// the advertised base clock. Let's assume this is no more than a factor 2.
|
||||
EXPECT_GE(max_hz * 2, current_hz);
|
||||
|
||||
int major, minor, bugfix;
|
||||
std::string build;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <sched.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "snapshot/linux/capture_memory_delegate_linux.h"
|
||||
#include "snapshot/linux/cpu_context_linux.h"
|
||||
#include "util/misc/reinterpret_bytes.h"
|
||||
|
||||
@ -138,8 +139,10 @@ ThreadSnapshotLinux::ThreadSnapshotLinux()
|
||||
|
||||
ThreadSnapshotLinux::~ThreadSnapshotLinux() {}
|
||||
|
||||
bool ThreadSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
|
||||
const ProcessReaderLinux::Thread& thread) {
|
||||
bool ThreadSnapshotLinux::Initialize(
|
||||
ProcessReaderLinux* process_reader,
|
||||
const ProcessReaderLinux::Thread& thread,
|
||||
uint32_t* gather_indirectly_referenced_memory_bytes_remaining) {
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
@ -205,6 +208,13 @@ bool ThreadSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
|
||||
thread.static_priority, thread.sched_policy, thread.nice_value)
|
||||
: -1;
|
||||
|
||||
CaptureMemoryDelegateLinux capture_memory_delegate(
|
||||
process_reader,
|
||||
&thread,
|
||||
&pointed_to_memory_,
|
||||
gather_indirectly_referenced_memory_bytes_remaining);
|
||||
CaptureMemory::PointedToByContext(context_, &capture_memory_delegate);
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
@ -240,7 +250,13 @@ uint64_t ThreadSnapshotLinux::ThreadSpecificDataAddress() const {
|
||||
}
|
||||
|
||||
std::vector<const MemorySnapshot*> ThreadSnapshotLinux::ExtraMemory() const {
|
||||
return std::vector<const MemorySnapshot*>();
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
std::vector<const MemorySnapshot*> result;
|
||||
result.reserve(pointed_to_memory_.size());
|
||||
for (const auto& pointed_to_memory : pointed_to_memory_) {
|
||||
result.push_back(pointed_to_memory.get());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -47,8 +47,10 @@ class ThreadSnapshotLinux final : public ThreadSnapshot {
|
||||
//!
|
||||
//! \return `true` if the snapshot could be created, `false` otherwise with
|
||||
//! a message logged.
|
||||
bool Initialize(ProcessReaderLinux* process_reader,
|
||||
const ProcessReaderLinux::Thread& thread);
|
||||
bool Initialize(
|
||||
ProcessReaderLinux* process_reader,
|
||||
const ProcessReaderLinux::Thread& thread,
|
||||
uint32_t* gather_indirectly_referenced_memory_bytes_remaining);
|
||||
|
||||
// ThreadSnapshot:
|
||||
|
||||
@ -81,6 +83,7 @@ class ThreadSnapshotLinux final : public ThreadSnapshot {
|
||||
pid_t thread_id_;
|
||||
int priority_;
|
||||
InitializationStateDcheck initialized_;
|
||||
std::vector<std::unique_ptr<MemorySnapshotGeneric>> pointed_to_memory_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "util/win/xp_compat.h"
|
||||
#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
#include "snapshot/linux/process_snapshot_linux.h"
|
||||
#include "util/linux/direct_ptrace_connection.h"
|
||||
#endif // OS_APPLE
|
||||
|
||||
namespace crashpad {
|
||||
@ -198,8 +199,12 @@ int GenerateDumpMain(int argc, char* argv[]) {
|
||||
}
|
||||
#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
// TODO(jperaza): https://crashpad.chromium.org/bug/30.
|
||||
DirectPtraceConnection task;
|
||||
if (!task.Initialize(options.pid)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ProcessSnapshotLinux process_snapshot;
|
||||
if (!process_snapshot.Initialize(nullptr)) {
|
||||
if (!process_snapshot.Initialize(&task)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif // OS_APPLE
|
||||
|
@ -227,6 +227,12 @@ class FullReverseIterator : public MemoryMap::Iterator {
|
||||
std::vector<MemoryMap::Mapping>::const_reverse_iterator rend_;
|
||||
};
|
||||
|
||||
// Faster than a CheckedRange, for temporary values.
|
||||
struct FastRange {
|
||||
VMAddress base;
|
||||
VMSize size;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
MemoryMap::Mapping::Mapping()
|
||||
@ -321,6 +327,57 @@ const MemoryMap::Mapping* MemoryMap::FindMappingWithName(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<CheckedRange<VMAddress>> MemoryMap::GetReadableRanges(
|
||||
const CheckedRange<VMAddress, VMSize>& range) const {
|
||||
using Range = CheckedRange<VMAddress, VMSize>;
|
||||
|
||||
VMAddress range_base = range.base();
|
||||
VMAddress range_end = range.end();
|
||||
std::vector<FastRange> overlapping;
|
||||
|
||||
// Find all readable ranges overlapping the target range, maintaining order.
|
||||
for (const auto& mapping : mappings_) {
|
||||
if (!mapping.readable)
|
||||
continue;
|
||||
if (mapping.range.End() < range_base)
|
||||
continue;
|
||||
if (mapping.range.Base() >= range_end)
|
||||
continue;
|
||||
// Special case: the "[vvar]" region is marked readable, but we can't
|
||||
// access it.
|
||||
if (mapping.inode == 0 && mapping.name == "[vvar]")
|
||||
continue;
|
||||
overlapping.push_back({mapping.range.Base(), mapping.range.Size()});
|
||||
}
|
||||
if (overlapping.empty())
|
||||
return std::vector<Range>();
|
||||
|
||||
// For the first and last, trim to the boundary of the incoming range.
|
||||
FastRange& front = overlapping.front();
|
||||
VMAddress original_front_base = front.base;
|
||||
front.base = std::max(front.base, range_base);
|
||||
front.size = (original_front_base + front.size) - front.base;
|
||||
FastRange& back = overlapping.back();
|
||||
VMAddress back_end = back.base + back.size;
|
||||
back.size = std::min(range_end, back_end) - back.base;
|
||||
|
||||
// Coalesce, and convert to return type.
|
||||
std::vector<Range> result;
|
||||
result.push_back({overlapping[0].base, overlapping[0].size});
|
||||
DCHECK(result.back().IsValid());
|
||||
for (size_t i = 1; i < overlapping.size(); ++i) {
|
||||
if (result.back().end() == overlapping[i].base) {
|
||||
result.back().SetRange(result.back().base(),
|
||||
result.back().size() + overlapping[i].size);
|
||||
} else {
|
||||
result.push_back({overlapping[i].base, overlapping[i].size});
|
||||
}
|
||||
DCHECK(result.back().IsValid());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<MemoryMap::Iterator> MemoryMap::FindFilePossibleMmapStarts(
|
||||
const Mapping& mapping) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
@ -77,6 +77,16 @@ class MemoryMap {
|
||||
//! it was obtained from.
|
||||
const Mapping* FindMappingWithName(const std::string& name) const;
|
||||
|
||||
//! \brief Given a range to be read from the target process, returns a vector
|
||||
//! of ranges, representing the readable portions of the original range.
|
||||
//!
|
||||
//! \param[in] range The range being identified.
|
||||
//!
|
||||
//! \return A vector of ranges corresponding to the portion of \a range that
|
||||
//! is readable based on the memory map.
|
||||
std::vector<CheckedRange<uint64_t>> GetReadableRanges(
|
||||
const CheckedRange<LinuxVMAddress, LinuxVMSize>& range) const;
|
||||
|
||||
//! \brief An abstract base class for iterating over ordered sets of mappings
|
||||
//! in a MemoryMap.
|
||||
class Iterator {
|
||||
|
Loading…
x
Reference in New Issue
Block a user