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:
Родитель
6950a552bf
Коммит
3231a80e8b
|
@ -33,6 +33,8 @@
|
|||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'minidump_annotation_writer.cc',
|
||||
'minidump_annotation_writer.h',
|
||||
'minidump_byte_array_writer.cc',
|
||||
'minidump_byte_array_writer.h',
|
||||
'minidump_context.h',
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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];
|
||||
};
|
||||
|
||||
//! \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
|
||||
//! within a minidump file.
|
||||
//!
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'minidump_annotation_writer_test.cc',
|
||||
'minidump_byte_array_writer_test.cc',
|
||||
'minidump_context_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>
|
||||
const typename T::ListType* MinidumpListAtLocationDescriptor(
|
||||
const std::string& file_contents,
|
||||
|
@ -313,6 +319,15 @@ MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
|||
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 {
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -96,6 +96,7 @@ MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MEMORY_INFO_LIST);
|
|||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCrashpadInfoList);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpRVAList);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpAnnotationList);
|
||||
|
||||
// These types have final fields carrying variable-sized data (typically string
|
||||
// data).
|
||||
|
@ -141,10 +142,10 @@ const T* TMinidumpWritableAtLocationDescriptor(
|
|||
//! - With a MINIDUMP_HEADER template parameter, a template specialization
|
||||
//! ensures that the structure’s magic number and version fields are correct.
|
||||
//! - With a MINIDUMP_MEMORY_LIST, MINIDUMP_THREAD_LIST, MINIDUMP_MODULE_LIST,
|
||||
//! MINIDUMP_MEMORY_INFO_LIST, or MinidumpSimpleStringDictionary template
|
||||
//! parameter, template specializations ensure that the size given by \a
|
||||
//! location matches the size expected of a stream containing the number of
|
||||
//! elements it claims to have.
|
||||
//! MINIDUMP_MEMORY_INFO_LIST, MinidumpSimpleStringDictionary, or
|
||||
//! MinidumpAnnotationList template parameter, template specializations
|
||||
//! ensure that the size given by \a location matches the size expected of a
|
||||
//! stream containing the number of elements it claims to have.
|
||||
//! - With an IMAGE_DEBUG_MISC, CodeViewRecordPDB20, or CodeViewRecordPDB70
|
||||
//! template parameter, template specializations ensure that the structure
|
||||
//! has the expected format including any magic number and the `NUL`-
|
||||
|
@ -230,6 +231,12 @@ MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
|||
const std::string& file_contents,
|
||||
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
|
||||
//! contents, where the offset of the object is known.
|
||||
//!
|
||||
|
|
Загрузка…
Ссылка в новой задаче