mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
Add the minidump extension and writer for Annotation objects.
This adds extensions for MinidumpAnnotation and MinidumpAnnotationList as well as their writer classes. Nothing currently connects the client- side annotations to the writer, so annotations are not yet written into minidumps. Bug: crashpad:192 Change-Id: Ic51536157177921640ca15ae14e5e01ca875ae12 Reviewed-on: https://chromium-review.googlesource.com/731309 Commit-Queue: Robert Sesek <rsesek@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
6950a552bf
commit
3231a80e8b
@ -33,6 +33,8 @@
|
|||||||
'..',
|
'..',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'minidump_annotation_writer.cc',
|
||||||
|
'minidump_annotation_writer.h',
|
||||||
'minidump_byte_array_writer.cc',
|
'minidump_byte_array_writer.cc',
|
||||||
'minidump_byte_array_writer.h',
|
'minidump_byte_array_writer.h',
|
||||||
'minidump_context.h',
|
'minidump_context.h',
|
||||||
|
162
minidump/minidump_annotation_writer.cc
Normal file
162
minidump/minidump_annotation_writer.cc
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
// Copyright 2017 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_annotation_writer.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "util/file/file_writer.h"
|
||||||
|
#include "util/numeric/safe_assignment.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
|
||||||
|
MinidumpAnnotationWriter::MinidumpAnnotationWriter() = default;
|
||||||
|
|
||||||
|
MinidumpAnnotationWriter::~MinidumpAnnotationWriter() = default;
|
||||||
|
|
||||||
|
void MinidumpAnnotationWriter::InitializeFromSnapshot(
|
||||||
|
const AnnotationSnapshot& snapshot) {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
name_.SetUTF8(snapshot.name);
|
||||||
|
annotation_.type = snapshot.type;
|
||||||
|
annotation_.reserved = 0;
|
||||||
|
value_.set_data(snapshot.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinidumpAnnotationWriter::InitializeWithData(
|
||||||
|
const std::string& name,
|
||||||
|
uint16_t type,
|
||||||
|
const std::vector<uint8_t>& data) {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
name_.SetUTF8(name);
|
||||||
|
annotation_.type = type;
|
||||||
|
annotation_.reserved = 0;
|
||||||
|
value_.set_data(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpAnnotationWriter::Freeze() {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
if (!MinidumpWritable::Freeze()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_.RegisterRVA(&annotation_.name);
|
||||||
|
value_.RegisterRVA(&annotation_.value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MinidumpAnnotationWriter::SizeOfObject() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
// This object is written by the MinidumpAnnotationListWriter, and its
|
||||||
|
// children write themselves.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<internal::MinidumpWritable*> MinidumpAnnotationWriter::Children() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
return {&name_, &value_};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpAnnotationWriter::WriteObject(FileWriterInterface* file_writer) {
|
||||||
|
DCHECK_EQ(state(), kStateWritable);
|
||||||
|
|
||||||
|
// This object is written by the MinidumpAnnotationListWriter, and its
|
||||||
|
// children write themselves.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MinidumpAnnotationListWriter::MinidumpAnnotationListWriter()
|
||||||
|
: minidump_list_(new MinidumpAnnotationList()) {}
|
||||||
|
|
||||||
|
MinidumpAnnotationListWriter::~MinidumpAnnotationListWriter() = default;
|
||||||
|
|
||||||
|
void MinidumpAnnotationListWriter::InitializeFromList(
|
||||||
|
const std::vector<AnnotationSnapshot>& list) {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
for (const auto& annotation : list) {
|
||||||
|
auto writer = std::make_unique<MinidumpAnnotationWriter>();
|
||||||
|
writer->InitializeFromSnapshot(annotation);
|
||||||
|
AddObject(std::move(writer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinidumpAnnotationListWriter::AddObject(
|
||||||
|
std::unique_ptr<MinidumpAnnotationWriter> annotation_writer) {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
objects_.push_back(std::move(annotation_writer));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpAnnotationListWriter::IsUseful() const {
|
||||||
|
return !objects_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpAnnotationListWriter::Freeze() {
|
||||||
|
DCHECK_EQ(state(), kStateMutable);
|
||||||
|
|
||||||
|
if (!MinidumpWritable::Freeze()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AssignIfInRange(&minidump_list_->count, objects_.size())) {
|
||||||
|
LOG(ERROR) << "annotation list size " << objects_.size()
|
||||||
|
<< " is out of range";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MinidumpAnnotationListWriter::SizeOfObject() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
return sizeof(*minidump_list_) + sizeof(MinidumpAnnotation) * objects_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<internal::MinidumpWritable*>
|
||||||
|
MinidumpAnnotationListWriter::Children() {
|
||||||
|
DCHECK_GE(state(), kStateFrozen);
|
||||||
|
|
||||||
|
std::vector<internal::MinidumpWritable*> children(objects_.size());
|
||||||
|
for (size_t i = 0; i < objects_.size(); ++i) {
|
||||||
|
children[i] = objects_[i].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpAnnotationListWriter::WriteObject(
|
||||||
|
FileWriterInterface* file_writer) {
|
||||||
|
DCHECK_EQ(state(), kStateWritable);
|
||||||
|
|
||||||
|
std::vector<WritableIoVec> iov(1 + objects_.size());
|
||||||
|
iov[0].iov_base = minidump_list_.get();
|
||||||
|
iov[0].iov_len = sizeof(*minidump_list_);
|
||||||
|
|
||||||
|
for (const auto& object : objects_) {
|
||||||
|
iov.emplace_back(WritableIoVec{object->minidump_annotation(),
|
||||||
|
sizeof(MinidumpAnnotation)});
|
||||||
|
}
|
||||||
|
|
||||||
|
return file_writer->WriteIoVec(&iov);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crashpad
|
109
minidump/minidump_annotation_writer.h
Normal file
109
minidump/minidump_annotation_writer.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// Copyright 2017 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_ANNOTATION_WRITER_H_
|
||||||
|
#define CRASHPAD_MINIDUMP_MINIDUMP_ANNOTATION_WRITER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "minidump/minidump_byte_array_writer.h"
|
||||||
|
#include "minidump/minidump_extensions.h"
|
||||||
|
#include "minidump/minidump_string_writer.h"
|
||||||
|
#include "minidump/minidump_writable.h"
|
||||||
|
#include "snapshot/annotation_snapshot.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
|
||||||
|
//! \brief The writer for a MinidumpAnnotation object in a minidump file.
|
||||||
|
//!
|
||||||
|
//! Because MinidumpAnnotation objects only appear as elements
|
||||||
|
//! of MinidumpAnnotationList objects, this class does not write any
|
||||||
|
//! data on its own. It makes its MinidumpAnnotation data available to its
|
||||||
|
//! MinidumpAnnotationList parent, which writes it as part of a
|
||||||
|
//! MinidumpAnnotationList.
|
||||||
|
class MinidumpAnnotationWriter final : public internal::MinidumpWritable {
|
||||||
|
public:
|
||||||
|
MinidumpAnnotationWriter();
|
||||||
|
~MinidumpAnnotationWriter();
|
||||||
|
|
||||||
|
//! \brief Initializes the annotation writer with data from an
|
||||||
|
//! AnnotationSnapshot.
|
||||||
|
void InitializeFromSnapshot(const AnnotationSnapshot& snapshot);
|
||||||
|
|
||||||
|
//! \brief Initializes the annotation writer with data values.
|
||||||
|
void InitializeWithData(const std::string& name,
|
||||||
|
uint16_t type,
|
||||||
|
const std::vector<uint8_t>& data);
|
||||||
|
|
||||||
|
//! \brief Returns the MinidumpAnnotation referencing this object’s data.
|
||||||
|
const MinidumpAnnotation* minidump_annotation() const { return &annotation_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// MinidumpWritable:
|
||||||
|
|
||||||
|
bool Freeze() override;
|
||||||
|
size_t SizeOfObject() override;
|
||||||
|
std::vector<internal::MinidumpWritable*> Children() override;
|
||||||
|
bool WriteObject(FileWriterInterface* file_writer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinidumpAnnotation annotation_;
|
||||||
|
internal::MinidumpUTF8StringWriter name_;
|
||||||
|
MinidumpByteArrayWriter value_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpAnnotationWriter);
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \brief The writer for a MinidumpAnnotationList object in a minidump file,
|
||||||
|
//! containing a list of MinidumpAnnotation objects.
|
||||||
|
class MinidumpAnnotationListWriter final : public internal::MinidumpWritable {
|
||||||
|
public:
|
||||||
|
MinidumpAnnotationListWriter();
|
||||||
|
~MinidumpAnnotationListWriter();
|
||||||
|
|
||||||
|
//! \brief Initializes the annotation list writer with a list of
|
||||||
|
//! AnnotationSnapshot objects.
|
||||||
|
void InitializeFromList(const std::vector<AnnotationSnapshot>& list);
|
||||||
|
|
||||||
|
//! \brief Adds a single MinidumpAnnotationWriter to the list to be written.
|
||||||
|
void AddObject(std::unique_ptr<MinidumpAnnotationWriter> annotation_writer);
|
||||||
|
|
||||||
|
//! \brief Determines whether the object is useful.
|
||||||
|
//!
|
||||||
|
//! A useful object is one that carries data that makes a meaningful
|
||||||
|
//! contribution to a minidump file. An object carrying entries would be
|
||||||
|
//! considered useful.
|
||||||
|
//!
|
||||||
|
//! \return `true` if the object is useful, `false` otherwise.
|
||||||
|
bool IsUseful() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// MinidumpWritable:
|
||||||
|
|
||||||
|
bool Freeze() override;
|
||||||
|
size_t SizeOfObject() override;
|
||||||
|
std::vector<internal::MinidumpWritable*> Children() override;
|
||||||
|
bool WriteObject(FileWriterInterface* file_writer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<MinidumpAnnotationList> minidump_list_;
|
||||||
|
std::vector<std::unique_ptr<MinidumpAnnotationWriter>> objects_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpAnnotationListWriter);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace crashpad
|
||||||
|
|
||||||
|
#endif // CRASHPAD_MINIDUMP_MINIDUMP_ANNOTATION_WRITER_H_
|
188
minidump/minidump_annotation_writer_test.cc
Normal file
188
minidump/minidump_annotation_writer_test.cc
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
// Copyright 2017 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_annotation_writer.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "base/macros.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "minidump/minidump_extensions.h"
|
||||||
|
#include "minidump/test/minidump_byte_array_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.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
namespace test {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const MinidumpAnnotationList* MinidumpAnnotationListAtStart(
|
||||||
|
const std::string& file_contents,
|
||||||
|
uint32_t count) {
|
||||||
|
MINIDUMP_LOCATION_DESCRIPTOR location_descriptor;
|
||||||
|
location_descriptor.DataSize = static_cast<uint32_t>(
|
||||||
|
sizeof(MinidumpAnnotationList) + count * sizeof(MinidumpAnnotation));
|
||||||
|
location_descriptor.Rva = 0;
|
||||||
|
return MinidumpWritableAtLocationDescriptor<MinidumpAnnotationList>(
|
||||||
|
file_contents, location_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpAnnotationWriter, EmptyList) {
|
||||||
|
StringFile string_file;
|
||||||
|
|
||||||
|
MinidumpAnnotationListWriter list_writer;
|
||||||
|
|
||||||
|
EXPECT_FALSE(list_writer.IsUseful());
|
||||||
|
|
||||||
|
EXPECT_TRUE(list_writer.WriteEverything(&string_file));
|
||||||
|
|
||||||
|
ASSERT_EQ(string_file.string().size(), sizeof(MinidumpAnnotationList));
|
||||||
|
|
||||||
|
auto* list = MinidumpAnnotationListAtStart(string_file.string(), 0);
|
||||||
|
ASSERT_TRUE(list);
|
||||||
|
EXPECT_EQ(0u, list->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpAnnotationWriter, OneItem) {
|
||||||
|
StringFile string_file;
|
||||||
|
|
||||||
|
const char kName[] = "name";
|
||||||
|
const uint16_t kType = 0xFFFF;
|
||||||
|
const std::vector<uint8_t> kValue{'v', 'a', 'l', 'u', 'e', '\0'};
|
||||||
|
|
||||||
|
auto annotation_writer = std::make_unique<MinidumpAnnotationWriter>();
|
||||||
|
annotation_writer->InitializeWithData(kName, kType, kValue);
|
||||||
|
|
||||||
|
MinidumpAnnotationListWriter list_writer;
|
||||||
|
list_writer.AddObject(std::move(annotation_writer));
|
||||||
|
|
||||||
|
EXPECT_TRUE(list_writer.IsUseful());
|
||||||
|
|
||||||
|
EXPECT_TRUE(list_writer.WriteEverything(&string_file));
|
||||||
|
|
||||||
|
ASSERT_EQ(string_file.string().size(),
|
||||||
|
sizeof(MinidumpAnnotationList) + sizeof(MinidumpAnnotation) +
|
||||||
|
sizeof(MinidumpUTF8String) + sizeof(kName) +
|
||||||
|
sizeof(MinidumpByteArray) + kValue.size() +
|
||||||
|
3); // 3 for padding.
|
||||||
|
|
||||||
|
auto* list = MinidumpAnnotationListAtStart(string_file.string(), 1);
|
||||||
|
ASSERT_TRUE(list);
|
||||||
|
EXPECT_EQ(1u, list->count);
|
||||||
|
EXPECT_EQ(kName,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||||
|
list->objects[0].name));
|
||||||
|
EXPECT_EQ(kType, list->objects[0].type);
|
||||||
|
EXPECT_EQ(0u, list->objects[0].reserved);
|
||||||
|
EXPECT_EQ(
|
||||||
|
kValue,
|
||||||
|
MinidumpByteArrayAtRVA(string_file.string(), list->objects[0].value));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpAnnotationWriter, ThreeItems) {
|
||||||
|
StringFile string_file;
|
||||||
|
|
||||||
|
const char* kNames[] = {
|
||||||
|
"~~FIRST~~", " second + ", "3",
|
||||||
|
};
|
||||||
|
const uint16_t kTypes[] = {
|
||||||
|
0x1, 0xABCD, 0x42,
|
||||||
|
};
|
||||||
|
const std::vector<uint8_t> kValues[] = {
|
||||||
|
{'\0'}, {0xB0, 0xA0, 0xD0, 0xD0, 0xD0}, {'T'},
|
||||||
|
};
|
||||||
|
|
||||||
|
MinidumpAnnotationListWriter list_writer;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < arraysize(kNames); ++i) {
|
||||||
|
auto annotation = std::make_unique<MinidumpAnnotationWriter>();
|
||||||
|
annotation->InitializeWithData(kNames[i], kTypes[i], kValues[i]);
|
||||||
|
list_writer.AddObject(std::move(annotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_TRUE(list_writer.WriteEverything(&string_file));
|
||||||
|
|
||||||
|
ASSERT_EQ(string_file.string().size(),
|
||||||
|
sizeof(MinidumpAnnotationList) + 3 * sizeof(MinidumpAnnotation) +
|
||||||
|
3 * sizeof(MinidumpUTF8String) + 3 * sizeof(MinidumpByteArray) +
|
||||||
|
strlen(kNames[0]) + 1 + kValues[0].size() + 2 +
|
||||||
|
strlen(kNames[1]) + 1 + 3 + kValues[1].size() + 1 +
|
||||||
|
strlen(kNames[2]) + 1 + 3 + kValues[2].size() + 2);
|
||||||
|
|
||||||
|
auto* list = MinidumpAnnotationListAtStart(string_file.string(), 3);
|
||||||
|
ASSERT_TRUE(list);
|
||||||
|
EXPECT_EQ(3u, list->count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
EXPECT_EQ(kNames[i],
|
||||||
|
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||||
|
list->objects[i].name));
|
||||||
|
EXPECT_EQ(kTypes[i], list->objects[i].type);
|
||||||
|
EXPECT_EQ(0u, list->objects[i].reserved);
|
||||||
|
EXPECT_EQ(
|
||||||
|
kValues[i],
|
||||||
|
MinidumpByteArrayAtRVA(string_file.string(), list->objects[i].value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MinidumpAnnotationWriter, DuplicateNames) {
|
||||||
|
StringFile string_file;
|
||||||
|
|
||||||
|
const char kName[] = "@@name!";
|
||||||
|
const uint16_t kType = 0x1;
|
||||||
|
const std::vector<uint8_t> kValue1{'r', 'e', 'd', '\0'};
|
||||||
|
const std::vector<uint8_t> kValue2{'m', 'a', 'g', 'e', 'n', 't', 'a', '\0'};
|
||||||
|
|
||||||
|
MinidumpAnnotationListWriter list_writer;
|
||||||
|
|
||||||
|
auto annotation = std::make_unique<MinidumpAnnotationWriter>();
|
||||||
|
annotation->InitializeWithData(kName, kType, kValue1);
|
||||||
|
list_writer.AddObject(std::move(annotation));
|
||||||
|
|
||||||
|
annotation = std::make_unique<MinidumpAnnotationWriter>();
|
||||||
|
annotation->InitializeWithData(kName, kType, kValue2);
|
||||||
|
list_writer.AddObject(std::move(annotation));
|
||||||
|
|
||||||
|
EXPECT_TRUE(list_writer.WriteEverything(&string_file));
|
||||||
|
|
||||||
|
ASSERT_EQ(string_file.string().size(),
|
||||||
|
sizeof(MinidumpAnnotationList) + 2 * sizeof(MinidumpAnnotation) +
|
||||||
|
2 * sizeof(MinidumpUTF8String) + 2 * sizeof(MinidumpByteArray) +
|
||||||
|
2 * sizeof(kName) + kValue1.size() + kValue2.size());
|
||||||
|
|
||||||
|
auto* list = MinidumpAnnotationListAtStart(string_file.string(), 2);
|
||||||
|
ASSERT_TRUE(list);
|
||||||
|
EXPECT_EQ(2u, list->count);
|
||||||
|
|
||||||
|
EXPECT_EQ(kName,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||||
|
list->objects[0].name));
|
||||||
|
EXPECT_EQ(kType, list->objects[0].type);
|
||||||
|
EXPECT_EQ(
|
||||||
|
kValue1,
|
||||||
|
MinidumpByteArrayAtRVA(string_file.string(), list->objects[0].value));
|
||||||
|
|
||||||
|
EXPECT_EQ(kName,
|
||||||
|
MinidumpUTF8StringAtRVAAsString(string_file.string(),
|
||||||
|
list->objects[1].name));
|
||||||
|
EXPECT_EQ(kType, list->objects[1].type);
|
||||||
|
EXPECT_EQ(
|
||||||
|
kValue2,
|
||||||
|
MinidumpByteArrayAtRVA(string_file.string(), list->objects[1].value));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace test
|
||||||
|
} // namespace crashpad
|
@ -282,6 +282,32 @@ struct ALIGNAS(4) PACKED MinidumpSimpleStringDictionary {
|
|||||||
MinidumpSimpleStringDictionaryEntry entries[0];
|
MinidumpSimpleStringDictionaryEntry entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \brief A typed annotation object.
|
||||||
|
struct ALIGNAS(4) PACKED MinidumpAnnotation {
|
||||||
|
//! \brief ::RVA of a MinidumpUTF8String containing the name of the
|
||||||
|
//! annotation.
|
||||||
|
RVA name;
|
||||||
|
|
||||||
|
//! \brief The type of data stored in the \a value of the annotation. This
|
||||||
|
//! may correspond to an \a Annotation::Type or it may be user-defined.
|
||||||
|
uint16_t type;
|
||||||
|
|
||||||
|
//! \brief This field is always `0`.
|
||||||
|
uint16_t reserved;
|
||||||
|
|
||||||
|
//! \brief ::RVA of a MinidumpByteArray to the data for the annotation.
|
||||||
|
RVA value;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \brief A list of annotation objects.
|
||||||
|
struct ALIGNAS(4) PACKED MinidumpAnnotationList {
|
||||||
|
//! \brief The number of annotation objects present.
|
||||||
|
uint32_t count;
|
||||||
|
|
||||||
|
//! \brief A list of MinidumpAnnotation objects.
|
||||||
|
MinidumpAnnotation objects[0];
|
||||||
|
};
|
||||||
|
|
||||||
//! \brief Additional Crashpad-specific information about a module carried
|
//! \brief Additional Crashpad-specific information about a module carried
|
||||||
//! within a minidump file.
|
//! within a minidump file.
|
||||||
//!
|
//!
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
'..',
|
'..',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'minidump_annotation_writer_test.cc',
|
||||||
'minidump_byte_array_writer_test.cc',
|
'minidump_byte_array_writer_test.cc',
|
||||||
'minidump_context_writer_test.cc',
|
'minidump_context_writer_test.cc',
|
||||||
'minidump_crashpad_info_writer_test.cc',
|
'minidump_crashpad_info_writer_test.cc',
|
||||||
|
@ -223,6 +223,12 @@ struct MinidumpSimpleStringDictionaryListTraits {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MinidumpAnnotationListObjectsTraits {
|
||||||
|
using ListType = MinidumpAnnotationList;
|
||||||
|
enum : size_t { kElementSize = sizeof(MinidumpAnnotation) };
|
||||||
|
static size_t ElementCount(const ListType* list) { return list->count; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const typename T::ListType* MinidumpListAtLocationDescriptor(
|
const typename T::ListType* MinidumpListAtLocationDescriptor(
|
||||||
const std::string& file_contents,
|
const std::string& file_contents,
|
||||||
@ -313,6 +319,15 @@ MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
|||||||
MinidumpSimpleStringDictionaryListTraits>(file_contents, location);
|
MinidumpSimpleStringDictionaryListTraits>(file_contents, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
const MinidumpAnnotationList*
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpAnnotationList>(
|
||||||
|
const std::string& file_contents,
|
||||||
|
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||||
|
return MinidumpListAtLocationDescriptor<MinidumpAnnotationListObjectsTraits>(
|
||||||
|
file_contents, location);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -96,6 +96,7 @@ MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MEMORY_INFO_LIST);
|
|||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCrashpadInfoList);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCrashpadInfoList);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpRVAList);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpRVAList);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary);
|
||||||
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpAnnotationList);
|
||||||
|
|
||||||
// These types have final fields carrying variable-sized data (typically string
|
// These types have final fields carrying variable-sized data (typically string
|
||||||
// data).
|
// data).
|
||||||
@ -141,10 +142,10 @@ const T* TMinidumpWritableAtLocationDescriptor(
|
|||||||
//! - With a MINIDUMP_HEADER template parameter, a template specialization
|
//! - With a MINIDUMP_HEADER template parameter, a template specialization
|
||||||
//! ensures that the structure’s magic number and version fields are correct.
|
//! ensures that the structure’s magic number and version fields are correct.
|
||||||
//! - With a MINIDUMP_MEMORY_LIST, MINIDUMP_THREAD_LIST, MINIDUMP_MODULE_LIST,
|
//! - With a MINIDUMP_MEMORY_LIST, MINIDUMP_THREAD_LIST, MINIDUMP_MODULE_LIST,
|
||||||
//! MINIDUMP_MEMORY_INFO_LIST, or MinidumpSimpleStringDictionary template
|
//! MINIDUMP_MEMORY_INFO_LIST, MinidumpSimpleStringDictionary, or
|
||||||
//! parameter, template specializations ensure that the size given by \a
|
//! MinidumpAnnotationList template parameter, template specializations
|
||||||
//! location matches the size expected of a stream containing the number of
|
//! ensure that the size given by \a location matches the size expected of a
|
||||||
//! elements it claims to have.
|
//! stream containing the number of elements it claims to have.
|
||||||
//! - With an IMAGE_DEBUG_MISC, CodeViewRecordPDB20, or CodeViewRecordPDB70
|
//! - With an IMAGE_DEBUG_MISC, CodeViewRecordPDB20, or CodeViewRecordPDB70
|
||||||
//! template parameter, template specializations ensure that the structure
|
//! template parameter, template specializations ensure that the structure
|
||||||
//! has the expected format including any magic number and the `NUL`-
|
//! has the expected format including any magic number and the `NUL`-
|
||||||
@ -230,6 +231,12 @@ MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
|||||||
const std::string& file_contents,
|
const std::string& file_contents,
|
||||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
const MinidumpAnnotationList*
|
||||||
|
MinidumpWritableAtLocationDescriptor<MinidumpAnnotationList>(
|
||||||
|
const std::string& file_contents,
|
||||||
|
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||||
|
|
||||||
//! \brief Returns a typed minidump object located within a minidump file’s
|
//! \brief Returns a typed minidump object located within a minidump file’s
|
||||||
//! contents, where the offset of the object is known.
|
//! contents, where the offset of the object is known.
|
||||||
//!
|
//!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user