mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 22:26:06 +00:00
[minidump] Add support for RVA64 / MINIDUMP_LOCATION_DESCRIPTOR64
Newer minidump stream types, like MINIDUMP_THREAD_NAME_LIST, use 64-bit RVAs (which have 64-bit location descriptors) instead of 32-bit RVAs and location descriptors. This adds support to MinidumpWritable for the new 64-bit RVA64 and MINIDUMP_LOCATION_DESCRIPTOR64 types. Bug: crashpad:327 Change-Id: Icd67bca600756a68ef9ba7d5a429f935eebf726f Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3673776 Commit-Queue: Ben Hamilton <benhamilton@google.com> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
b1ffe93562
commit
a903f7541f
@ -42,6 +42,15 @@
|
||||
//! \sa MINIDUMP_LOCATION_DESCRIPTOR
|
||||
typedef uint32_t RVA;
|
||||
|
||||
//! \brief A 64-bit offset within a minidump file, relative to the start of its
|
||||
//! MINIDUMP_HEADER.
|
||||
//!
|
||||
//! RVA stands for “relative virtual address”. Within a minidump file, RVAs are
|
||||
//! used as pointers to link structures together.
|
||||
//!
|
||||
//! \sa MINIDUMP_LOCATION_DESCRIPTOR64
|
||||
typedef uint64_t RVA64;
|
||||
|
||||
//! \brief A pointer to a structure or union within a minidump file.
|
||||
struct __attribute__((packed, aligned(4))) MINIDUMP_LOCATION_DESCRIPTOR {
|
||||
//! \brief The size of the referenced structure or union, in bytes.
|
||||
@ -52,6 +61,16 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_LOCATION_DESCRIPTOR {
|
||||
RVA Rva;
|
||||
};
|
||||
|
||||
//! \brief A 64-bit pointer to a structure or union within a minidump file.
|
||||
struct __attribute__((packed, aligned(4))) MINIDUMP_LOCATION_DESCRIPTOR64 {
|
||||
//! \brief The size of the referenced structure or union, in bytes.
|
||||
uint64_t DataSize;
|
||||
|
||||
//! \brief The 64-bit relative virtual address of the structure or union
|
||||
//! within the minidump file.
|
||||
RVA64 Rva;
|
||||
};
|
||||
|
||||
//! \brief A pointer to a snapshot of a region of memory contained within a
|
||||
//! minidump file.
|
||||
//!
|
||||
|
@ -75,6 +75,12 @@ void MinidumpWritable::RegisterRVA(RVA* rva) {
|
||||
registered_rvas_.push_back(rva);
|
||||
}
|
||||
|
||||
void MinidumpWritable::RegisterRVA(RVA64* rva64) {
|
||||
DCHECK_LE(state_, kStateFrozen);
|
||||
|
||||
registered_rva64s_.push_back(rva64);
|
||||
}
|
||||
|
||||
void MinidumpWritable::RegisterLocationDescriptor(
|
||||
MINIDUMP_LOCATION_DESCRIPTOR* location_descriptor) {
|
||||
DCHECK_LE(state_, kStateFrozen);
|
||||
@ -82,12 +88,20 @@ void MinidumpWritable::RegisterLocationDescriptor(
|
||||
registered_location_descriptors_.push_back(location_descriptor);
|
||||
}
|
||||
|
||||
void MinidumpWritable::RegisterLocationDescriptor(
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64* location_descriptor64) {
|
||||
DCHECK_LE(state_, kStateFrozen);
|
||||
|
||||
registered_location_descriptor64s_.push_back(location_descriptor64);
|
||||
}
|
||||
|
||||
MinidumpWritable::MinidumpWritable()
|
||||
: registered_rvas_(),
|
||||
registered_rva64s_(),
|
||||
registered_location_descriptors_(),
|
||||
registered_location_descriptor64s_(),
|
||||
leading_pad_bytes_(0),
|
||||
state_(kStateMutable) {
|
||||
}
|
||||
state_(kStateMutable) {}
|
||||
|
||||
bool MinidumpWritable::Freeze() {
|
||||
DCHECK_EQ(state_, kStateMutable);
|
||||
@ -160,10 +174,10 @@ size_t MinidumpWritable::WillWriteAtOffset(
|
||||
return kInvalidSize;
|
||||
}
|
||||
|
||||
// Populate the RVA fields in other objects that have registered to point to
|
||||
// this one. Typically, a parent object will have registered to point to its
|
||||
// children, but this can also occur where no parent-child relationship
|
||||
// exists.
|
||||
// Populate the 32-bit RVA fields in other objects that have registered to
|
||||
// point to this one. Typically, a parent object will have registered to
|
||||
// point to its children, but this can also occur where no parent-child
|
||||
// relationship exists.
|
||||
if (!registered_rvas_.empty() ||
|
||||
!registered_location_descriptors_.empty()) {
|
||||
RVA local_rva;
|
||||
@ -191,12 +205,45 @@ size_t MinidumpWritable::WillWriteAtOffset(
|
||||
}
|
||||
}
|
||||
|
||||
// This object is now considered writable. However, if it contains RVA or
|
||||
// MINIDUMP_LOCATION_DESCRIPTOR fields, they may not be fully updated yet,
|
||||
// because it’s the repsonsibility of these fields’ pointees to update them.
|
||||
// Once WillWriteAtOffset has completed running for both phases on an entire
|
||||
// tree, and the entire tree has moved into kStateFrozen, all RVA and
|
||||
// MINIDUMP_LOCATION_DESCRIPTOR fields within that tree will be populated.
|
||||
// Populate the 64-bit RVA fields in other objects that have registered to
|
||||
// point to this one. Typically, a parent object will have registered to
|
||||
// point to its children, but this can also occur where no parent-child
|
||||
// relationship exists.
|
||||
if (!registered_rva64s_.empty() ||
|
||||
!registered_location_descriptor64s_.empty()) {
|
||||
RVA64 local_rva64;
|
||||
if (!AssignIfInRange(&local_rva64, local_offset)) {
|
||||
LOG(ERROR) << "offset " << local_offset << " out of range";
|
||||
return kInvalidSize;
|
||||
}
|
||||
|
||||
for (RVA64* rva64 : registered_rva64s_) {
|
||||
*rva64 = local_rva64;
|
||||
}
|
||||
|
||||
if (!registered_location_descriptor64s_.empty()) {
|
||||
decltype(registered_location_descriptor64s_[0]->DataSize) local_size;
|
||||
if (!AssignIfInRange(&local_size, size)) {
|
||||
LOG(ERROR) << "size " << size << " out of range";
|
||||
return kInvalidSize;
|
||||
}
|
||||
|
||||
for (MINIDUMP_LOCATION_DESCRIPTOR64* location_descriptor :
|
||||
registered_location_descriptor64s_) {
|
||||
location_descriptor->DataSize = local_size;
|
||||
location_descriptor->Rva = local_rva64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This object is now considered writable. However, if it contains RVA/RVA64
|
||||
// or MINIDUMP_LOCATION_DESCRIPTOR/MINIDUMP_LOCATION_DESCRIPTOR64 fields,
|
||||
// they may not be fully updated yet, because it’s the repsonsibility of
|
||||
// these fields’ pointees to update them. Once WillWriteAtOffset has
|
||||
// completed running for both phases on an entire tree, and the entire tree
|
||||
// has moved into kStateFrozen, all RVA/RVA64 and
|
||||
// MINIDUMP_LOCATION_DESCRIPTOR/MINIDUMP_LOCATION_DESCRIPTOR64 fields within
|
||||
// that tree will be populated.
|
||||
state_ = kStateWritable;
|
||||
} else {
|
||||
if (phase == kPhaseEarly) {
|
||||
|
@ -71,6 +71,9 @@ class MinidumpWritable {
|
||||
// to be able to register their own pointers with distinct objects.
|
||||
void RegisterRVA(RVA* rva);
|
||||
|
||||
//! \brief 64-bit specialization of RegisterRVA.
|
||||
void RegisterRVA(RVA64* rva);
|
||||
|
||||
//! \brief Registers a location descriptor as one that should point to the
|
||||
//! object on which this method is called.
|
||||
//!
|
||||
@ -89,6 +92,10 @@ class MinidumpWritable {
|
||||
void RegisterLocationDescriptor(
|
||||
MINIDUMP_LOCATION_DESCRIPTOR* location_descriptor);
|
||||
|
||||
//! \brief 64-bit specialization of RegisterLocationDescriptor.
|
||||
void RegisterLocationDescriptor(
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64* location_descriptor64);
|
||||
|
||||
protected:
|
||||
//! \brief Identifies the state of an object.
|
||||
//!
|
||||
@ -267,9 +274,15 @@ class MinidumpWritable {
|
||||
private:
|
||||
std::vector<RVA*> registered_rvas_; // weak
|
||||
|
||||
std::vector<RVA64*> registered_rva64s_; // weak
|
||||
|
||||
// weak
|
||||
std::vector<MINIDUMP_LOCATION_DESCRIPTOR*> registered_location_descriptors_;
|
||||
|
||||
// weak
|
||||
std::vector<MINIDUMP_LOCATION_DESCRIPTOR64*>
|
||||
registered_location_descriptor64s_;
|
||||
|
||||
size_t leading_pad_bytes_;
|
||||
State state_;
|
||||
};
|
||||
|
@ -485,14 +485,15 @@ TEST(MinidumpWritable, MinidumpWritable) {
|
||||
}
|
||||
}
|
||||
|
||||
class TestRVAMinidumpWritable final : public BaseTestMinidumpWritable {
|
||||
template <typename RVAType>
|
||||
class TTestRVAMinidumpWritable final : public BaseTestMinidumpWritable {
|
||||
public:
|
||||
TestRVAMinidumpWritable() : BaseTestMinidumpWritable(), rva_() {}
|
||||
TTestRVAMinidumpWritable() : BaseTestMinidumpWritable(), rva_() {}
|
||||
|
||||
TestRVAMinidumpWritable(const TestRVAMinidumpWritable&) = delete;
|
||||
TestRVAMinidumpWritable& operator=(const TestRVAMinidumpWritable&) = delete;
|
||||
TTestRVAMinidumpWritable(const TTestRVAMinidumpWritable&) = delete;
|
||||
TTestRVAMinidumpWritable& operator=(const TTestRVAMinidumpWritable&) = delete;
|
||||
|
||||
~TestRVAMinidumpWritable() {}
|
||||
~TTestRVAMinidumpWritable() {}
|
||||
|
||||
void SetRVA(MinidumpWritable* other) { other->RegisterRVA(&rva_); }
|
||||
|
||||
@ -509,15 +510,46 @@ class TestRVAMinidumpWritable final : public BaseTestMinidumpWritable {
|
||||
}
|
||||
|
||||
private:
|
||||
RVA rva_;
|
||||
RVAType rva_;
|
||||
};
|
||||
|
||||
RVA RVAAtIndex(const std::string& string, size_t index) {
|
||||
return *reinterpret_cast<const RVA*>(&string[index * sizeof(RVA)]);
|
||||
template <typename RVAType>
|
||||
RVAType TRVAAtIndex(const std::string& string, size_t index) {
|
||||
return *reinterpret_cast<const RVAType*>(&string[index * sizeof(RVAType)]);
|
||||
}
|
||||
|
||||
TEST(MinidumpWritable, RVA) {
|
||||
template <typename T>
|
||||
struct TestNames {};
|
||||
|
||||
template <>
|
||||
struct TestNames<RVA> {
|
||||
static constexpr char kName[] = "RVA";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TestNames<RVA64> {
|
||||
static constexpr char kName[] = "RVA64";
|
||||
};
|
||||
|
||||
class TestTypeNames {
|
||||
public:
|
||||
template <typename T>
|
||||
static std::string GetName(int) {
|
||||
return std::string(TestNames<T>::kName);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RVAType>
|
||||
class MinidumpWritable : public ::testing::Test {};
|
||||
|
||||
using RVATypes = ::testing::Types<RVA, RVA64>;
|
||||
TYPED_TEST_SUITE(MinidumpWritable, RVATypes, TestTypeNames);
|
||||
|
||||
TYPED_TEST(MinidumpWritable, RVA) {
|
||||
StringFile string_file;
|
||||
using TestRVAMinidumpWritable = TTestRVAMinidumpWritable<TypeParam>;
|
||||
const auto RVAAtIndex = TRVAAtIndex<TypeParam>;
|
||||
constexpr size_t kRVASize = sizeof(TypeParam);
|
||||
|
||||
{
|
||||
SCOPED_TRACE("unset");
|
||||
@ -525,8 +557,8 @@ TEST(MinidumpWritable, RVA) {
|
||||
TestRVAMinidumpWritable rva_writable;
|
||||
EXPECT_TRUE(rva_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * sizeof(RVA));
|
||||
ASSERT_EQ(string_file.string().size(), kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * kRVASize);
|
||||
rva_writable.Verify();
|
||||
}
|
||||
|
||||
@ -537,8 +569,8 @@ TEST(MinidumpWritable, RVA) {
|
||||
rva_writable.SetRVA(&rva_writable);
|
||||
EXPECT_TRUE(rva_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * sizeof(RVA));
|
||||
ASSERT_EQ(string_file.string().size(), kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * kRVASize);
|
||||
rva_writable.Verify();
|
||||
}
|
||||
|
||||
@ -552,9 +584,9 @@ TEST(MinidumpWritable, RVA) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 2 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 1 * sizeof(RVA));
|
||||
ASSERT_EQ(string_file.string().size(), 2 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 0 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 1 * kRVASize);
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -567,9 +599,9 @@ TEST(MinidumpWritable, RVA) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 2 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * sizeof(RVA));
|
||||
ASSERT_EQ(string_file.string().size(), 2 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * kRVASize);
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -583,9 +615,9 @@ TEST(MinidumpWritable, RVA) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 2 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * sizeof(RVA));
|
||||
ASSERT_EQ(string_file.string().size(), 2 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * kRVASize);
|
||||
parent.Verify();
|
||||
}
|
||||
|
||||
@ -607,28 +639,29 @@ TEST(MinidumpWritable, RVA) {
|
||||
child.AddChild(&grandchild_2);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 5 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 2), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 3), 1 * sizeof(RVA));
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 4), 1 * sizeof(RVA));
|
||||
ASSERT_EQ(string_file.string().size(), 5 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 0), 1 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 1), 0 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 2), 1 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 3), 1 * kRVASize);
|
||||
EXPECT_EQ(RVAAtIndex(string_file.string(), 4), 1 * kRVASize);
|
||||
parent.Verify();
|
||||
}
|
||||
}
|
||||
|
||||
class TestLocationDescriptorMinidumpWritable final
|
||||
template <typename MinidumpLocationDescriptorType>
|
||||
class TTestLocationDescriptorMinidumpWritable final
|
||||
: public BaseTestMinidumpWritable {
|
||||
public:
|
||||
TestLocationDescriptorMinidumpWritable()
|
||||
TTestLocationDescriptorMinidumpWritable()
|
||||
: BaseTestMinidumpWritable(), location_descriptor_(), string_() {}
|
||||
|
||||
TestLocationDescriptorMinidumpWritable(
|
||||
const TestLocationDescriptorMinidumpWritable&) = delete;
|
||||
TestLocationDescriptorMinidumpWritable& operator=(
|
||||
const TestLocationDescriptorMinidumpWritable&) = delete;
|
||||
TTestLocationDescriptorMinidumpWritable(
|
||||
const TTestLocationDescriptorMinidumpWritable&) = delete;
|
||||
TTestLocationDescriptorMinidumpWritable& operator=(
|
||||
const TTestLocationDescriptorMinidumpWritable&) = delete;
|
||||
|
||||
~TestLocationDescriptorMinidumpWritable() {}
|
||||
~TTestLocationDescriptorMinidumpWritable() {}
|
||||
|
||||
void SetLocationDescriptor(MinidumpWritable* other) {
|
||||
other->RegisterLocationDescriptor(&location_descriptor_);
|
||||
@ -658,30 +691,61 @@ class TestLocationDescriptorMinidumpWritable final
|
||||
}
|
||||
|
||||
private:
|
||||
MINIDUMP_LOCATION_DESCRIPTOR location_descriptor_;
|
||||
MinidumpLocationDescriptorType location_descriptor_;
|
||||
std::string string_;
|
||||
};
|
||||
|
||||
struct LocationDescriptorAndData {
|
||||
MINIDUMP_LOCATION_DESCRIPTOR location_descriptor;
|
||||
template <typename MinidumpLocationDescriptorType>
|
||||
struct TLocationDescriptorAndData {
|
||||
MinidumpLocationDescriptorType location_descriptor;
|
||||
char string[1];
|
||||
};
|
||||
|
||||
const LocationDescriptorAndData* LDDAtIndex(const std::string& string,
|
||||
size_t index) {
|
||||
return reinterpret_cast<const LocationDescriptorAndData*>(&string[index]);
|
||||
template <typename MinidumpLocationDescriptorType>
|
||||
const TLocationDescriptorAndData<MinidumpLocationDescriptorType>* TLDDAtIndex(
|
||||
const std::string& string,
|
||||
size_t index) {
|
||||
return reinterpret_cast<
|
||||
const TLocationDescriptorAndData<MinidumpLocationDescriptorType>*>(
|
||||
&string[index]);
|
||||
}
|
||||
|
||||
TEST(MinidumpWritable, LocationDescriptor) {
|
||||
template <typename MinidumpLocationDescriptorType>
|
||||
class MinidumpWritableLocationDescriptor : public ::testing::Test {};
|
||||
|
||||
template <>
|
||||
struct TestNames<MINIDUMP_LOCATION_DESCRIPTOR> {
|
||||
static constexpr char kName[] = "MINIDUMP_LOCATION_DESCRIPTOR";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TestNames<MINIDUMP_LOCATION_DESCRIPTOR64> {
|
||||
static constexpr char kName[] = "MINIDUMP_LOCATION_DESCRIPTOR64";
|
||||
};
|
||||
|
||||
using MinidumpLocationDescriptorTypes =
|
||||
::testing::Types<MINIDUMP_LOCATION_DESCRIPTOR,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64>;
|
||||
TYPED_TEST_SUITE(MinidumpWritableLocationDescriptor,
|
||||
MinidumpLocationDescriptorTypes,
|
||||
TestTypeNames);
|
||||
|
||||
TYPED_TEST(MinidumpWritableLocationDescriptor, LocationDescriptor) {
|
||||
StringFile string_file;
|
||||
|
||||
using LocationDescriptorAndData = TLocationDescriptorAndData<TypeParam>;
|
||||
const auto LDDAtIndex = TLDDAtIndex<TypeParam>;
|
||||
using TestLocationDescriptorMinidumpWritable =
|
||||
TTestLocationDescriptorMinidumpWritable<TypeParam>;
|
||||
constexpr size_t kMinidumpLocationDescriptorSize = sizeof(TypeParam);
|
||||
|
||||
{
|
||||
SCOPED_TRACE("unset");
|
||||
string_file.Reset();
|
||||
TestLocationDescriptorMinidumpWritable location_descriptor_writable;
|
||||
EXPECT_TRUE(location_descriptor_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 9u);
|
||||
ASSERT_EQ(string_file.string().size(), kMinidumpLocationDescriptorSize + 1);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 0u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
@ -696,9 +760,10 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
&location_descriptor_writable);
|
||||
EXPECT_TRUE(location_descriptor_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 9u);
|
||||
ASSERT_EQ(string_file.string().size(), kMinidumpLocationDescriptorSize + 1);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 9u);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 1);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
location_descriptor_writable.Verify();
|
||||
}
|
||||
@ -712,9 +777,10 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
location_descriptor_writable.SetString("zz");
|
||||
EXPECT_TRUE(location_descriptor_writable.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 11u);
|
||||
ASSERT_EQ(string_file.string().size(), kMinidumpLocationDescriptorSize + 3);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 11u);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 3);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("zz", ldd->string);
|
||||
location_descriptor_writable.Verify();
|
||||
@ -732,14 +798,18 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 22u);
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
kMinidumpLocationDescriptorSize * 2 + 6);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 11u);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 3);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("yy", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 12);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
ldd = LDDAtIndex(string_file.string(), kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 2);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva,
|
||||
kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_STREQ("x", ldd->string);
|
||||
parent.Verify();
|
||||
}
|
||||
@ -755,12 +825,15 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 23u);
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
kMinidumpLocationDescriptorSize * 2 + 7);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 11u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 3);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva,
|
||||
kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_STREQ("www", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 12);
|
||||
ldd = LDDAtIndex(string_file.string(), kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 0u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("vv", ldd->string);
|
||||
@ -779,13 +852,17 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
parent.AddChild(&child);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 29u);
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
kMinidumpLocationDescriptorSize * 2 + 13);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 13u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 16u);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 5);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva,
|
||||
kMinidumpLocationDescriptorSize + 8);
|
||||
EXPECT_STREQ("uuuu", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 16);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 13u);
|
||||
ldd = LDDAtIndex(string_file.string(), kMinidumpLocationDescriptorSize + 8);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 5);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("tttt", ldd->string);
|
||||
parent.Verify();
|
||||
@ -814,26 +891,38 @@ TEST(MinidumpWritable, LocationDescriptor) {
|
||||
child.AddChild(&grandchild_2);
|
||||
EXPECT_TRUE(parent.WriteEverything(&string_file));
|
||||
|
||||
ASSERT_EQ(string_file.string().size(), 58u);
|
||||
ASSERT_EQ(string_file.string().size(),
|
||||
kMinidumpLocationDescriptorSize * 5 + 18);
|
||||
const LocationDescriptorAndData* ldd = LDDAtIndex(string_file.string(), 0);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 2);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva,
|
||||
kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_STREQ("s", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 12);
|
||||
ldd = LDDAtIndex(string_file.string(), kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 0u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 0u);
|
||||
EXPECT_STREQ("r", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 24);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
ldd = LDDAtIndex(string_file.string(),
|
||||
kMinidumpLocationDescriptorSize * 2 + 8);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 2);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva,
|
||||
kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_STREQ("q", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 36);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
ldd = LDDAtIndex(string_file.string(),
|
||||
kMinidumpLocationDescriptorSize * 3 + 12);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 2);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva,
|
||||
kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_STREQ("p", ldd->string);
|
||||
ldd = LDDAtIndex(string_file.string(), 48);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize, 10u);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva, 12u);
|
||||
ldd = LDDAtIndex(string_file.string(),
|
||||
kMinidumpLocationDescriptorSize * 4 + 16);
|
||||
EXPECT_EQ(ldd->location_descriptor.DataSize,
|
||||
kMinidumpLocationDescriptorSize + 2);
|
||||
EXPECT_EQ(ldd->location_descriptor.Rva,
|
||||
kMinidumpLocationDescriptorSize + 4);
|
||||
EXPECT_STREQ("o", ldd->string);
|
||||
parent.Verify();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user