Add MinidumpExceptionWriter::InitializeFromSnapshot() and test.

TEST=minidump_test MinidumpExceptionWriter.InitializeFromSnapshot
R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/698673002
This commit is contained in:
Mark Mentovai 2014-11-04 12:41:01 -05:00
parent 8248c030e2
commit 62b0976290
6 changed files with 246 additions and 0 deletions

View File

@ -18,6 +18,7 @@
#include "base/logging.h"
#include "minidump/minidump_context_writer.h"
#include "snapshot/exception_snapshot.h"
#include "util/file/file_writer.h"
namespace crashpad {
@ -29,6 +30,26 @@ MinidumpExceptionWriter::MinidumpExceptionWriter()
MinidumpExceptionWriter::~MinidumpExceptionWriter() {
}
void MinidumpExceptionWriter::InitializeFromSnapshot(
const ExceptionSnapshot* exception_snapshot,
const MinidumpThreadIDMap* thread_id_map) {
DCHECK_EQ(state(), kStateMutable);
DCHECK(!context_);
auto thread_id_it = thread_id_map->find(exception_snapshot->ThreadID());
DCHECK(thread_id_it != thread_id_map->end());
SetThreadID(thread_id_it->second);
SetExceptionCode(exception_snapshot->Exception());
SetExceptionFlags(exception_snapshot->ExceptionInfo());
SetExceptionAddress(exception_snapshot->ExceptionAddress());
SetExceptionInformation(exception_snapshot->Codes());
scoped_ptr<MinidumpContextWriter> context =
MinidumpContextWriter::CreateFromSnapshot(exception_snapshot->Context());
SetContext(context.Pass());
}
void MinidumpExceptionWriter::SetContext(
scoped_ptr<MinidumpContextWriter> context) {
DCHECK_EQ(state(), kStateMutable);

View File

@ -23,9 +23,11 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_thread_id_map.h"
namespace crashpad {
class ExceptionSnapshot;
class MinidumpContextWriter;
//! \brief The writer for a MINIDUMP_EXCEPTION_STREAM stream in a minidump file.
@ -34,6 +36,21 @@ class MinidumpExceptionWriter final : public internal::MinidumpStreamWriter {
MinidumpExceptionWriter();
~MinidumpExceptionWriter() override;
//! \brief Initializes the MINIDUMP_EXCEPTION_STREAM based on \a
//! exception_snapshot.
//!
//! \param[in] exception_snapshot The exception snapshot to use as source
//! data.
//! \param[in] thread_id_map A MinidumpThreadIDMap to be consulted to
//! determine the 32-bit minidump thread ID to use for the thread
//! identified by \a exception_snapshot.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ExceptionSnapshot* exception_snapshot,
const MinidumpThreadIDMap* thread_id_map);
//! \brief Arranges for MINIDUMP_EXCEPTION_STREAM::ThreadContext to point to
//! the CPU context to be written by \a context.
//!

View File

@ -26,9 +26,12 @@
#include "minidump/minidump_context_writer.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_file_writer.h"
#include "minidump/minidump_thread_id_map.h"
#include "minidump/test/minidump_context_test_util.h"
#include "minidump/test/minidump_file_writer_test_util.h"
#include "minidump/test/minidump_writable_test_util.h"
#include "snapshot/test/test_cpu_context.h"
#include "snapshot/test/test_exception_snapshot.h"
#include "util/file/string_file_writer.h"
namespace crashpad {
@ -194,6 +197,62 @@ TEST(MinidumpExceptionWriter, Standard) {
ExpectMinidumpContextX86(kSeed, observed_context, false));
}
TEST(MinidumpExceptionWriter, InitializeFromSnapshot) {
std::vector<uint64_t> exception_codes;
exception_codes.push_back(0x1000000000000000);
exception_codes.push_back(0x5555555555555555);
MINIDUMP_EXCEPTION_STREAM expect_exception = {};
expect_exception.ThreadId = 123;
expect_exception.ExceptionRecord.ExceptionCode = 100;
expect_exception.ExceptionRecord.ExceptionFlags = 1;
expect_exception.ExceptionRecord.ExceptionAddress = 0xfedcba9876543210;
expect_exception.ExceptionRecord.NumberParameters = exception_codes.size();
for (size_t index = 0; index < exception_codes.size(); ++index) {
expect_exception.ExceptionRecord.ExceptionInformation[index] =
exception_codes[index];
}
const uint64_t kThreadID = 0xaaaaaaaaaaaaaaaa;
const uint32_t kSeed = 65;
TestExceptionSnapshot exception_snapshot;
exception_snapshot.SetThreadID(kThreadID);
exception_snapshot.SetException(
expect_exception.ExceptionRecord.ExceptionCode);
exception_snapshot.SetExceptionInfo(
expect_exception.ExceptionRecord.ExceptionFlags);
exception_snapshot.SetExceptionAddress(
expect_exception.ExceptionRecord.ExceptionAddress);
exception_snapshot.SetCodes(exception_codes);
InitializeCPUContextX86(exception_snapshot.MutableContext(), kSeed);
MinidumpThreadIDMap thread_id_map;
thread_id_map[kThreadID] = expect_exception.ThreadId;
auto exception_writer = make_scoped_ptr(new MinidumpExceptionWriter());
exception_writer->InitializeFromSnapshot(&exception_snapshot, &thread_id_map);
MinidumpFileWriter minidump_file_writer;
minidump_file_writer.AddStream(exception_writer.Pass());
StringFileWriter file_writer;
ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
const MINIDUMP_EXCEPTION_STREAM* exception;
ASSERT_NO_FATAL_FAILURE(GetExceptionStream(file_writer.string(), &exception));
const MinidumpContextX86* observed_context;
ASSERT_NO_FATAL_FAILURE(ExpectExceptionStream(&expect_exception,
exception,
file_writer.string(),
&observed_context));
ASSERT_NO_FATAL_FAILURE(
ExpectMinidumpContextX86(kSeed, observed_context, true));
}
TEST(MinidumpExceptionWriterDeathTest, NoContext) {
MinidumpFileWriter minidump_file_writer;
auto exception_writer = make_scoped_ptr(new MinidumpExceptionWriter());

View File

@ -88,6 +88,8 @@
'sources': [
'test/test_cpu_context.cc',
'test/test_cpu_context.h',
'test/test_exception_snapshot.cc',
'test/test_exception_snapshot.h',
'test/test_memory_snapshot.cc',
'test/test_memory_snapshot.h',
'test/test_module_snapshot.cc',

View File

@ -0,0 +1,59 @@
// Copyright 2014 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/test/test_exception_snapshot.h"
namespace crashpad {
namespace test {
TestExceptionSnapshot::TestExceptionSnapshot()
: context_union_(),
context_(),
thread_id_(0),
exception_(0),
exception_info_(0),
exception_address_(0),
codes_() {
context_.x86 = &context_union_.x86;
}
TestExceptionSnapshot::~TestExceptionSnapshot() {
}
const CPUContext* TestExceptionSnapshot::Context() const {
return &context_;
}
uint64_t TestExceptionSnapshot::ThreadID() const {
return thread_id_;
}
uint32_t TestExceptionSnapshot::Exception() const {
return exception_;
}
uint32_t TestExceptionSnapshot::ExceptionInfo() const {
return exception_info_;
}
uint64_t TestExceptionSnapshot::ExceptionAddress() const {
return exception_address_;
}
const std::vector<uint64_t>& TestExceptionSnapshot::Codes() const {
return codes_;
}
} // namespace test
} // namespace crashpad

View File

@ -0,0 +1,88 @@
// Copyright 2014 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_TEST_TEST_EXCEPTION_SNAPSHOT_H_
#define CRASHPAD_SNAPSHOT_TEST_TEST_EXCEPTION_SNAPSHOT_H_
#include <stdint.h>
#include <vector>
#include "base/basictypes.h"
#include "snapshot/cpu_context.h"
#include "snapshot/exception_snapshot.h"
namespace crashpad {
namespace test {
//! \brief A test ExceptionSnapshot that can carry arbitrary data for testing
//! purposes.
class TestExceptionSnapshot final : public ExceptionSnapshot {
public:
TestExceptionSnapshot();
~TestExceptionSnapshot();
//! \brief Obtains a pointer to the underlying mutable CPUContext structure.
//!
//! This method is intended to be used by callers to populate the CPUContext
//! structure.
//!
//! \return The same pointer that Context() does, while treating the data as
//! mutable.
//!
//! \attention This returns a non-`const` pointer to this objects private
//! data so that a caller can populate the context structure directly.
//! This is done because providing setter interfaces to each field in the
//! context structure would be unwieldy and cumbersome. Care must be taken
//! to populate the context structure correctly.
CPUContext* MutableContext() { return &context_; }
void SetThreadID(uint64_t thread_id) { thread_id_ = thread_id; }
void SetException(uint32_t exception) { exception_ = exception; }
void SetExceptionInfo(uint32_t exception_info) {
exception_info_ = exception_info;
}
void SetExceptionAddress(uint64_t exception_address) {
exception_address_ = exception_address;
}
void SetCodes(const std::vector<uint64_t>& codes) { codes_ = codes; }
// ExceptionSnapshot:
const CPUContext* Context() const override;
uint64_t ThreadID() const override;
uint32_t Exception() const override;
uint32_t ExceptionInfo() const override;
uint64_t ExceptionAddress() const override;
const std::vector<uint64_t>& Codes() const override;
private:
union {
CPUContextX86 x86;
CPUContextX86_64 x86_64;
} context_union_;
CPUContext context_;
uint64_t thread_id_;
uint32_t exception_;
uint32_t exception_info_;
uint64_t exception_address_;
std::vector<uint64_t> codes_;
DISALLOW_COPY_AND_ASSIGN(TestExceptionSnapshot);
};
} // namespace test
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_TEST_TEST_EXCEPTION_SNAPSHOT_H_