mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
Add MinidumpModuleCrashpadInfo, its list form, their writers, and their
test. Move SimpleAnnotations from being a property of the minidump to being a property of the module, matching the Snapshot interface. TEST=minidump_test MinidumpCrashpadInfo.*:MinidumpCrashpadModule.* R=rsesek@chromium.org Review URL: https://codereview.chromium.org/675803002
This commit is contained in:
parent
38aeadc1c1
commit
61af24848f
@ -34,6 +34,8 @@
|
|||||||
'minidump_context_writer.h',
|
'minidump_context_writer.h',
|
||||||
'minidump_crashpad_info_writer.cc',
|
'minidump_crashpad_info_writer.cc',
|
||||||
'minidump_crashpad_info_writer.h',
|
'minidump_crashpad_info_writer.h',
|
||||||
|
'minidump_crashpad_module_writer.cc',
|
||||||
|
'minidump_crashpad_module_writer.h',
|
||||||
'minidump_exception_writer.cc',
|
'minidump_exception_writer.cc',
|
||||||
'minidump_exception_writer.h',
|
'minidump_exception_writer.h',
|
||||||
'minidump_extensions.cc',
|
'minidump_extensions.cc',
|
||||||
@ -77,6 +79,7 @@
|
|||||||
'sources': [
|
'sources': [
|
||||||
'minidump_context_writer_test.cc',
|
'minidump_context_writer_test.cc',
|
||||||
'minidump_crashpad_info_writer_test.cc',
|
'minidump_crashpad_info_writer_test.cc',
|
||||||
|
'minidump_crashpad_module_writer_test.cc',
|
||||||
'minidump_exception_writer_test.cc',
|
'minidump_exception_writer_test.cc',
|
||||||
'minidump_file_writer_test.cc',
|
'minidump_file_writer_test.cc',
|
||||||
'minidump_memory_writer_test.cc',
|
'minidump_memory_writer_test.cc',
|
||||||
|
@ -15,24 +15,24 @@
|
|||||||
#include "minidump/minidump_crashpad_info_writer.h"
|
#include "minidump/minidump_crashpad_info_writer.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
#include "minidump/minidump_crashpad_module_writer.h"
|
||||||
#include "util/file/file_writer.h"
|
#include "util/file/file_writer.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
MinidumpCrashpadInfoWriter::MinidumpCrashpadInfoWriter()
|
MinidumpCrashpadInfoWriter::MinidumpCrashpadInfoWriter()
|
||||||
: MinidumpStreamWriter(), crashpad_info_(), simple_annotations_() {
|
: MinidumpStreamWriter(), crashpad_info_(), module_list_(nullptr) {
|
||||||
crashpad_info_.size = sizeof(crashpad_info_);
|
crashpad_info_.version = MinidumpCrashpadInfo::kVersion;
|
||||||
crashpad_info_.version = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MinidumpCrashpadInfoWriter::~MinidumpCrashpadInfoWriter() {
|
MinidumpCrashpadInfoWriter::~MinidumpCrashpadInfoWriter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinidumpCrashpadInfoWriter::SetSimpleAnnotations(
|
void MinidumpCrashpadInfoWriter::SetModuleList(
|
||||||
MinidumpSimpleStringDictionaryWriter* simple_annotations) {
|
MinidumpModuleCrashpadInfoListWriter* module_list) {
|
||||||
DCHECK_EQ(state(), kStateMutable);
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
simple_annotations_ = simple_annotations;
|
module_list_ = module_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MinidumpCrashpadInfoWriter::Freeze() {
|
bool MinidumpCrashpadInfoWriter::Freeze() {
|
||||||
@ -42,9 +42,8 @@ bool MinidumpCrashpadInfoWriter::Freeze() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simple_annotations_) {
|
if (module_list_) {
|
||||||
simple_annotations_->RegisterLocationDescriptor(
|
module_list_->RegisterLocationDescriptor(&crashpad_info_.module_list);
|
||||||
&crashpad_info_.simple_annotations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -61,8 +60,8 @@ MinidumpCrashpadInfoWriter::Children() {
|
|||||||
DCHECK_GE(state(), kStateFrozen);
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
std::vector<MinidumpWritable*> children;
|
std::vector<MinidumpWritable*> children;
|
||||||
if (simple_annotations_) {
|
if (module_list_) {
|
||||||
children.push_back(simple_annotations_);
|
children.push_back(module_list_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
@ -15,36 +15,31 @@
|
|||||||
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_INFO_WRITER_H_
|
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_INFO_WRITER_H_
|
||||||
#define CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_INFO_WRITER_H_
|
#define CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_INFO_WRITER_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "minidump/minidump_extensions.h"
|
#include "minidump/minidump_extensions.h"
|
||||||
#include "minidump/minidump_simple_string_dictionary_writer.h"
|
|
||||||
#include "minidump/minidump_stream_writer.h"
|
#include "minidump/minidump_stream_writer.h"
|
||||||
#include "minidump/minidump_writable.h"
|
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
|
class MinidumpModuleCrashpadInfoListWriter;
|
||||||
|
|
||||||
//! \brief The writer for a MinidumpCrashpadInfo stream in a minidump file.
|
//! \brief The writer for a MinidumpCrashpadInfo stream in a minidump file.
|
||||||
class MinidumpCrashpadInfoWriter final : public internal::MinidumpStreamWriter {
|
class MinidumpCrashpadInfoWriter final : public internal::MinidumpStreamWriter {
|
||||||
public:
|
public:
|
||||||
MinidumpCrashpadInfoWriter();
|
MinidumpCrashpadInfoWriter();
|
||||||
~MinidumpCrashpadInfoWriter();
|
~MinidumpCrashpadInfoWriter();
|
||||||
|
|
||||||
//! \brief Arranges for MinidumpCrashpadInfo::simple_annotations to point to
|
//! \brief Arranges for MinidumpCrashpadInfo::module_list to point to the
|
||||||
//! the MinidumpSimpleStringDictionaryWriter object to be written by \a
|
//! MinidumpModuleCrashpadInfoList object to be written by \a
|
||||||
//! simple_annotations.
|
//! module_list.
|
||||||
//!
|
//!
|
||||||
//! \a simple_annotations will become a child of this object in the overall
|
//! \a module_list will become a child of this object in the overall tree of
|
||||||
//! tree of internal::MinidumpWritable objects.
|
//! internal::MinidumpWritable objects.
|
||||||
//!
|
//!
|
||||||
//! \note Valid in #kStateMutable.
|
//! \note Valid in #kStateMutable.
|
||||||
void SetSimpleAnnotations(
|
void SetModuleList(MinidumpModuleCrashpadInfoListWriter* module_list);
|
||||||
MinidumpSimpleStringDictionaryWriter* simple_annotations);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// MinidumpWritable:
|
// MinidumpWritable:
|
||||||
@ -58,7 +53,7 @@ class MinidumpCrashpadInfoWriter final : public internal::MinidumpStreamWriter {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
MinidumpCrashpadInfo crashpad_info_;
|
MinidumpCrashpadInfo crashpad_info_;
|
||||||
MinidumpSimpleStringDictionaryWriter* simple_annotations_; // weak
|
MinidumpModuleCrashpadInfoListWriter* module_list_; // weak
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(MinidumpCrashpadInfoWriter);
|
DISALLOW_COPY_AND_ASSIGN(MinidumpCrashpadInfoWriter);
|
||||||
};
|
};
|
||||||
|
@ -17,11 +17,10 @@
|
|||||||
#include <dbghelp.h>
|
#include <dbghelp.h>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "minidump/minidump_crashpad_module_writer.h"
|
||||||
#include "minidump/minidump_extensions.h"
|
#include "minidump/minidump_extensions.h"
|
||||||
#include "minidump/minidump_file_writer.h"
|
#include "minidump/minidump_file_writer.h"
|
||||||
#include "minidump/minidump_simple_string_dictionary_writer.h"
|
|
||||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||||
#include "minidump/test/minidump_string_writer_test_util.h"
|
|
||||||
#include "minidump/test/minidump_writable_test_util.h"
|
#include "minidump/test/minidump_writable_test_util.h"
|
||||||
#include "util/file/string_file_writer.h"
|
#include "util/file/string_file_writer.h"
|
||||||
|
|
||||||
@ -29,26 +28,9 @@ namespace crashpad {
|
|||||||
namespace test {
|
namespace test {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void GetCrashpadInfoStream(
|
void GetCrashpadInfoStream(const std::string& file_contents,
|
||||||
const std::string& file_contents,
|
const MinidumpCrashpadInfo** crashpad_info,
|
||||||
const MinidumpCrashpadInfo** crashpad_info,
|
const MinidumpModuleCrashpadInfoList** module_list) {
|
||||||
const MinidumpSimpleStringDictionary** simple_annotations) {
|
|
||||||
const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER);
|
|
||||||
const size_t kCrashpadInfoStreamOffset =
|
|
||||||
kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY);
|
|
||||||
size_t end = kCrashpadInfoStreamOffset + sizeof(MinidumpCrashpadInfo);
|
|
||||||
const size_t kSimpleAnnotationsOffset = simple_annotations ? end : 0;
|
|
||||||
if (simple_annotations) {
|
|
||||||
end += sizeof(MinidumpSimpleStringDictionary);
|
|
||||||
}
|
|
||||||
const size_t kFileSize = end;
|
|
||||||
|
|
||||||
if (!simple_annotations) {
|
|
||||||
ASSERT_EQ(kFileSize, file_contents.size());
|
|
||||||
} else {
|
|
||||||
EXPECT_GE(file_contents.size(), kFileSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
const MINIDUMP_DIRECTORY* directory;
|
const MINIDUMP_DIRECTORY* directory;
|
||||||
const MINIDUMP_HEADER* header =
|
const MINIDUMP_HEADER* header =
|
||||||
MinidumpHeaderAtStart(file_contents, &directory);
|
MinidumpHeaderAtStart(file_contents, &directory);
|
||||||
@ -56,23 +38,14 @@ void GetCrashpadInfoStream(
|
|||||||
ASSERT_TRUE(directory);
|
ASSERT_TRUE(directory);
|
||||||
|
|
||||||
ASSERT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[0].StreamType);
|
ASSERT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[0].StreamType);
|
||||||
EXPECT_EQ(kCrashpadInfoStreamOffset, directory[0].Location.Rva);
|
|
||||||
|
|
||||||
*crashpad_info = MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>(
|
*crashpad_info = MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>(
|
||||||
file_contents, directory[0].Location);
|
file_contents, directory[0].Location);
|
||||||
ASSERT_TRUE(*crashpad_info);
|
ASSERT_TRUE(*crashpad_info);
|
||||||
|
|
||||||
if (simple_annotations) {
|
*module_list =
|
||||||
EXPECT_EQ(kSimpleAnnotationsOffset,
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfoList>(
|
||||||
(*crashpad_info)->simple_annotations.Rva);
|
file_contents, (*crashpad_info)->module_list);
|
||||||
*simple_annotations =
|
|
||||||
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
|
||||||
file_contents, (*crashpad_info)->simple_annotations);
|
|
||||||
ASSERT_TRUE(*simple_annotations);
|
|
||||||
} else {
|
|
||||||
ASSERT_EQ(0u, (*crashpad_info)->simple_annotations.DataSize);
|
|
||||||
ASSERT_EQ(0u, (*crashpad_info)->simple_annotations.Rva);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MinidumpCrashpadInfoWriter, Empty) {
|
TEST(MinidumpCrashpadInfoWriter, Empty) {
|
||||||
@ -85,66 +58,51 @@ TEST(MinidumpCrashpadInfoWriter, Empty) {
|
|||||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
|
ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
|
||||||
|
|
||||||
const MinidumpCrashpadInfo* crashpad_info;
|
const MinidumpCrashpadInfo* crashpad_info;
|
||||||
|
const MinidumpModuleCrashpadInfoList* module_list;
|
||||||
|
|
||||||
ASSERT_NO_FATAL_FAILURE(
|
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
||||||
GetCrashpadInfoStream(file_writer.string(), &crashpad_info, nullptr));
|
file_writer.string(), &crashpad_info, &module_list));
|
||||||
|
|
||||||
EXPECT_EQ(sizeof(*crashpad_info), crashpad_info->size);
|
EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version);
|
||||||
EXPECT_EQ(1u, crashpad_info->version);
|
EXPECT_FALSE(module_list);
|
||||||
EXPECT_EQ(0u, crashpad_info->simple_annotations.DataSize);
|
|
||||||
EXPECT_EQ(0u, crashpad_info->simple_annotations.Rva);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MinidumpCrashpadInfoWriter, SimpleAnnotations) {
|
TEST(MinidumpCrashpadInfoWriter, CrashpadModuleList) {
|
||||||
|
const uint32_t kMinidumpModuleListIndex = 3;
|
||||||
|
|
||||||
MinidumpFileWriter minidump_file_writer;
|
MinidumpFileWriter minidump_file_writer;
|
||||||
MinidumpCrashpadInfoWriter crashpad_info_writer;
|
MinidumpCrashpadInfoWriter crashpad_info_writer;
|
||||||
|
|
||||||
minidump_file_writer.AddStream(&crashpad_info_writer);
|
minidump_file_writer.AddStream(&crashpad_info_writer);
|
||||||
|
|
||||||
MinidumpSimpleStringDictionaryWriter simple_annotations_writer;
|
MinidumpModuleCrashpadInfoListWriter module_list_writer;
|
||||||
|
MinidumpModuleCrashpadInfoWriter module_writer;
|
||||||
// Set a key and value before adding the simple_annotations_writer to
|
module_writer.SetMinidumpModuleListIndex(kMinidumpModuleListIndex);
|
||||||
// crashpad_info_writer, and another one after.
|
module_list_writer.AddModule(&module_writer);
|
||||||
const char kKey0[] = "k0";
|
crashpad_info_writer.SetModuleList(&module_list_writer);
|
||||||
const char kValue0[] = "v";
|
|
||||||
const char kKey1[] = "KEY1";
|
|
||||||
const char kValue1[] = "";
|
|
||||||
MinidumpSimpleStringDictionaryEntryWriter entry_0;
|
|
||||||
entry_0.SetKeyValue(kKey0, kValue0);
|
|
||||||
simple_annotations_writer.AddEntry(&entry_0);
|
|
||||||
|
|
||||||
crashpad_info_writer.SetSimpleAnnotations(&simple_annotations_writer);
|
|
||||||
|
|
||||||
MinidumpSimpleStringDictionaryEntryWriter entry_1;
|
|
||||||
entry_1.SetKeyValue(kKey1, kValue1);
|
|
||||||
simple_annotations_writer.AddEntry(&entry_1);
|
|
||||||
|
|
||||||
StringFileWriter file_writer;
|
StringFileWriter file_writer;
|
||||||
ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
|
ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
|
||||||
|
|
||||||
const MinidumpCrashpadInfo* crashpad_info;
|
const MinidumpCrashpadInfo* crashpad_info;
|
||||||
const MinidumpSimpleStringDictionary* simple_annotations;
|
const MinidumpModuleCrashpadInfoList* module_list;
|
||||||
|
|
||||||
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
ASSERT_NO_FATAL_FAILURE(GetCrashpadInfoStream(
|
||||||
file_writer.string(), &crashpad_info, &simple_annotations));
|
file_writer.string(), &crashpad_info, &module_list));
|
||||||
|
|
||||||
EXPECT_EQ(sizeof(*crashpad_info), crashpad_info->size);
|
EXPECT_EQ(MinidumpCrashpadInfo::kVersion, crashpad_info->version);
|
||||||
EXPECT_EQ(1u, crashpad_info->version);
|
ASSERT_TRUE(module_list);
|
||||||
|
ASSERT_EQ(1u, module_list->count);
|
||||||
|
|
||||||
ASSERT_EQ(2u, simple_annotations->count);
|
const MinidumpModuleCrashpadInfo* module =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||||
|
file_writer.string(), module_list->modules[0]);
|
||||||
|
ASSERT_TRUE(module);
|
||||||
|
|
||||||
EXPECT_EQ(kKey1,
|
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version);
|
||||||
MinidumpUTF8StringAtRVAAsString(
|
EXPECT_EQ(kMinidumpModuleListIndex, module->minidump_module_list_index);
|
||||||
file_writer.string(), simple_annotations->entries[0].key));
|
EXPECT_EQ(0u, module->simple_annotations.DataSize);
|
||||||
EXPECT_EQ(kValue1,
|
EXPECT_EQ(0u, module->simple_annotations.Rva);
|
||||||
MinidumpUTF8StringAtRVAAsString(
|
|
||||||
file_writer.string(), simple_annotations->entries[0].value));
|
|
||||||
EXPECT_EQ(kKey0,
|
|
||||||
MinidumpUTF8StringAtRVAAsString(
|
|
||||||
file_writer.string(), simple_annotations->entries[1].key));
|
|
||||||
EXPECT_EQ(kValue0,
|
|
||||||
MinidumpUTF8StringAtRVAAsString(
|
|
||||||
file_writer.string(), simple_annotations->entries[1].value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
160
minidump/minidump_crashpad_module_writer.cc
Normal file
160
minidump/minidump_crashpad_module_writer.cc
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// 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 "minidump/minidump_crashpad_module_writer.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "minidump/minidump_simple_string_dictionary_writer.h"
|
||||||
|
#include "util/file/file_writer.h"
|
||||||
|
#include "util/numeric/safe_assignment.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoWriter::MinidumpModuleCrashpadInfoWriter()
|
||||||
|
: MinidumpWritable(), module_(), simple_annotations_() {
|
||||||
|
module_.version = MinidumpModuleCrashpadInfo::kVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoWriter::~MinidumpModuleCrashpadInfoWriter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinidumpModuleCrashpadInfoWriter::SetSimpleAnnotations(
|
||||||
|
MinidumpSimpleStringDictionaryWriter* simple_annotations) {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
simple_annotations_ = simple_annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpModuleCrashpadInfoWriter::Freeze() {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
if (!MinidumpWritable::Freeze()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simple_annotations_) {
|
||||||
|
simple_annotations_->RegisterLocationDescriptor(
|
||||||
|
&module_.simple_annotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MinidumpModuleCrashpadInfoWriter::SizeOfObject() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
return sizeof(module_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<internal::MinidumpWritable*>
|
||||||
|
MinidumpModuleCrashpadInfoWriter::Children() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
std::vector<MinidumpWritable*> children;
|
||||||
|
if (simple_annotations_) {
|
||||||
|
children.push_back(simple_annotations_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpModuleCrashpadInfoWriter::WriteObject(
|
||||||
|
FileWriterInterface* file_writer) {
|
||||||
|
DCHECK_EQ(state(), kStateWritable);
|
||||||
|
|
||||||
|
return file_writer->Write(&module_, sizeof(module_));
|
||||||
|
}
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoListWriter::MinidumpModuleCrashpadInfoListWriter()
|
||||||
|
: MinidumpWritable(),
|
||||||
|
module_list_base_(),
|
||||||
|
modules_(),
|
||||||
|
module_location_descriptors_() {
|
||||||
|
}
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoListWriter::~MinidumpModuleCrashpadInfoListWriter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinidumpModuleCrashpadInfoListWriter::AddModule(
|
||||||
|
MinidumpModuleCrashpadInfoWriter* module) {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
modules_.push_back(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpModuleCrashpadInfoListWriter::Freeze() {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
DCHECK(module_location_descriptors_.empty());
|
||||||
|
|
||||||
|
if (!MinidumpWritable::Freeze()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t module_count = modules_.size();
|
||||||
|
if (!AssignIfInRange(&module_list_base_.count, module_count)) {
|
||||||
|
LOG(ERROR) << "module_count " << module_count << " out of range";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_location_descriptors_.resize(module_count);
|
||||||
|
for (size_t index = 0; index < module_count; ++index) {
|
||||||
|
modules_[index]->RegisterLocationDescriptor(
|
||||||
|
&module_location_descriptors_[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MinidumpModuleCrashpadInfoListWriter::SizeOfObject() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
return sizeof(module_list_base_) +
|
||||||
|
modules_.size() * sizeof(MINIDUMP_LOCATION_DESCRIPTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<internal::MinidumpWritable*>
|
||||||
|
MinidumpModuleCrashpadInfoListWriter::Children() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
std::vector<MinidumpWritable*> children;
|
||||||
|
for (MinidumpModuleCrashpadInfoWriter* module : modules_) {
|
||||||
|
children.push_back(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpModuleCrashpadInfoListWriter::WriteObject(
|
||||||
|
FileWriterInterface* file_writer) {
|
||||||
|
DCHECK_EQ(state(), kStateWritable);
|
||||||
|
DCHECK_EQ(modules_.size(), module_location_descriptors_.size());
|
||||||
|
|
||||||
|
WritableIoVec iov;
|
||||||
|
iov.iov_base = &module_list_base_;
|
||||||
|
iov.iov_len = sizeof(module_list_base_);
|
||||||
|
std::vector<WritableIoVec> iovecs(1, iov);
|
||||||
|
|
||||||
|
if (!module_location_descriptors_.empty()) {
|
||||||
|
iov.iov_base = &module_location_descriptors_[0];
|
||||||
|
iov.iov_len = module_location_descriptors_.size() *
|
||||||
|
sizeof(MINIDUMP_LOCATION_DESCRIPTOR);
|
||||||
|
iovecs.push_back(iov);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file_writer->WriteIoVec(&iovecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crashpad
|
102
minidump/minidump_crashpad_module_writer.h
Normal file
102
minidump/minidump_crashpad_module_writer.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// 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_MINIDUMP_MINIDUMP_CRASHPAD_MODULE_WRITER_H_
|
||||||
|
#define CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_MODULE_WRITER_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "minidump/minidump_extensions.h"
|
||||||
|
#include "minidump/minidump_writable.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
|
||||||
|
class MinidumpSimpleStringDictionaryWriter;
|
||||||
|
|
||||||
|
//! \brief The writer for a MinidumpModuleCrashpadInfo object in a minidump
|
||||||
|
//! file.
|
||||||
|
class MinidumpModuleCrashpadInfoWriter final
|
||||||
|
: public internal::MinidumpWritable {
|
||||||
|
public:
|
||||||
|
MinidumpModuleCrashpadInfoWriter();
|
||||||
|
~MinidumpModuleCrashpadInfoWriter();
|
||||||
|
|
||||||
|
//! \brief Sets MinidumpModuleCrashpadInfo::minidump_module_list_index.
|
||||||
|
void SetMinidumpModuleListIndex(uint32_t minidump_module_list_index) {
|
||||||
|
module_.minidump_module_list_index = minidump_module_list_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Arranges for MinidumpModuleCrashpadInfo::simple_annotations to
|
||||||
|
//! point to the MinidumpSimpleStringDictionaryWriter object to be written
|
||||||
|
//! by \a simple_annotations.
|
||||||
|
//!
|
||||||
|
//! \a simple_annotations will become a child of this object in the overall
|
||||||
|
//! tree of internal::MinidumpWritable objects.
|
||||||
|
//!
|
||||||
|
//! \note Valid in #kStateMutable.
|
||||||
|
void SetSimpleAnnotations(
|
||||||
|
MinidumpSimpleStringDictionaryWriter* simple_annotations);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// MinidumpWritable:
|
||||||
|
bool Freeze() override;
|
||||||
|
size_t SizeOfObject() override;
|
||||||
|
std::vector<MinidumpWritable*> Children() override;
|
||||||
|
bool WriteObject(FileWriterInterface* file_writer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinidumpModuleCrashpadInfo module_;
|
||||||
|
MinidumpSimpleStringDictionaryWriter* simple_annotations_; // weak
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCrashpadInfoWriter);
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \brief The writer for a MinidumpModuleCrashpadInfoList object in a minidump
|
||||||
|
//! file, containing a list of MinidumpModuleCrashpadInfo objects.
|
||||||
|
class MinidumpModuleCrashpadInfoListWriter final
|
||||||
|
: public internal::MinidumpWritable {
|
||||||
|
public:
|
||||||
|
MinidumpModuleCrashpadInfoListWriter();
|
||||||
|
~MinidumpModuleCrashpadInfoListWriter();
|
||||||
|
|
||||||
|
//! \brief Adds a MinidumpModuleCrashpadInfo to the
|
||||||
|
//! MinidumpModuleCrashpadInfoList.
|
||||||
|
//!
|
||||||
|
//! \a module will become a child of this object in the overall tree of
|
||||||
|
//! internal::MinidumpWritable objects.
|
||||||
|
//!
|
||||||
|
//! \note Valid in #kStateMutable.
|
||||||
|
void AddModule(MinidumpModuleCrashpadInfoWriter* module);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// MinidumpWritable:
|
||||||
|
bool Freeze() override;
|
||||||
|
size_t SizeOfObject() override;
|
||||||
|
std::vector<MinidumpWritable*> Children() override;
|
||||||
|
bool WriteObject(FileWriterInterface* file_writer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinidumpModuleCrashpadInfoList module_list_base_;
|
||||||
|
std::vector<MinidumpModuleCrashpadInfoWriter*> modules_; // weak
|
||||||
|
std::vector<MINIDUMP_LOCATION_DESCRIPTOR> module_location_descriptors_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCrashpadInfoListWriter);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace crashpad
|
||||||
|
|
||||||
|
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_MODULE_WRITER_H_
|
266
minidump/minidump_crashpad_module_writer_test.cc
Normal file
266
minidump/minidump_crashpad_module_writer_test.cc
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
// 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 "minidump/minidump_crashpad_module_writer.h"
|
||||||
|
|
||||||
|
#include <dbghelp.h>
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "minidump/minidump_extensions.h"
|
||||||
|
#include "minidump/minidump_simple_string_dictionary_writer.h"
|
||||||
|
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||||
|
#include "minidump/test/minidump_string_writer_test_util.h"
|
||||||
|
#include "minidump/test/minidump_writable_test_util.h"
|
||||||
|
#include "util/file/string_file_writer.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
namespace test {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfoList* MinidumpModuleCrashpadInfoListAtStart(
|
||||||
|
const std::string& file_contents,
|
||||||
|
size_t count) {
|
||||||
|
MINIDUMP_LOCATION_DESCRIPTOR location_descriptor;
|
||||||
|
location_descriptor.DataSize = sizeof(MinidumpModuleCrashpadInfoList) +
|
||||||
|
count * sizeof(MINIDUMP_LOCATION_DESCRIPTOR);
|
||||||
|
location_descriptor.Rva = 0;
|
||||||
|
return MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfoList>(
|
||||||
|
file_contents, location_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpModuleCrashpadInfoWriter, EmptyList) {
|
||||||
|
StringFileWriter file_writer;
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoListWriter module_list_writer;
|
||||||
|
|
||||||
|
EXPECT_TRUE(module_list_writer.WriteEverything(&file_writer));
|
||||||
|
ASSERT_EQ(sizeof(MinidumpModuleCrashpadInfoList),
|
||||||
|
file_writer.string().size());
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfoList* module_list =
|
||||||
|
MinidumpModuleCrashpadInfoListAtStart(file_writer.string(), 0);
|
||||||
|
ASSERT_TRUE(module_list);
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, module_list->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpModuleCrashpadInfoWriter, EmptyModule) {
|
||||||
|
StringFileWriter file_writer;
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoListWriter module_list_writer;
|
||||||
|
MinidumpModuleCrashpadInfoWriter module_writer;
|
||||||
|
module_list_writer.AddModule(&module_writer);
|
||||||
|
|
||||||
|
EXPECT_TRUE(module_list_writer.WriteEverything(&file_writer));
|
||||||
|
ASSERT_EQ(sizeof(MinidumpModuleCrashpadInfoList) +
|
||||||
|
sizeof(MINIDUMP_LOCATION_DESCRIPTOR) +
|
||||||
|
sizeof(MinidumpModuleCrashpadInfo),
|
||||||
|
file_writer.string().size());
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfoList* module_list =
|
||||||
|
MinidumpModuleCrashpadInfoListAtStart(file_writer.string(), 1);
|
||||||
|
ASSERT_TRUE(module_list);
|
||||||
|
|
||||||
|
ASSERT_EQ(1u, module_list->count);
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfo* module =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||||
|
file_writer.string(), module_list->modules[0]);
|
||||||
|
ASSERT_TRUE(module);
|
||||||
|
|
||||||
|
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version);
|
||||||
|
EXPECT_EQ(0u, module->minidump_module_list_index);
|
||||||
|
EXPECT_EQ(0u, module->simple_annotations.DataSize);
|
||||||
|
EXPECT_EQ(0u, module->simple_annotations.Rva);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpModuleCrashpadInfoWriter, FullModule) {
|
||||||
|
const uint32_t kMinidumpModuleListIndex = 1;
|
||||||
|
const char kKey[] = "key";
|
||||||
|
const char kValue[] = "value";
|
||||||
|
|
||||||
|
StringFileWriter file_writer;
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoListWriter module_list_writer;
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoWriter module_writer;
|
||||||
|
module_writer.SetMinidumpModuleListIndex(kMinidumpModuleListIndex);
|
||||||
|
MinidumpSimpleStringDictionaryWriter simple_string_dictionary_writer;
|
||||||
|
MinidumpSimpleStringDictionaryEntryWriter
|
||||||
|
simple_string_dictionary_entry_writer;
|
||||||
|
simple_string_dictionary_entry_writer.SetKeyValue(kKey, kValue);
|
||||||
|
simple_string_dictionary_writer.AddEntry(
|
||||||
|
&simple_string_dictionary_entry_writer);
|
||||||
|
module_writer.SetSimpleAnnotations(&simple_string_dictionary_writer);
|
||||||
|
module_list_writer.AddModule(&module_writer);
|
||||||
|
|
||||||
|
EXPECT_TRUE(module_list_writer.WriteEverything(&file_writer));
|
||||||
|
ASSERT_EQ(sizeof(MinidumpModuleCrashpadInfoList) +
|
||||||
|
sizeof(MINIDUMP_LOCATION_DESCRIPTOR) +
|
||||||
|
sizeof(MinidumpModuleCrashpadInfo) +
|
||||||
|
sizeof(MinidumpSimpleStringDictionary) +
|
||||||
|
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||||
|
sizeof(MinidumpUTF8String) + arraysize(kKey) +
|
||||||
|
sizeof(MinidumpUTF8String) + arraysize(kValue),
|
||||||
|
file_writer.string().size());
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfoList* module_list =
|
||||||
|
MinidumpModuleCrashpadInfoListAtStart(file_writer.string(), 1);
|
||||||
|
ASSERT_TRUE(module_list);
|
||||||
|
|
||||||
|
ASSERT_EQ(1u, module_list->count);
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfo* module =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||||
|
file_writer.string(), module_list->modules[0]);
|
||||||
|
ASSERT_TRUE(module);
|
||||||
|
|
||||||
|
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module->version);
|
||||||
|
EXPECT_EQ(kMinidumpModuleListIndex, module->minidump_module_list_index);
|
||||||
|
EXPECT_NE(0u, module->simple_annotations.DataSize);
|
||||||
|
EXPECT_NE(0u, module->simple_annotations.Rva);
|
||||||
|
|
||||||
|
const MinidumpSimpleStringDictionary* simple_annotations =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||||
|
file_writer.string(), module->simple_annotations);
|
||||||
|
ASSERT_TRUE(simple_annotations);
|
||||||
|
|
||||||
|
ASSERT_EQ(1u, simple_annotations->count);
|
||||||
|
EXPECT_EQ(kKey,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations->entries[0].key));
|
||||||
|
EXPECT_EQ(kValue,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations->entries[0].value));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpModuleCrashpadInfoWriter, ThreeModules) {
|
||||||
|
const uint32_t kMinidumpModuleListIndex0 = 0;
|
||||||
|
const char kKey0[] = "key";
|
||||||
|
const char kValue0[] = "value";
|
||||||
|
const uint32_t kMinidumpModuleListIndex1 = 2;
|
||||||
|
const uint32_t kMinidumpModuleListIndex2 = 5;
|
||||||
|
const char kKey2A[] = "K";
|
||||||
|
const char kValue2A[] = "VVV";
|
||||||
|
const char kKey2B[] = "river";
|
||||||
|
const char kValue2B[] = "hudson";
|
||||||
|
|
||||||
|
StringFileWriter file_writer;
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoListWriter module_list_writer;
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoWriter module_writer_0;
|
||||||
|
module_writer_0.SetMinidumpModuleListIndex(kMinidumpModuleListIndex0);
|
||||||
|
MinidumpSimpleStringDictionaryWriter simple_string_dictionary_writer_0;
|
||||||
|
MinidumpSimpleStringDictionaryEntryWriter
|
||||||
|
simple_string_dictionary_entry_writer_0;
|
||||||
|
simple_string_dictionary_entry_writer_0.SetKeyValue(kKey0, kValue0);
|
||||||
|
simple_string_dictionary_writer_0.AddEntry(
|
||||||
|
&simple_string_dictionary_entry_writer_0);
|
||||||
|
module_writer_0.SetSimpleAnnotations(&simple_string_dictionary_writer_0);
|
||||||
|
module_list_writer.AddModule(&module_writer_0);
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoWriter module_writer_1;
|
||||||
|
module_writer_1.SetMinidumpModuleListIndex(kMinidumpModuleListIndex1);
|
||||||
|
module_list_writer.AddModule(&module_writer_1);
|
||||||
|
|
||||||
|
MinidumpModuleCrashpadInfoWriter module_writer_2;
|
||||||
|
module_writer_2.SetMinidumpModuleListIndex(kMinidumpModuleListIndex2);
|
||||||
|
MinidumpSimpleStringDictionaryWriter simple_string_dictionary_writer_2;
|
||||||
|
MinidumpSimpleStringDictionaryEntryWriter
|
||||||
|
simple_string_dictionary_entry_writer_2a;
|
||||||
|
simple_string_dictionary_entry_writer_2a.SetKeyValue(kKey2A, kValue2A);
|
||||||
|
simple_string_dictionary_writer_2.AddEntry(
|
||||||
|
&simple_string_dictionary_entry_writer_2a);
|
||||||
|
MinidumpSimpleStringDictionaryEntryWriter
|
||||||
|
simple_string_dictionary_entry_writer_2b;
|
||||||
|
simple_string_dictionary_entry_writer_2b.SetKeyValue(kKey2B, kValue2B);
|
||||||
|
simple_string_dictionary_writer_2.AddEntry(
|
||||||
|
&simple_string_dictionary_entry_writer_2b);
|
||||||
|
module_writer_2.SetSimpleAnnotations(&simple_string_dictionary_writer_2);
|
||||||
|
module_list_writer.AddModule(&module_writer_2);
|
||||||
|
|
||||||
|
EXPECT_TRUE(module_list_writer.WriteEverything(&file_writer));
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfoList* module_list =
|
||||||
|
MinidumpModuleCrashpadInfoListAtStart(file_writer.string(), 3);
|
||||||
|
ASSERT_TRUE(module_list);
|
||||||
|
|
||||||
|
ASSERT_EQ(3u, module_list->count);
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfo* module_0 =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||||
|
file_writer.string(), module_list->modules[0]);
|
||||||
|
ASSERT_TRUE(module_0);
|
||||||
|
|
||||||
|
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_0->version);
|
||||||
|
EXPECT_EQ(kMinidumpModuleListIndex0, module_0->minidump_module_list_index);
|
||||||
|
|
||||||
|
const MinidumpSimpleStringDictionary* simple_annotations_0 =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||||
|
file_writer.string(), module_0->simple_annotations);
|
||||||
|
ASSERT_TRUE(simple_annotations_0);
|
||||||
|
|
||||||
|
ASSERT_EQ(1u, simple_annotations_0->count);
|
||||||
|
EXPECT_EQ(kKey0,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations_0->entries[0].key));
|
||||||
|
EXPECT_EQ(kValue0,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations_0->entries[0].value));
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfo* module_1 =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||||
|
file_writer.string(), module_list->modules[1]);
|
||||||
|
ASSERT_TRUE(module_1);
|
||||||
|
|
||||||
|
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_1->version);
|
||||||
|
EXPECT_EQ(kMinidumpModuleListIndex1, module_1->minidump_module_list_index);
|
||||||
|
|
||||||
|
const MinidumpSimpleStringDictionary* simple_annotations_1 =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||||
|
file_writer.string(), module_1->simple_annotations);
|
||||||
|
EXPECT_FALSE(simple_annotations_1);
|
||||||
|
|
||||||
|
const MinidumpModuleCrashpadInfo* module_2 =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfo>(
|
||||||
|
file_writer.string(), module_list->modules[2]);
|
||||||
|
ASSERT_TRUE(module_2);
|
||||||
|
|
||||||
|
EXPECT_EQ(MinidumpModuleCrashpadInfo::kVersion, module_2->version);
|
||||||
|
EXPECT_EQ(kMinidumpModuleListIndex2, module_2->minidump_module_list_index);
|
||||||
|
|
||||||
|
const MinidumpSimpleStringDictionary* simple_annotations_2 =
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||||
|
file_writer.string(), module_2->simple_annotations);
|
||||||
|
ASSERT_TRUE(simple_annotations_2);
|
||||||
|
|
||||||
|
ASSERT_EQ(2u, simple_annotations_2->count);
|
||||||
|
EXPECT_EQ(kKey2A,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations_2->entries[0].key));
|
||||||
|
EXPECT_EQ(kValue2A,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations_2->entries[0].value));
|
||||||
|
EXPECT_EQ(kKey2B,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations_2->entries[1].key));
|
||||||
|
EXPECT_EQ(kValue2B,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(
|
||||||
|
file_writer.string(), simple_annotations_2->entries[1].value));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace test
|
||||||
|
} // namespace crashpad
|
@ -18,5 +18,7 @@ namespace crashpad {
|
|||||||
|
|
||||||
const uint32_t MinidumpModuleCodeViewRecordPDB20::kSignature;
|
const uint32_t MinidumpModuleCodeViewRecordPDB20::kSignature;
|
||||||
const uint32_t MinidumpModuleCodeViewRecordPDB70::kSignature;
|
const uint32_t MinidumpModuleCodeViewRecordPDB70::kSignature;
|
||||||
|
const uint32_t MinidumpModuleCrashpadInfo::kVersion;
|
||||||
|
const uint32_t MinidumpCrashpadInfo::kVersion;
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -316,31 +316,108 @@ struct __attribute__((packed, aligned(4))) MinidumpSimpleStringDictionary {
|
|||||||
MinidumpSimpleStringDictionaryEntry entries[0];
|
MinidumpSimpleStringDictionaryEntry entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief Additional Crashpad-specific information carried within a minidump
|
//! \brief Additional Crashpad-specific information about a module carried
|
||||||
//! file.
|
//! within a minidump file.
|
||||||
struct __attribute__((packed, aligned(4))) MinidumpCrashpadInfo {
|
//!
|
||||||
//! \brief The size of the entire structure, in bytes.
|
//! This structure augments the information provided by MINIDUMP_MODULE. The
|
||||||
|
//! minidump file must contain a module list stream
|
||||||
|
//! (::kMinidumpStreamTypeModuleList) in order for this structure to appear.
|
||||||
|
//!
|
||||||
|
//! This structure is versioned. When changing this structure, leave the
|
||||||
|
//! existing structure intact so that earlier parsers will be able to understand
|
||||||
|
//! the fields they are aware of, and make additions at the end of the
|
||||||
|
//! structure. Revise #kVersion and document each field’s validity based on
|
||||||
|
//! #version, so that newer parsers will be able to determine whether the added
|
||||||
|
//! fields are valid or not.
|
||||||
|
//!
|
||||||
|
//! \sa MinidumpModuleCrashpadInfoList
|
||||||
|
struct __attribute__((packed, aligned(4))) MinidumpModuleCrashpadInfo {
|
||||||
|
//! \brief The structure’s currently-defined version number.
|
||||||
//!
|
//!
|
||||||
//! \sa version
|
//! \sa version
|
||||||
uint32_t size;
|
static const uint32_t kVersion = 1;
|
||||||
|
|
||||||
//! \brief The structure’s version number. This can be used to determine which
|
//! \brief The structure’s version number.
|
||||||
//! other fields in the structure are valid.
|
|
||||||
//!
|
//!
|
||||||
//! \sa size
|
//! Readers can use this field to determine which other fields in the
|
||||||
|
//! structure are valid. Upon encountering a value greater than #kVersion, a
|
||||||
|
//! reader should assume that the structure’s layout is compatible with the
|
||||||
|
//! structure defined as having value #kVersion.
|
||||||
|
//!
|
||||||
|
//! Writers may produce values less than #kVersion in this field if there is
|
||||||
|
//! no need for any fields present in later versions.
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
|
||||||
//! \brief A MinidumpSimpleStringDictionary pointing to strings interpreted as
|
//! \brief A link to a MINIDUMP_MODULE structure in the module list stream.
|
||||||
//! key-value pairs. The process that crashed controlled the data that
|
|
||||||
//! appears here.
|
|
||||||
//!
|
//!
|
||||||
//! If MINIDUMP_LOCATION_DESCRIPTOR::DataSize is `0`, no key-value pairs are
|
//! This field is an index into MINIDUMP_MODULE_LIST::Modules. This field’s
|
||||||
//! present, and MINIDUMP_LOCATION_DESCRIPTOR::Rva should not be consulted.
|
//! value must be in the range of MINIDUMP_MODULE_LIST::NumberOfEntries.
|
||||||
|
//!
|
||||||
|
//! This field is present when #version is at least `1`.
|
||||||
|
uint32_t minidump_module_list_index;
|
||||||
|
|
||||||
|
//! \brief A MinidumpSimpleStringDictionary pointing to strings interpreted as
|
||||||
|
//! key-value pairs. The module controls the data that appears here.
|
||||||
//!
|
//!
|
||||||
//! This field is present when #version is at least `1`.
|
//! This field is present when #version is at least `1`.
|
||||||
MINIDUMP_LOCATION_DESCRIPTOR simple_annotations;
|
MINIDUMP_LOCATION_DESCRIPTOR simple_annotations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \brief Additional Crashpad-specific information about modules carried within
|
||||||
|
//! a minidump file.
|
||||||
|
//!
|
||||||
|
//! This structure augments the information provided by
|
||||||
|
//! MINIDUMP_MODULE_LIST. The minidump file must contain a module list stream
|
||||||
|
//! (::kMinidumpStreamTypeModuleList) in order for this structure to appear.
|
||||||
|
struct __attribute__((packed, aligned(4))) MinidumpModuleCrashpadInfoList {
|
||||||
|
//! \brief The number of modules present in the #modules array.
|
||||||
|
//!
|
||||||
|
//! This may be less than the value of MINIDUMP_MODULE_LIST::NumberOfModules
|
||||||
|
//! because not every MINIDUMP_MODULE structure carried within the minidump
|
||||||
|
//! file will necessarily have Crashpad-specific information provided by a
|
||||||
|
//! MinidumpModuleCrashpadInfo structure.
|
||||||
|
uint32_t count;
|
||||||
|
|
||||||
|
//! \brief Pointers to MinidumpModuleCrashpadInfo structures.
|
||||||
|
//!
|
||||||
|
//! These are referenced indirectly through MINIDUMP_LOCATION_DESCRIPTOR
|
||||||
|
//! pointers to allow for future growth of the MinidumpModuleCrashpadInfo
|
||||||
|
//! structure.
|
||||||
|
MINIDUMP_LOCATION_DESCRIPTOR modules[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \brief Additional Crashpad-specific information carried within a minidump
|
||||||
|
//! file.
|
||||||
|
//!
|
||||||
|
//! This structure is versioned. When changing this structure, leave the
|
||||||
|
//! existing structure intact so that earlier parsers will be able to understand
|
||||||
|
//! the fields they are aware of, and make additions at the end of the
|
||||||
|
//! structure. Revise #kVersion and document each field’s validity based on
|
||||||
|
//! #version, so that newer parsers will be able to determine whether the added
|
||||||
|
//! fields are valid or not.
|
||||||
|
struct __attribute__((packed, aligned(4))) MinidumpCrashpadInfo {
|
||||||
|
//! \brief The structure’s currently-defined version number.
|
||||||
|
//!
|
||||||
|
//! \sa version
|
||||||
|
static const uint32_t kVersion = 1;
|
||||||
|
|
||||||
|
//! \brief The structure’s version number.
|
||||||
|
//!
|
||||||
|
//! Readers can use this field to determine which other fields in the
|
||||||
|
//! structure are valid. Upon encountering a value greater than #kVersion, a
|
||||||
|
//! reader should assume that the structure’s layout is compatible with the
|
||||||
|
//! structure defined as having value #kVersion.
|
||||||
|
//!
|
||||||
|
//! Writers may produce values less than #kVersion in this field if there is
|
||||||
|
//! no need for any fields present in later versions.
|
||||||
|
uint32_t version;
|
||||||
|
|
||||||
|
//! \brief A pointer to a MinidumpModuleCrashpadInfoList structure.
|
||||||
|
//!
|
||||||
|
//! This field is present when #version is at least `1`.
|
||||||
|
MINIDUMP_LOCATION_DESCRIPTOR module_list;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
|
||||||
#endif // CRASHPAD_MINIDUMP_MINIDUMP_EXTENSIONS_H_
|
#endif // CRASHPAD_MINIDUMP_MINIDUMP_EXTENSIONS_H_
|
||||||
|
@ -160,6 +160,14 @@ struct MinidumpThreadListTraits {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MinidumpModuleCrashpadInfoListTraits {
|
||||||
|
typedef MinidumpModuleCrashpadInfoList ListType;
|
||||||
|
static constexpr size_t kElementSize = sizeof(MINIDUMP_LOCATION_DESCRIPTOR);
|
||||||
|
static size_t ElementCount(const ListType* list) {
|
||||||
|
return list->count;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct MinidumpSimpleStringDictionaryListTraits {
|
struct MinidumpSimpleStringDictionaryListTraits {
|
||||||
typedef MinidumpSimpleStringDictionary ListType;
|
typedef MinidumpSimpleStringDictionary ListType;
|
||||||
static constexpr size_t kElementSize =
|
static constexpr size_t kElementSize =
|
||||||
@ -216,6 +224,15 @@ const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor<
|
|||||||
file_contents, location);
|
file_contents, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
const MinidumpModuleCrashpadInfoList*
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfoList>(
|
||||||
|
const std::string& file_contents,
|
||||||
|
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||||
|
return MinidumpListAtLocationDescriptor<MinidumpModuleCrashpadInfoListTraits>(
|
||||||
|
file_contents, location);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const MinidumpSimpleStringDictionary*
|
const MinidumpSimpleStringDictionary*
|
||||||
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||||
|
@ -102,6 +102,7 @@ MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_DIRECTORY);
|
|||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MEMORY_LIST);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MEMORY_LIST);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MODULE_LIST);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MODULE_LIST);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_THREAD_LIST);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_THREAD_LIST);
|
||||||
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCrashpadInfoList);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary);
|
||||||
|
|
||||||
// These types have final fields carrying variable-sized data (typically string
|
// These types have final fields carrying variable-sized data (typically string
|
||||||
@ -216,6 +217,12 @@ const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor<
|
|||||||
MINIDUMP_THREAD_LIST>(const std::string& file_contents,
|
MINIDUMP_THREAD_LIST>(const std::string& file_contents,
|
||||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
const MinidumpModuleCrashpadInfoList*
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCrashpadInfoList>(
|
||||||
|
const std::string& file_contents,
|
||||||
|
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const MinidumpModuleCodeViewRecordPDB20*
|
const MinidumpModuleCodeViewRecordPDB20*
|
||||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user