Have MinidumpMemoryListWriter deal directly in SnapshotMinidumpMemoryWriters

This is as a precursor to
https://chromium-review.googlesource.com/374539 which merges
MemorySnapshots and so needs to be able to update them from the minidump
code.

MinidumpMemoryWriter existed to be able to mock for tests; that
behaviour is wrapped up in TestMemorySnapshot now.

BUG=crashpad:61, chromium:638370

Change-Id: I825ec57493b12fc1848018585c14544faa7e66d4
Reviewed-on: https://chromium-review.googlesource.com/374019
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Scott Graham 2016-08-25 15:01:27 -07:00
parent 357c7c7b7b
commit c6f88d164e
6 changed files with 87 additions and 189 deletions

View File

@ -24,32 +24,27 @@
#include "util/numeric/safe_assignment.h" #include "util/numeric/safe_assignment.h"
namespace crashpad { namespace crashpad {
namespace {
class SnapshotMinidumpMemoryWriter final : public MinidumpMemoryWriter, SnapshotMinidumpMemoryWriter::SnapshotMinidumpMemoryWriter(
public MemorySnapshot::Delegate { const MemorySnapshot* memory_snapshot)
public: : internal::MinidumpWritable(),
explicit SnapshotMinidumpMemoryWriter(const MemorySnapshot* memory_snapshot)
: MinidumpMemoryWriter(),
MemorySnapshot::Delegate(), MemorySnapshot::Delegate(),
memory_descriptor_(),
registered_memory_descriptors_(),
memory_snapshot_(memory_snapshot), memory_snapshot_(memory_snapshot),
file_writer_(nullptr) { file_writer_(nullptr) {}
}
~SnapshotMinidumpMemoryWriter() override {} SnapshotMinidumpMemoryWriter::~SnapshotMinidumpMemoryWriter() {}
// MemorySnapshot::Delegate: bool SnapshotMinidumpMemoryWriter::MemorySnapshotDelegateRead(void* data,
size_t size) {
bool MemorySnapshotDelegateRead(void* data, size_t size) override {
DCHECK_EQ(state(), kStateWritable); DCHECK_EQ(state(), kStateWritable);
DCHECK_EQ(size, MemoryRangeSize()); DCHECK_EQ(size, UnderlyingSnapshot().Size());
return file_writer_->Write(data, size); return file_writer_->Write(data, size);
} }
protected: bool SnapshotMinidumpMemoryWriter::WriteObject(
// MinidumpMemoryWriter: FileWriterInterface* file_writer) {
bool WriteObject(FileWriterInterface* file_writer) override {
DCHECK_EQ(state(), kStateWritable); DCHECK_EQ(state(), kStateWritable);
DCHECK(!file_writer_); DCHECK(!file_writer_);
@ -60,41 +55,14 @@ class SnapshotMinidumpMemoryWriter final : public MinidumpMemoryWriter,
return memory_snapshot_->Read(this); return memory_snapshot_->Read(this);
} }
uint64_t MemoryRangeBaseAddress() const override {
DCHECK_EQ(state(), kStateFrozen);
return memory_snapshot_->Address();
}
size_t MemoryRangeSize() const override {
DCHECK_GE(state(), kStateFrozen);
return memory_snapshot_->Size();
}
private:
const MemorySnapshot* memory_snapshot_;
FileWriterInterface* file_writer_;
DISALLOW_COPY_AND_ASSIGN(SnapshotMinidumpMemoryWriter);
};
} // namespace
MinidumpMemoryWriter::~MinidumpMemoryWriter() {
}
std::unique_ptr<MinidumpMemoryWriter> MinidumpMemoryWriter::CreateFromSnapshot(
const MemorySnapshot* memory_snapshot) {
return base::WrapUnique(new SnapshotMinidumpMemoryWriter(memory_snapshot));
}
const MINIDUMP_MEMORY_DESCRIPTOR* const MINIDUMP_MEMORY_DESCRIPTOR*
MinidumpMemoryWriter::MinidumpMemoryDescriptor() const { SnapshotMinidumpMemoryWriter::MinidumpMemoryDescriptor() const {
DCHECK_EQ(state(), kStateWritable); DCHECK_EQ(state(), kStateWritable);
return &memory_descriptor_; return &memory_descriptor_;
} }
void MinidumpMemoryWriter::RegisterMemoryDescriptor( void SnapshotMinidumpMemoryWriter::RegisterMemoryDescriptor(
MINIDUMP_MEMORY_DESCRIPTOR* memory_descriptor) { MINIDUMP_MEMORY_DESCRIPTOR* memory_descriptor) {
DCHECK_LE(state(), kStateFrozen); DCHECK_LE(state(), kStateFrozen);
@ -102,13 +70,7 @@ void MinidumpMemoryWriter::RegisterMemoryDescriptor(
RegisterLocationDescriptor(&memory_descriptor->Memory); RegisterLocationDescriptor(&memory_descriptor->Memory);
} }
MinidumpMemoryWriter::MinidumpMemoryWriter() bool SnapshotMinidumpMemoryWriter::Freeze() {
: MinidumpWritable(),
memory_descriptor_(),
registered_memory_descriptors_() {
}
bool MinidumpMemoryWriter::Freeze() {
DCHECK_EQ(state(), kStateMutable); DCHECK_EQ(state(), kStateMutable);
if (!MinidumpWritable::Freeze()) { if (!MinidumpWritable::Freeze()) {
@ -120,26 +82,26 @@ bool MinidumpMemoryWriter::Freeze() {
return true; return true;
} }
size_t MinidumpMemoryWriter::Alignment() { size_t SnapshotMinidumpMemoryWriter::Alignment() {
DCHECK_GE(state(), kStateFrozen); DCHECK_GE(state(), kStateFrozen);
return 16; return 16;
} }
size_t MinidumpMemoryWriter::SizeOfObject() { size_t SnapshotMinidumpMemoryWriter::SizeOfObject() {
DCHECK_GE(state(), kStateFrozen); DCHECK_GE(state(), kStateFrozen);
return MemoryRangeSize(); return UnderlyingSnapshot().Size();
} }
bool MinidumpMemoryWriter::WillWriteAtOffsetImpl(FileOffset offset) { bool SnapshotMinidumpMemoryWriter::WillWriteAtOffsetImpl(FileOffset offset) {
DCHECK_EQ(state(), kStateFrozen); DCHECK_EQ(state(), kStateFrozen);
// There will always be at least one registered descriptor, the one for this // There will always be at least one registered descriptor, the one for this
// objects own memory_descriptor_ field. // objects own memory_descriptor_ field.
DCHECK_GE(registered_memory_descriptors_.size(), 1u); DCHECK_GE(registered_memory_descriptors_.size(), 1u);
uint64_t base_address = MemoryRangeBaseAddress(); uint64_t base_address = UnderlyingSnapshot().Address();
decltype(registered_memory_descriptors_[0]->StartOfMemoryRange) local_address; decltype(registered_memory_descriptors_[0]->StartOfMemoryRange) local_address;
if (!AssignIfInRange(&local_address, base_address)) { if (!AssignIfInRange(&local_address, base_address)) {
LOG(ERROR) << "base_address " << base_address << " out of range"; LOG(ERROR) << "base_address " << base_address << " out of range";
@ -154,7 +116,7 @@ bool MinidumpMemoryWriter::WillWriteAtOffsetImpl(FileOffset offset) {
return MinidumpWritable::WillWriteAtOffsetImpl(offset); return MinidumpWritable::WillWriteAtOffsetImpl(offset);
} }
internal::MinidumpWritable::Phase MinidumpMemoryWriter::WritePhase() { internal::MinidumpWritable::Phase SnapshotMinidumpMemoryWriter::WritePhase() {
// Memory dumps are large and are unlikely to be consumed in their entirety. // Memory dumps are large and are unlikely to be consumed in their entirety.
// Data accesses are expected to be sparse and sporadic, and are expected to // Data accesses are expected to be sparse and sporadic, and are expected to
// occur after all of the other structural and informational data from the // occur after all of the other structural and informational data from the
@ -178,14 +140,14 @@ void MinidumpMemoryListWriter::AddFromSnapshot(
DCHECK_EQ(state(), kStateMutable); DCHECK_EQ(state(), kStateMutable);
for (const MemorySnapshot* memory_snapshot : memory_snapshots) { for (const MemorySnapshot* memory_snapshot : memory_snapshots) {
std::unique_ptr<MinidumpMemoryWriter> memory = std::unique_ptr<SnapshotMinidumpMemoryWriter> memory(
MinidumpMemoryWriter::CreateFromSnapshot(memory_snapshot); new SnapshotMinidumpMemoryWriter(memory_snapshot));
AddMemory(std::move(memory)); AddMemory(std::move(memory));
} }
} }
void MinidumpMemoryListWriter::AddMemory( void MinidumpMemoryListWriter::AddMemory(
std::unique_ptr<MinidumpMemoryWriter> memory_writer) { std::unique_ptr<SnapshotMinidumpMemoryWriter> memory_writer) {
DCHECK_EQ(state(), kStateMutable); DCHECK_EQ(state(), kStateMutable);
AddExtraMemory(memory_writer.get()); AddExtraMemory(memory_writer.get());
@ -193,7 +155,7 @@ void MinidumpMemoryListWriter::AddMemory(
} }
void MinidumpMemoryListWriter::AddExtraMemory( void MinidumpMemoryListWriter::AddExtraMemory(
MinidumpMemoryWriter* memory_writer) { SnapshotMinidumpMemoryWriter* memory_writer) {
DCHECK_EQ(state(), kStateMutable); DCHECK_EQ(state(), kStateMutable);
memory_writers_.push_back(memory_writer); memory_writers_.push_back(memory_writer);
@ -232,7 +194,7 @@ std::vector<internal::MinidumpWritable*> MinidumpMemoryListWriter::Children() {
DCHECK_LE(children_.size(), memory_writers_.size()); DCHECK_LE(children_.size(), memory_writers_.size());
std::vector<MinidumpWritable*> children; std::vector<MinidumpWritable*> children;
for (MinidumpMemoryWriter* child : children_) { for (SnapshotMinidumpMemoryWriter* child : children_) {
children.push_back(child); children.push_back(child);
} }
@ -247,7 +209,7 @@ bool MinidumpMemoryListWriter::WriteObject(FileWriterInterface* file_writer) {
iov.iov_len = sizeof(memory_list_base_); iov.iov_len = sizeof(memory_list_base_);
std::vector<WritableIoVec> iovecs(1, iov); std::vector<WritableIoVec> iovecs(1, iov);
for (const MinidumpMemoryWriter* memory_writer : memory_writers_) { for (const SnapshotMinidumpMemoryWriter* memory_writer : memory_writers_) {
iov.iov_base = memory_writer->MinidumpMemoryDescriptor(); iov.iov_base = memory_writer->MinidumpMemoryDescriptor();
iov.iov_len = sizeof(MINIDUMP_MEMORY_DESCRIPTOR); iov.iov_len = sizeof(MINIDUMP_MEMORY_DESCRIPTOR);
iovecs.push_back(iov); iovecs.push_back(iov);

View File

@ -26,34 +26,19 @@
#include "base/macros.h" #include "base/macros.h"
#include "minidump/minidump_stream_writer.h" #include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h" #include "minidump/minidump_writable.h"
#include "snapshot/memory_snapshot.h"
#include "util/file/file_io.h" #include "util/file/file_io.h"
#include "util/stdlib/pointer_container.h" #include "util/stdlib/pointer_container.h"
namespace crashpad { namespace crashpad {
class MemorySnapshot;
//! \brief The base class for writers of memory ranges pointed to by //! \brief The base class for writers of memory ranges pointed to by
//! MINIDUMP_MEMORY_DESCRIPTOR objects in a minidump file. //! MINIDUMP_MEMORY_DESCRIPTOR objects in a minidump file.
//! class SnapshotMinidumpMemoryWriter : public internal::MinidumpWritable,
//! This is an abstract base class because users are expected to provide their public MemorySnapshot::Delegate {
//! own implementations that, when possible, obtain the memory contents
//! on-demand in their WriteObject() methods. Memory ranges may be large, and
//! the alternative construction would require the contents of multiple ranges
//! to be held in memory simultaneously while a minidump file is being written.
class MinidumpMemoryWriter : public internal::MinidumpWritable {
public: public:
~MinidumpMemoryWriter() override; explicit SnapshotMinidumpMemoryWriter(const MemorySnapshot* memory_snapshot);
~SnapshotMinidumpMemoryWriter() override;
//! \brief Creates a concrete initialized MinidumpMemoryWriter based on \a
//! memory_snapshot.
//!
//! \param[in] memory_snapshot The memory snapshot to use as source data.
//!
//! \return An object of a MinidumpMemoryWriter subclass initialized using the
//! source data in \a memory_snapshot.
static std::unique_ptr<MinidumpMemoryWriter> CreateFromSnapshot(
const MemorySnapshot* memory_snapshot);
//! \brief Returns a MINIDUMP_MEMORY_DESCRIPTOR referencing the data that this //! \brief Returns a MINIDUMP_MEMORY_DESCRIPTOR referencing the data that this
//! object writes. //! object writes.
@ -76,24 +61,14 @@ class MinidumpMemoryWriter : public internal::MinidumpWritable {
//! \note Valid in #kStateFrozen or any preceding state. //! \note Valid in #kStateFrozen or any preceding state.
void RegisterMemoryDescriptor(MINIDUMP_MEMORY_DESCRIPTOR* memory_descriptor); void RegisterMemoryDescriptor(MINIDUMP_MEMORY_DESCRIPTOR* memory_descriptor);
protected: private:
MinidumpMemoryWriter(); // MemorySnapshot::Delegate:
bool MemorySnapshotDelegateRead(void* data, size_t size) override;
//! \brief Returns the base address of the memory region in the address space
//! of the process that the snapshot describes.
//!
//! \note This method will only be called in #kStateFrozen.
virtual uint64_t MemoryRangeBaseAddress() const = 0;
//! \brief Returns the size of the memory region in bytes.
//!
//! \note This method will only be called in #kStateFrozen or a subsequent
//! state.
virtual size_t MemoryRangeSize() const = 0;
// MinidumpWritable: // MinidumpWritable:
bool Freeze() override; bool Freeze() override;
size_t SizeOfObject() final; size_t SizeOfObject() final;
bool WriteObject(FileWriterInterface* file_writer) override;
//! \brief Returns the objects desired byte-boundary alignment. //! \brief Returns the objects desired byte-boundary alignment.
//! //!
@ -119,13 +94,18 @@ class MinidumpMemoryWriter : public internal::MinidumpWritable {
//! \note Valid in any state. //! \note Valid in any state.
Phase WritePhase() final; Phase WritePhase() final;
private: //! \brief Gets the underlying memory snapshot that the memory writer will
//! write to the minidump.
const MemorySnapshot& UnderlyingSnapshot() const { return *memory_snapshot_; }
MINIDUMP_MEMORY_DESCRIPTOR memory_descriptor_; MINIDUMP_MEMORY_DESCRIPTOR memory_descriptor_;
// weak // weak
std::vector<MINIDUMP_MEMORY_DESCRIPTOR*> registered_memory_descriptors_; std::vector<MINIDUMP_MEMORY_DESCRIPTOR*> registered_memory_descriptors_;
const MemorySnapshot* memory_snapshot_;
FileWriterInterface* file_writer_;
DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryWriter); DISALLOW_COPY_AND_ASSIGN(SnapshotMinidumpMemoryWriter);
}; };
//! \brief The writer for a MINIDUMP_MEMORY_LIST stream in a minidump file, //! \brief The writer for a MINIDUMP_MEMORY_LIST stream in a minidump file,
@ -135,8 +115,8 @@ class MinidumpMemoryListWriter final : public internal::MinidumpStreamWriter {
MinidumpMemoryListWriter(); MinidumpMemoryListWriter();
~MinidumpMemoryListWriter() override; ~MinidumpMemoryListWriter() override;
//! \brief Adds a concrete initialized MinidumpMemoryWriter for each memory //! \brief Adds a concrete initialized SnapshotMinidumpMemoryWriter for each
//! snapshot in \a memory_snapshots to the MINIDUMP_MEMORY_LIST. //! memory snapshot in \a memory_snapshots to the MINIDUMP_MEMORY_LIST.
//! //!
//! Memory snapshots are added in the fashion of AddMemory(). //! Memory snapshots are added in the fashion of AddMemory().
//! //!
@ -146,15 +126,15 @@ class MinidumpMemoryListWriter final : public internal::MinidumpStreamWriter {
void AddFromSnapshot( void AddFromSnapshot(
const std::vector<const MemorySnapshot*>& memory_snapshots); const std::vector<const MemorySnapshot*>& memory_snapshots);
//! \brief Adds a MinidumpMemoryWriter to the MINIDUMP_MEMORY_LIST. //! \brief Adds a SnapshotMinidumpMemoryWriter to the MINIDUMP_MEMORY_LIST.
//! //!
//! This object takes ownership of \a memory_writer and becomes its parent in //! This object takes ownership of \a memory_writer and becomes its parent in
//! the overall tree of internal::MinidumpWritable objects. //! the overall tree of internal::MinidumpWritable objects.
//! //!
//! \note Valid in #kStateMutable. //! \note Valid in #kStateMutable.
void AddMemory(std::unique_ptr<MinidumpMemoryWriter> memory_writer); void AddMemory(std::unique_ptr<SnapshotMinidumpMemoryWriter> memory_writer);
//! \brief Adds a MinidumpMemoryWriter thats a child of another //! \brief Adds a SnapshotMinidumpMemoryWriter thats a child of another
//! internal::MinidumpWritable object to the MINIDUMP_MEMORY_LIST. //! internal::MinidumpWritable object to the MINIDUMP_MEMORY_LIST.
//! //!
//! \a memory_writer does not become a child of this object, but the //! \a memory_writer does not become a child of this object, but the
@ -163,12 +143,12 @@ class MinidumpMemoryListWriter final : public internal::MinidumpStreamWriter {
//! internal::MinidumpWritable tree. //! internal::MinidumpWritable tree.
//! //!
//! This method exists to be called by objects that have their own //! This method exists to be called by objects that have their own
//! MinidumpMemoryWriter children but wish for them to also appear in the //! SnapshotMinidumpMemoryWriter children but wish for them to also appear in
//! minidump files MINIDUMP_MEMORY_LIST. MinidumpThreadWriter, which has a //! the minidump files MINIDUMP_MEMORY_LIST. MinidumpThreadWriter, which has
//! MinidumpMemoryWriter for thread stack memory, is an example. //! a SnapshotMinidumpMemoryWriter for thread stack memory, is an example.
//! //!
//! \note Valid in #kStateMutable. //! \note Valid in #kStateMutable.
void AddExtraMemory(MinidumpMemoryWriter* memory_writer); void AddExtraMemory(SnapshotMinidumpMemoryWriter* memory_writer);
protected: protected:
// MinidumpWritable: // MinidumpWritable:
@ -181,8 +161,8 @@ class MinidumpMemoryListWriter final : public internal::MinidumpStreamWriter {
MinidumpStreamType StreamType() const override; MinidumpStreamType StreamType() const override;
private: private:
std::vector<MinidumpMemoryWriter*> memory_writers_; // weak std::vector<SnapshotMinidumpMemoryWriter*> memory_writers_; // weak
PointerVector<MinidumpMemoryWriter> children_; PointerVector<SnapshotMinidumpMemoryWriter> children_;
MINIDUMP_MEMORY_LIST memory_list_base_; MINIDUMP_MEMORY_LIST memory_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryListWriter); DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryListWriter);

View File

@ -51,8 +51,8 @@ void MinidumpThreadWriter::InitializeFromSnapshot(
const MemorySnapshot* stack_snapshot = thread_snapshot->Stack(); const MemorySnapshot* stack_snapshot = thread_snapshot->Stack();
if (stack_snapshot && stack_snapshot->Size() > 0) { if (stack_snapshot && stack_snapshot->Size() > 0) {
std::unique_ptr<MinidumpMemoryWriter> stack = std::unique_ptr<SnapshotMinidumpMemoryWriter> stack(
MinidumpMemoryWriter::CreateFromSnapshot(stack_snapshot); new SnapshotMinidumpMemoryWriter(stack_snapshot));
SetStack(std::move(stack)); SetStack(std::move(stack));
} }
@ -68,7 +68,7 @@ const MINIDUMP_THREAD* MinidumpThreadWriter::MinidumpThread() const {
} }
void MinidumpThreadWriter::SetStack( void MinidumpThreadWriter::SetStack(
std::unique_ptr<MinidumpMemoryWriter> stack) { std::unique_ptr<SnapshotMinidumpMemoryWriter> stack) {
DCHECK_EQ(state(), kStateMutable); DCHECK_EQ(state(), kStateMutable);
stack_ = std::move(stack); stack_ = std::move(stack);
@ -172,7 +172,7 @@ void MinidumpThreadListWriter::AddThread(
DCHECK_EQ(state(), kStateMutable); DCHECK_EQ(state(), kStateMutable);
if (memory_list_writer_) { if (memory_list_writer_) {
MinidumpMemoryWriter* stack = thread->Stack(); SnapshotMinidumpMemoryWriter* stack = thread->Stack();
if (stack) { if (stack) {
memory_list_writer_->AddExtraMemory(stack); memory_list_writer_->AddExtraMemory(stack);
} }

View File

@ -33,7 +33,7 @@ namespace crashpad {
class MinidumpContextWriter; class MinidumpContextWriter;
class MinidumpMemoryListWriter; class MinidumpMemoryListWriter;
class MinidumpMemoryWriter; class SnapshotMinidumpMemoryWriter;
class ThreadSnapshot; class ThreadSnapshot;
//! \brief The writer for a MINIDUMP_THREAD object in a minidump file. //! \brief The writer for a MINIDUMP_THREAD object in a minidump file.
@ -67,8 +67,8 @@ class MinidumpThreadWriter final : public internal::MinidumpWritable {
//! \note Valid in #kStateWritable. //! \note Valid in #kStateWritable.
const MINIDUMP_THREAD* MinidumpThread() const; const MINIDUMP_THREAD* MinidumpThread() const;
//! \brief Returns a MinidumpMemoryWriter that will write the memory region //! \brief Returns a SnapshotMinidumpMemoryWriter that will write the memory
//! corresponding to this objects stack. //! region corresponding to this objects stack.
//! //!
//! If the thread does not have a stack, or its stack could not be determined, //! If the thread does not have a stack, or its stack could not be determined,
//! this will return `nullptr`. //! this will return `nullptr`.
@ -80,7 +80,7 @@ class MinidumpThreadWriter final : public internal::MinidumpWritable {
//! MinidumpMemoryListWriter::AddExtraMemory(). //! MinidumpMemoryListWriter::AddExtraMemory().
//! //!
//! \note Valid in any state. //! \note Valid in any state.
MinidumpMemoryWriter* Stack() const { return stack_.get(); } SnapshotMinidumpMemoryWriter* Stack() const { return stack_.get(); }
//! \brief Arranges for MINIDUMP_THREAD::Stack to point to the MINIDUMP_MEMORY //! \brief Arranges for MINIDUMP_THREAD::Stack to point to the MINIDUMP_MEMORY
//! object to be written by \a stack. //! object to be written by \a stack.
@ -89,7 +89,7 @@ class MinidumpThreadWriter final : public internal::MinidumpWritable {
//! overall tree of internal::MinidumpWritable objects. //! overall tree of internal::MinidumpWritable objects.
//! //!
//! \note Valid in #kStateMutable. //! \note Valid in #kStateMutable.
void SetStack(std::unique_ptr<MinidumpMemoryWriter> stack); void SetStack(std::unique_ptr<SnapshotMinidumpMemoryWriter> stack);
//! \brief Arranges for MINIDUMP_THREAD::ThreadContext to point to the CPU //! \brief Arranges for MINIDUMP_THREAD::ThreadContext to point to the CPU
//! context to be written by \a context. //! context to be written by \a context.
@ -130,7 +130,7 @@ class MinidumpThreadWriter final : public internal::MinidumpWritable {
private: private:
MINIDUMP_THREAD thread_; MINIDUMP_THREAD thread_;
std::unique_ptr<MinidumpMemoryWriter> stack_; std::unique_ptr<SnapshotMinidumpMemoryWriter> stack_;
std::unique_ptr<MinidumpContextWriter> context_; std::unique_ptr<MinidumpContextWriter> context_;
DISALLOW_COPY_AND_ASSIGN(MinidumpThreadWriter); DISALLOW_COPY_AND_ASSIGN(MinidumpThreadWriter);
@ -161,9 +161,9 @@ class MinidumpThreadListWriter final : public internal::MinidumpStreamWriter {
//! region should be added to as extra memory. //! region should be added to as extra memory.
//! //!
//! Each MINIDUMP_THREAD object can contain a reference to a //! Each MINIDUMP_THREAD object can contain a reference to a
//! MinidumpMemoryWriter object that contains a snapshot of its stack memory. //! SnapshotMinidumpMemoryWriter object that contains a snapshot of its stac
//! In the overall tree of internal::MinidumpWritable objects, these //! memory. In the overall tree of internal::MinidumpWritable objects, these
//! MinidumpMemoryWriter objects are considered children of their //! SnapshotMinidumpMemoryWriter objects are considered children of their
//! MINIDUMP_THREAD, and are referenced by a MINIDUMP_MEMORY_DESCRIPTOR //! MINIDUMP_THREAD, and are referenced by a MINIDUMP_MEMORY_DESCRIPTOR
//! contained in the MINIDUMP_THREAD. It is also possible for the same memory //! contained in the MINIDUMP_THREAD. It is also possible for the same memory
//! regions to have MINIDUMP_MEMORY_DESCRIPTOR objects present in a //! regions to have MINIDUMP_MEMORY_DESCRIPTOR objects present in a

View File

@ -22,48 +22,15 @@ namespace test {
TestMinidumpMemoryWriter::TestMinidumpMemoryWriter(uint64_t base_address, TestMinidumpMemoryWriter::TestMinidumpMemoryWriter(uint64_t base_address,
size_t size, size_t size,
uint8_t value) uint8_t value)
: MinidumpMemoryWriter(), : SnapshotMinidumpMemoryWriter(&test_snapshot_) {
base_address_(base_address), test_snapshot_.SetAddress(base_address);
expected_offset_(-1), test_snapshot_.SetSize(size);
size_(size), test_snapshot_.SetValue(value);
value_(value) {
} }
TestMinidumpMemoryWriter::~TestMinidumpMemoryWriter() { TestMinidumpMemoryWriter::~TestMinidumpMemoryWriter() {
} }
uint64_t TestMinidumpMemoryWriter::MemoryRangeBaseAddress() const {
EXPECT_EQ(state(), kStateFrozen);
return base_address_;
}
size_t TestMinidumpMemoryWriter::MemoryRangeSize() const {
EXPECT_GE(state(), kStateFrozen);
return size_;
}
bool TestMinidumpMemoryWriter::WillWriteAtOffsetImpl(FileOffset offset) {
EXPECT_EQ(state(), kStateFrozen);
expected_offset_ = offset;
bool rv = MinidumpMemoryWriter::WillWriteAtOffsetImpl(offset);
EXPECT_TRUE(rv);
return rv;
}
bool TestMinidumpMemoryWriter::WriteObject(FileWriterInterface* file_writer) {
EXPECT_EQ(state(), kStateWritable);
EXPECT_EQ(expected_offset_, file_writer->Seek(0, SEEK_CUR));
bool rv = true;
if (size_ > 0) {
std::string data(size_, value_);
rv = file_writer->Write(&data[0], size_);
EXPECT_TRUE(rv);
}
return rv;
}
void ExpectMinidumpMemoryDescriptor( void ExpectMinidumpMemoryDescriptor(
const MINIDUMP_MEMORY_DESCRIPTOR* expected, const MINIDUMP_MEMORY_DESCRIPTOR* expected,
const MINIDUMP_MEMORY_DESCRIPTOR* observed) { const MINIDUMP_MEMORY_DESCRIPTOR* observed) {

View File

@ -25,34 +25,23 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "snapshot/test/test_memory_snapshot.h"
#include "util/file/file_writer.h" #include "util/file/file_writer.h"
namespace crashpad { namespace crashpad {
namespace test { namespace test {
//! \brief A MinidumpMemoryWriter implementation used for testing. //! \brief A SnapshotMinidumpMemoryWriter implementation used for testing.
//! //!
//! TestMinidumpMemoryWriter objects are created with a fixed base address and //! TestMinidumpMemoryWriter objects are created with a fixed base address and
//! size, and will write the same byte (\a value) repeatedly, \a size times. //! size, and will write the same byte (\a value) repeatedly, \a size times.
class TestMinidumpMemoryWriter final : public MinidumpMemoryWriter { class TestMinidumpMemoryWriter final : public SnapshotMinidumpMemoryWriter {
public: public:
TestMinidumpMemoryWriter(uint64_t base_address, size_t size, uint8_t value); TestMinidumpMemoryWriter(uint64_t base_address, size_t size, uint8_t value);
~TestMinidumpMemoryWriter(); ~TestMinidumpMemoryWriter();
protected:
// MinidumpMemoryWriter:
uint64_t MemoryRangeBaseAddress() const override;
size_t MemoryRangeSize() const override;
// MinidumpWritable:
bool WillWriteAtOffsetImpl(FileOffset offset) override;
bool WriteObject(FileWriterInterface* file_writer) override;
private: private:
uint64_t base_address_; TestMemorySnapshot test_snapshot_;
FileOffset expected_offset_;
size_t size_;
uint8_t value_;
DISALLOW_COPY_AND_ASSIGN(TestMinidumpMemoryWriter); DISALLOW_COPY_AND_ASSIGN(TestMinidumpMemoryWriter);
}; };