mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-26 23:01:05 +08:00
minidump: Migrate the rest of the tests to
MinidumpWritableAtLocationDescriptor<>(). TEST=minidump_test R=rsesek@chromium.org Review URL: https://codereview.chromium.org/670853002
This commit is contained in:
parent
8a6a4c68e4
commit
20f95a2f5b
@ -19,6 +19,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_context.h"
|
||||
#include "minidump/test/minidump_context_test_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "util/file/string_file_writer.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -39,7 +40,7 @@ TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
ASSERT_EQ(sizeof(MinidumpContextX86), file_writer.string().size());
|
||||
|
||||
const MinidumpContextX86* observed =
|
||||
reinterpret_cast<const MinidumpContextX86*>(&file_writer.string()[0]);
|
||||
MinidumpWritableAtRVA<MinidumpContextX86>(file_writer.string(), 0);
|
||||
ExpectMinidumpContextX86(0, observed);
|
||||
}
|
||||
|
||||
@ -56,7 +57,7 @@ TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
ASSERT_EQ(sizeof(MinidumpContextX86), file_writer.string().size());
|
||||
|
||||
const MinidumpContextX86* observed =
|
||||
reinterpret_cast<const MinidumpContextX86*>(&file_writer.string()[0]);
|
||||
MinidumpWritableAtRVA<MinidumpContextX86>(file_writer.string(), 0);
|
||||
ExpectMinidumpContextX86(kSeed, observed);
|
||||
}
|
||||
}
|
||||
@ -75,7 +76,7 @@ TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
ASSERT_EQ(sizeof(MinidumpContextAMD64), file_writer.string().size());
|
||||
|
||||
const MinidumpContextAMD64* observed =
|
||||
reinterpret_cast<const MinidumpContextAMD64*>(&file_writer.string()[0]);
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(file_writer.string(), 0);
|
||||
ExpectMinidumpContextAMD64(0, observed);
|
||||
}
|
||||
|
||||
@ -92,7 +93,7 @@ TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
ASSERT_EQ(sizeof(MinidumpContextAMD64), file_writer.string().size());
|
||||
|
||||
const MinidumpContextAMD64* observed =
|
||||
reinterpret_cast<const MinidumpContextAMD64*>(&file_writer.string()[0]);
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(file_writer.string(), 0);
|
||||
ExpectMinidumpContextAMD64(kSeed, observed);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#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 {
|
||||
@ -55,20 +56,19 @@ void GetCrashpadInfoStream(
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeCrashpadInfo, directory[0].StreamType);
|
||||
ASSERT_EQ(sizeof(MinidumpCrashpadInfo), directory[0].Location.DataSize);
|
||||
ASSERT_EQ(kCrashpadInfoStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kCrashpadInfoStreamOffset, directory[0].Location.Rva);
|
||||
|
||||
*crashpad_info = reinterpret_cast<const MinidumpCrashpadInfo*>(
|
||||
&file_contents[kCrashpadInfoStreamOffset]);
|
||||
*crashpad_info = MinidumpWritableAtLocationDescriptor<MinidumpCrashpadInfo>(
|
||||
file_contents, directory[0].Location);
|
||||
ASSERT_TRUE(*crashpad_info);
|
||||
|
||||
if (simple_annotations) {
|
||||
ASSERT_GE((*crashpad_info)->simple_annotations.DataSize,
|
||||
sizeof(MinidumpSimpleStringDictionary));
|
||||
ASSERT_EQ(kSimpleAnnotationsOffset,
|
||||
EXPECT_EQ(kSimpleAnnotationsOffset,
|
||||
(*crashpad_info)->simple_annotations.Rva);
|
||||
*simple_annotations =
|
||||
reinterpret_cast<const MinidumpSimpleStringDictionary*>(
|
||||
&file_contents[kSimpleAnnotationsOffset]);
|
||||
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);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "minidump/test/minidump_context_test_util.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "util/file/string_file_writer.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -50,11 +51,12 @@ void GetExceptionStream(const std::string& file_contents,
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0));
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeException, directory[0].StreamType);
|
||||
ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_EXCEPTION_STREAM));
|
||||
ASSERT_EQ(kExceptionStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kExceptionStreamOffset, directory[0].Location.Rva);
|
||||
|
||||
*exception_stream = reinterpret_cast<const MINIDUMP_EXCEPTION_STREAM*>(
|
||||
&file_contents[kExceptionStreamOffset]);
|
||||
*exception_stream =
|
||||
MinidumpWritableAtLocationDescriptor<MINIDUMP_EXCEPTION_STREAM>(
|
||||
file_contents, directory[0].Location);
|
||||
ASSERT_TRUE(exception_stream);
|
||||
}
|
||||
|
||||
// The MINIDUMP_EXCEPTION_STREAMs |expected| and |observed| are compared against
|
||||
@ -83,13 +85,9 @@ void ExpectExceptionStream(const MINIDUMP_EXCEPTION_STREAM* expected,
|
||||
EXPECT_EQ(expected->ExceptionRecord.ExceptionInformation[index],
|
||||
observed->ExceptionRecord.ExceptionInformation[index]);
|
||||
}
|
||||
EXPECT_EQ(expected->ThreadContext.DataSize, observed->ThreadContext.DataSize);
|
||||
ASSERT_NE(0u, observed->ThreadContext.DataSize);
|
||||
ASSERT_NE(0u, observed->ThreadContext.Rva);
|
||||
ASSERT_GE(file_contents.size(),
|
||||
observed->ThreadContext.Rva + observed->ThreadContext.DataSize);
|
||||
*context = reinterpret_cast<const MinidumpContextX86*>(
|
||||
&file_contents[observed->ThreadContext.Rva]);
|
||||
*context = MinidumpWritableAtLocationDescriptor<MinidumpContextX86>(
|
||||
file_contents, observed->ThreadContext);
|
||||
ASSERT_TRUE(context);
|
||||
}
|
||||
|
||||
TEST(MinidumpExceptionWriter, Minimal) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "minidump/minidump_stream_writer.h"
|
||||
#include "minidump/minidump_writable.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "util/file/file_writer.h"
|
||||
#include "util/file/string_file_writer.h"
|
||||
|
||||
@ -106,8 +107,9 @@ TEST(MinidumpFileWriter, OneStream) {
|
||||
EXPECT_EQ(kStreamSize, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStreamOffset, directory[0].Location.Rva);
|
||||
|
||||
const uint8_t* stream_data =
|
||||
reinterpret_cast<const uint8_t*>(&file_writer.string()[kStreamOffset]);
|
||||
const uint8_t* stream_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
file_writer.string(), directory[0].Location);
|
||||
ASSERT_TRUE(stream_data);
|
||||
|
||||
std::string expected_stream(kStreamSize, kStreamValue);
|
||||
EXPECT_EQ(0, memcmp(stream_data, expected_stream.c_str(), kStreamSize));
|
||||
@ -118,38 +120,38 @@ TEST(MinidumpFileWriter, ThreeStreams) {
|
||||
const time_t kTimestamp = 0x155d2fb8;
|
||||
minidump_file.SetTimestamp(kTimestamp);
|
||||
|
||||
const size_t kStream1Size = 5;
|
||||
const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x6d);
|
||||
const uint8_t kStream1Value = 0x5a;
|
||||
TestStream stream1(kStream1Type, kStream1Size, kStream1Value);
|
||||
minidump_file.AddStream(&stream1);
|
||||
const size_t kStream0Size = 5;
|
||||
const MinidumpStreamType kStream0Type = static_cast<MinidumpStreamType>(0x6d);
|
||||
const uint8_t kStream0Value = 0x5a;
|
||||
TestStream stream0(kStream0Type, kStream0Size, kStream0Value);
|
||||
minidump_file.AddStream(&stream0);
|
||||
|
||||
// Make the second stream’s type be a smaller quantity than the first stream’s
|
||||
// to test that the streams show up in the order that they were added, not in
|
||||
// numeric order.
|
||||
const size_t kStream2Size = 3;
|
||||
const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x4d);
|
||||
const uint8_t kStream2Value = 0xa5;
|
||||
const size_t kStream1Size = 3;
|
||||
const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x4d);
|
||||
const uint8_t kStream1Value = 0xa5;
|
||||
TestStream stream1(kStream1Type, kStream1Size, kStream1Value);
|
||||
minidump_file.AddStream(&stream1);
|
||||
|
||||
const size_t kStream2Size = 1;
|
||||
const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x7e);
|
||||
const uint8_t kStream2Value = 0x36;
|
||||
TestStream stream2(kStream2Type, kStream2Size, kStream2Value);
|
||||
minidump_file.AddStream(&stream2);
|
||||
|
||||
const size_t kStream3Size = 1;
|
||||
const MinidumpStreamType kStream3Type = static_cast<MinidumpStreamType>(0x7e);
|
||||
const uint8_t kStream3Value = 0x36;
|
||||
TestStream stream3(kStream3Type, kStream3Size, kStream3Value);
|
||||
minidump_file.AddStream(&stream3);
|
||||
|
||||
StringFileWriter file_writer;
|
||||
ASSERT_TRUE(minidump_file.WriteEverything(&file_writer));
|
||||
|
||||
const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER);
|
||||
const size_t kStream1Offset =
|
||||
const size_t kStream0Offset =
|
||||
kDirectoryOffset + 3 * sizeof(MINIDUMP_DIRECTORY);
|
||||
const size_t kStream2Padding = 3;
|
||||
const size_t kStream1Padding = 3;
|
||||
const size_t kStream1Offset = kStream0Offset + kStream0Size + kStream1Padding;
|
||||
const size_t kStream2Padding = 1;
|
||||
const size_t kStream2Offset = kStream1Offset + kStream1Size + kStream2Padding;
|
||||
const size_t kStream3Padding = 1;
|
||||
const size_t kStream3Offset = kStream2Offset + kStream2Size + kStream3Padding;
|
||||
const size_t kFileSize = kStream3Offset + kStream3Size;
|
||||
const size_t kFileSize = kStream2Offset + kStream2Size;
|
||||
|
||||
ASSERT_EQ(kFileSize, file_writer.string().size());
|
||||
|
||||
@ -159,40 +161,43 @@ TEST(MinidumpFileWriter, ThreeStreams) {
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 3, kTimestamp));
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
EXPECT_EQ(kStream1Type, directory[0].StreamType);
|
||||
EXPECT_EQ(kStream1Size, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStream1Offset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kStream2Type, directory[1].StreamType);
|
||||
EXPECT_EQ(kStream2Size, directory[1].Location.DataSize);
|
||||
EXPECT_EQ(kStream2Offset, directory[1].Location.Rva);
|
||||
EXPECT_EQ(kStream3Type, directory[2].StreamType);
|
||||
EXPECT_EQ(kStream3Size, directory[2].Location.DataSize);
|
||||
EXPECT_EQ(kStream3Offset, directory[2].Location.Rva);
|
||||
EXPECT_EQ(kStream0Type, directory[0].StreamType);
|
||||
EXPECT_EQ(kStream0Size, directory[0].Location.DataSize);
|
||||
EXPECT_EQ(kStream0Offset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kStream1Type, directory[1].StreamType);
|
||||
EXPECT_EQ(kStream1Size, directory[1].Location.DataSize);
|
||||
EXPECT_EQ(kStream1Offset, directory[1].Location.Rva);
|
||||
EXPECT_EQ(kStream2Type, directory[2].StreamType);
|
||||
EXPECT_EQ(kStream2Size, directory[2].Location.DataSize);
|
||||
EXPECT_EQ(kStream2Offset, directory[2].Location.Rva);
|
||||
|
||||
const uint8_t* stream1_data =
|
||||
reinterpret_cast<const uint8_t*>(&file_writer.string()[kStream1Offset]);
|
||||
const uint8_t* stream0_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
file_writer.string(), directory[0].Location);
|
||||
ASSERT_TRUE(stream0_data);
|
||||
|
||||
std::string expected_stream0(kStream0Size, kStream0Value);
|
||||
EXPECT_EQ(0, memcmp(stream0_data, expected_stream0.c_str(), kStream0Size));
|
||||
|
||||
const int kZeroes[16] = {};
|
||||
ASSERT_GE(sizeof(kZeroes), kStream1Padding);
|
||||
EXPECT_EQ(0, memcmp(stream0_data + kStream0Size, kZeroes, kStream1Padding));
|
||||
|
||||
const uint8_t* stream1_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
file_writer.string(), directory[1].Location);
|
||||
ASSERT_TRUE(stream1_data);
|
||||
|
||||
std::string expected_stream1(kStream1Size, kStream1Value);
|
||||
EXPECT_EQ(0, memcmp(stream1_data, expected_stream1.c_str(), kStream1Size));
|
||||
|
||||
const int kZeroes[16] = {};
|
||||
ASSERT_GE(sizeof(kZeroes), kStream2Padding);
|
||||
EXPECT_EQ(0, memcmp(stream1_data + kStream1Size, kZeroes, kStream2Padding));
|
||||
|
||||
const uint8_t* stream2_data =
|
||||
reinterpret_cast<const uint8_t*>(&file_writer.string()[kStream2Offset]);
|
||||
const uint8_t* stream2_data = MinidumpWritableAtLocationDescriptor<uint8_t>(
|
||||
file_writer.string(), directory[2].Location);
|
||||
ASSERT_TRUE(stream2_data);
|
||||
|
||||
std::string expected_stream2(kStream2Size, kStream2Value);
|
||||
EXPECT_EQ(0, memcmp(stream2_data, expected_stream2.c_str(), kStream2Size));
|
||||
|
||||
ASSERT_GE(sizeof(kZeroes), kStream3Padding);
|
||||
EXPECT_EQ(0, memcmp(stream2_data + kStream2Size, kZeroes, kStream3Padding));
|
||||
|
||||
const uint8_t* stream3_data =
|
||||
reinterpret_cast<const uint8_t*>(&file_writer.string()[kStream3Offset]);
|
||||
|
||||
std::string expected_stream3(kStream3Size, kStream3Value);
|
||||
EXPECT_EQ(0, memcmp(stream3_data, expected_stream3.c_str(), kStream3Size));
|
||||
}
|
||||
|
||||
TEST(MinidumpFileWriter, ZeroLengthStream) {
|
||||
@ -226,18 +231,18 @@ TEST(MinidumpFileWriter, ZeroLengthStream) {
|
||||
TEST(MinidumpFileWriterDeathTest, SameStreamType) {
|
||||
MinidumpFileWriter minidump_file;
|
||||
|
||||
const size_t kStream1Size = 5;
|
||||
const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x4d);
|
||||
const uint8_t kStream1Value = 0x5a;
|
||||
TestStream stream1(kStream1Type, kStream1Size, kStream1Value);
|
||||
minidump_file.AddStream(&stream1);
|
||||
const size_t kStream0Size = 5;
|
||||
const MinidumpStreamType kStream0Type = static_cast<MinidumpStreamType>(0x4d);
|
||||
const uint8_t kStream0Value = 0x5a;
|
||||
TestStream stream0(kStream0Type, kStream0Size, kStream0Value);
|
||||
minidump_file.AddStream(&stream0);
|
||||
|
||||
// It is an error to add a second stream of the same type.
|
||||
const size_t kStream2Size = 3;
|
||||
const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x4d);
|
||||
const uint8_t kStream2Value = 0xa5;
|
||||
TestStream stream2(kStream2Type, kStream2Size, kStream2Value);
|
||||
ASSERT_DEATH(minidump_file.AddStream(&stream2), "already present");
|
||||
const size_t kStream1Size = 3;
|
||||
const MinidumpStreamType kStream1Type = static_cast<MinidumpStreamType>(0x4d);
|
||||
const uint8_t kStream1Value = 0xa5;
|
||||
TestStream stream1(kStream1Type, kStream1Size, kStream1Value);
|
||||
ASSERT_DEATH(minidump_file.AddStream(&stream1), "already present");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "minidump/minidump_stream_writer.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_memory_writer_test_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "util/file/string_file_writer.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -63,17 +64,11 @@ void GetMemoryListStream(const std::string& file_contents,
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeMemoryList,
|
||||
directory[directory_index].StreamType);
|
||||
ASSERT_GE(directory[directory_index].Location.DataSize,
|
||||
sizeof(MINIDUMP_MEMORY_LIST));
|
||||
ASSERT_EQ(kMemoryListStreamOffset, directory[directory_index].Location.Rva);
|
||||
EXPECT_EQ(kMemoryListStreamOffset, directory[directory_index].Location.Rva);
|
||||
|
||||
*memory_list = reinterpret_cast<const MINIDUMP_MEMORY_LIST*>(
|
||||
&file_contents[kMemoryListStreamOffset]);
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_MEMORY_LIST) +
|
||||
(*memory_list)->NumberOfMemoryRanges *
|
||||
sizeof(MINIDUMP_MEMORY_DESCRIPTOR),
|
||||
directory[directory_index].Location.DataSize);
|
||||
*memory_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
file_contents, directory[directory_index].Location);
|
||||
ASSERT_TRUE(memory_list);
|
||||
}
|
||||
|
||||
TEST(MinidumpMemoryWriter, EmptyMemoryList) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "util/file/string_file_writer.h"
|
||||
#include "util/stdlib/strlcpy.h"
|
||||
|
||||
@ -49,13 +50,11 @@ void GetMiscInfoStream(const std::string& file_contents, const T** misc_info) {
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeMiscInfo, directory[0].StreamType);
|
||||
ASSERT_EQ(kMiscInfoStreamSize, directory[0].Location.DataSize);
|
||||
ASSERT_EQ(kMiscInfoStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kMiscInfoStreamOffset, directory[0].Location.Rva);
|
||||
|
||||
*misc_info =
|
||||
reinterpret_cast<const T*>(&file_contents[kMiscInfoStreamOffset]);
|
||||
|
||||
ASSERT_EQ(kMiscInfoStreamSize, (*misc_info)->SizeOfInfo);
|
||||
*misc_info = MinidumpWritableAtLocationDescriptor<T>(file_contents,
|
||||
directory[0].Location);
|
||||
ASSERT_TRUE(misc_info);
|
||||
}
|
||||
|
||||
void ExpectNULPaddedString16Equal(const char16* expected,
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "minidump/minidump_file_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"
|
||||
#include "util/misc/uuid.h"
|
||||
|
||||
@ -48,15 +49,11 @@ void GetModuleListStream(const std::string& file_contents,
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeModuleList, directory[0].StreamType);
|
||||
ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_MODULE_LIST));
|
||||
ASSERT_EQ(kModuleListStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kModuleListStreamOffset, directory[0].Location.Rva);
|
||||
|
||||
*module_list = reinterpret_cast<const MINIDUMP_MODULE_LIST*>(
|
||||
&file_contents[kModuleListStreamOffset]);
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_MODULE_LIST) +
|
||||
(*module_list)->NumberOfModules * sizeof(MINIDUMP_MODULE),
|
||||
directory[0].Location.DataSize);
|
||||
*module_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_MODULE_LIST>(
|
||||
file_contents, directory[0].Location);
|
||||
ASSERT_TRUE(module_list);
|
||||
}
|
||||
|
||||
TEST(MinidumpModuleWriter, EmptyModuleList) {
|
||||
@ -92,19 +89,15 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
||||
uint32_t expected_pdb_age) {
|
||||
if (expected_pdb_name) {
|
||||
EXPECT_NE(0u, codeview_record->Rva);
|
||||
ASSERT_LE(codeview_record->Rva + codeview_record->DataSize,
|
||||
file_contents.size());
|
||||
|
||||
std::string observed_pdb_name;
|
||||
if (expected_pdb_uuid) {
|
||||
// The CodeView record should be a PDB 7.0 link.
|
||||
EXPECT_GE(codeview_record->DataSize,
|
||||
sizeof(MinidumpModuleCodeViewRecordPDB70));
|
||||
const MinidumpModuleCodeViewRecordPDB70* codeview_pdb70_record =
|
||||
reinterpret_cast<const MinidumpModuleCodeViewRecordPDB70*>(
|
||||
&file_contents[codeview_record->Rva]);
|
||||
EXPECT_EQ(MinidumpModuleCodeViewRecordPDB70::kSignature,
|
||||
codeview_pdb70_record->signature);
|
||||
MinidumpWritableAtLocationDescriptor<
|
||||
MinidumpModuleCodeViewRecordPDB70>(file_contents,
|
||||
*codeview_record);
|
||||
ASSERT_TRUE(codeview_pdb70_record);
|
||||
EXPECT_EQ(0,
|
||||
memcmp(expected_pdb_uuid,
|
||||
&codeview_pdb70_record->uuid,
|
||||
@ -117,13 +110,11 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
||||
offsetof(MinidumpModuleCodeViewRecordPDB70, pdb_name));
|
||||
} else {
|
||||
// The CodeView record should be a PDB 2.0 link.
|
||||
EXPECT_GE(codeview_record->DataSize,
|
||||
sizeof(MinidumpModuleCodeViewRecordPDB20));
|
||||
const MinidumpModuleCodeViewRecordPDB20* codeview_pdb20_record =
|
||||
reinterpret_cast<const MinidumpModuleCodeViewRecordPDB20*>(
|
||||
&file_contents[codeview_record->Rva]);
|
||||
EXPECT_EQ(MinidumpModuleCodeViewRecordPDB20::kSignature,
|
||||
codeview_pdb20_record->signature);
|
||||
MinidumpWritableAtLocationDescriptor<
|
||||
MinidumpModuleCodeViewRecordPDB20>(file_contents,
|
||||
*codeview_record);
|
||||
ASSERT_TRUE(codeview_pdb20_record);
|
||||
EXPECT_EQ(static_cast<uint32_t>(expected_pdb_timestamp),
|
||||
codeview_pdb20_record->timestamp);
|
||||
EXPECT_EQ(expected_pdb_age, codeview_pdb20_record->age);
|
||||
@ -157,14 +148,12 @@ void ExpectMiscellaneousDebugRecord(
|
||||
uint32_t expected_debug_type,
|
||||
bool expected_debug_utf16) {
|
||||
if (expected_debug_name) {
|
||||
EXPECT_GE(misc_record->DataSize, sizeof(IMAGE_DEBUG_MISC));
|
||||
EXPECT_NE(0u, misc_record->Rva);
|
||||
ASSERT_LE(misc_record->Rva + misc_record->DataSize, file_contents.size());
|
||||
const IMAGE_DEBUG_MISC* misc_debug_record =
|
||||
reinterpret_cast<const IMAGE_DEBUG_MISC*>(
|
||||
&file_contents[misc_record->Rva]);
|
||||
MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(file_contents,
|
||||
*misc_record);
|
||||
ASSERT_TRUE(misc_debug_record);
|
||||
EXPECT_EQ(expected_debug_type, misc_debug_record->DataType);
|
||||
EXPECT_EQ(misc_record->DataSize, misc_debug_record->Length);
|
||||
EXPECT_EQ(expected_debug_utf16, misc_debug_record->Unicode);
|
||||
EXPECT_EQ(0u, misc_debug_record->Reserved[0]);
|
||||
EXPECT_EQ(0u, misc_debug_record->Reserved[1]);
|
||||
|
@ -19,16 +19,23 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_extensions.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 MinidumpSimpleStringDictionary* MinidumpSimpleStringDictionaryCast(
|
||||
const StringFileWriter& file_writer) {
|
||||
return reinterpret_cast<const MinidumpSimpleStringDictionary*>(
|
||||
&file_writer.string()[0]);
|
||||
const MinidumpSimpleStringDictionary* MinidumpSimpleStringDictionaryAtStart(
|
||||
const std::string& file_contents,
|
||||
size_t count) {
|
||||
MINIDUMP_LOCATION_DESCRIPTOR location_descriptor;
|
||||
location_descriptor.DataSize =
|
||||
sizeof(MinidumpSimpleStringDictionary) +
|
||||
count * sizeof(MinidumpSimpleStringDictionaryEntry);
|
||||
location_descriptor.Rva = 0;
|
||||
return MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||
file_contents, location_descriptor);
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, EmptySimpleStringDictionary) {
|
||||
@ -41,7 +48,8 @@ TEST(MinidumpSimpleStringDictionaryWriter, EmptySimpleStringDictionary) {
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
MinidumpSimpleStringDictionaryAtStart(file_writer.string(), 0);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(0u, dictionary->count);
|
||||
}
|
||||
|
||||
@ -59,7 +67,8 @@ TEST(MinidumpSimpleStringDictionaryWriter, EmptyKeyValue) {
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
MinidumpSimpleStringDictionaryAtStart(file_writer.string(), 1);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
@ -89,7 +98,8 @@ TEST(MinidumpSimpleStringDictionaryWriter, OneKeyValue) {
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
MinidumpSimpleStringDictionaryAtStart(file_writer.string(), 1);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
@ -131,7 +141,8 @@ TEST(MinidumpSimpleStringDictionaryWriter, ThreeKeysValues) {
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
MinidumpSimpleStringDictionaryAtStart(file_writer.string(), 3);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(3u, dictionary->count);
|
||||
EXPECT_EQ(28u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(36u, dictionary->entries[0].value);
|
||||
@ -188,7 +199,8 @@ TEST(MinidumpSimpleStringDictionaryWriter, DuplicateKeyValue) {
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
MinidumpSimpleStringDictionaryAtStart(file_writer.string(), 1);
|
||||
ASSERT_TRUE(dictionary);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "minidump/minidump_file_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 {
|
||||
@ -56,17 +57,17 @@ void GetSystemInfoStream(const std::string& file_contents,
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeSystemInfo, directory[0].StreamType);
|
||||
ASSERT_EQ(sizeof(MINIDUMP_SYSTEM_INFO), directory[0].Location.DataSize);
|
||||
ASSERT_EQ(kSystemInfoStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kSystemInfoStreamOffset, directory[0].Location.Rva);
|
||||
|
||||
*system_info = reinterpret_cast<const MINIDUMP_SYSTEM_INFO*>(
|
||||
&file_contents[kSystemInfoStreamOffset]);
|
||||
*system_info = MinidumpWritableAtLocationDescriptor<MINIDUMP_SYSTEM_INFO>(
|
||||
file_contents, directory[0].Location);
|
||||
ASSERT_TRUE(system_info);
|
||||
|
||||
ASSERT_EQ(kCSDVersionOffset, (*system_info)->CSDVersionRva);
|
||||
EXPECT_EQ(kCSDVersionOffset, (*system_info)->CSDVersionRva);
|
||||
|
||||
*csd_version =
|
||||
MinidumpStringAtRVA(file_contents, (*system_info)->CSDVersionRva);
|
||||
ASSERT_EQ(kCSDVersionBytes, (*csd_version)->Length);
|
||||
EXPECT_EQ(kCSDVersionBytes, (*csd_version)->Length);
|
||||
}
|
||||
|
||||
TEST(MinidumpSystemInfoWriter, Empty) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "minidump/test/minidump_context_test_util.h"
|
||||
#include "minidump/test/minidump_memory_writer_test_util.h"
|
||||
#include "minidump/test/minidump_file_writer_test_util.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
#include "util/file/string_file_writer.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -51,19 +52,18 @@ void GetThreadListStream(const std::string& file_contents,
|
||||
ASSERT_TRUE(directory);
|
||||
|
||||
ASSERT_EQ(kMinidumpStreamTypeThreadList, directory[0].StreamType);
|
||||
ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_THREAD_LIST));
|
||||
ASSERT_EQ(kThreadListStreamOffset, directory[0].Location.Rva);
|
||||
EXPECT_EQ(kThreadListStreamOffset, directory[0].Location.Rva);
|
||||
|
||||
*thread_list = reinterpret_cast<const MINIDUMP_THREAD_LIST*>(
|
||||
&file_contents[kThreadListStreamOffset]);
|
||||
|
||||
ASSERT_EQ(sizeof(MINIDUMP_THREAD_LIST) +
|
||||
(*thread_list)->NumberOfThreads * sizeof(MINIDUMP_THREAD),
|
||||
directory[0].Location.DataSize);
|
||||
*thread_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_THREAD_LIST>(
|
||||
file_contents, directory[0].Location);
|
||||
ASSERT_TRUE(thread_list);
|
||||
|
||||
if (memory_list) {
|
||||
*memory_list = reinterpret_cast<const MINIDUMP_MEMORY_LIST*>(
|
||||
&file_contents[directory[1].Location.Rva]);
|
||||
ASSERT_EQ(kMinidumpStreamTypeMemoryList, directory[1].StreamType);
|
||||
|
||||
*memory_list = MinidumpWritableAtLocationDescriptor<MINIDUMP_MEMORY_LIST>(
|
||||
file_contents, directory[1].Location);
|
||||
ASSERT_TRUE(*memory_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,15 +32,6 @@ const MINIDUMP_HEADER* MinidumpHeaderAtStart(
|
||||
file_contents, location_descriptor);
|
||||
|
||||
if (header) {
|
||||
if (header->Signature != MINIDUMP_SIGNATURE) {
|
||||
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature);
|
||||
return nullptr;
|
||||
}
|
||||
if (header->Version != MINIDUMP_VERSION) {
|
||||
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
location_descriptor.DataSize =
|
||||
header->NumberOfStreams * sizeof(MINIDUMP_DIRECTORY);
|
||||
location_descriptor.Rva = header->StreamDirectoryRva;
|
||||
@ -57,8 +48,6 @@ void VerifyMinidumpHeader(const MINIDUMP_HEADER* header,
|
||||
uint32_t streams,
|
||||
uint32_t timestamp) {
|
||||
ASSERT_TRUE(header);
|
||||
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature);
|
||||
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version);
|
||||
ASSERT_EQ(streams, header->NumberOfStreams);
|
||||
ASSERT_EQ(streams ? sizeof(MINIDUMP_HEADER) : 0u, header->StreamDirectoryRva);
|
||||
EXPECT_EQ(0u, header->CheckSum);
|
||||
|
@ -45,13 +45,15 @@ const MINIDUMP_HEADER* MinidumpHeaderAtStart(
|
||||
//! \brief Verifies, via gtest assertions, that a MINIDUMP_HEADER contains
|
||||
//! expected values.
|
||||
//!
|
||||
//! All fields in the MINIDUMP_HEADER will be evaluated. Most are compared to
|
||||
//! their correct default values. MINIDUMP_HEADER::NumberOfStreams is compared
|
||||
//! to \a streams, and MINIDUMP_HEADER::TimeDateStamp is compared to \a
|
||||
//! timestamp. Most fields are checked with nonfatal EXPECT-style assertions,
|
||||
//! but MINIDUMP_HEADER::NumberOfStreams and MINIDUMP_HEADER::StreamDirectoryRva
|
||||
//! are checked with fatal ASSERT-style assertions, because they must be
|
||||
//! correct in order for processing of the minidump to continue.
|
||||
//! All fields in the MINIDUMP_HEADER will be evaluated except for the Signature
|
||||
//! and Version fields, because those are checked by MinidumpHeaderAtStart().
|
||||
//! Most other fields are are compared to their correct default values.
|
||||
//! MINIDUMP_HEADER::NumberOfStreams is compared to \a streams, and
|
||||
//! MINIDUMP_HEADER::TimeDateStamp is compared to \a timestamp. Most fields are
|
||||
//! checked with nonfatal EXPECT-style assertions, but
|
||||
//! MINIDUMP_HEADER::NumberOfStreams and MINIDUMP_HEADER::StreamDirectoryRva are
|
||||
//! checked with fatal ASSERT-style assertions, because they must be correct in
|
||||
//! order for processing of the minidump to continue.
|
||||
void VerifyMinidumpHeader(const MINIDUMP_HEADER* header,
|
||||
uint32_t streams,
|
||||
uint32_t timestamp);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -34,12 +35,20 @@ const void* MinidumpWritableAtRVAInternal(const std::string& file_contents,
|
||||
const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location,
|
||||
size_t expected_minimum_size) {
|
||||
size_t expected_size,
|
||||
bool allow_oversized_data) {
|
||||
if (location.DataSize == 0) {
|
||||
EXPECT_EQ(0u, location.Rva);
|
||||
return nullptr;
|
||||
} else if (location.DataSize < expected_minimum_size) {
|
||||
EXPECT_GE(location.DataSize, expected_minimum_size);
|
||||
}
|
||||
|
||||
if (allow_oversized_data) {
|
||||
if (location.DataSize < expected_size) {
|
||||
EXPECT_GE(location.DataSize, expected_size);
|
||||
return nullptr;
|
||||
}
|
||||
} else if (location.DataSize != expected_size) {
|
||||
EXPECT_EQ(expected_size, location.DataSize);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -54,5 +63,213 @@ const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
return rv;
|
||||
}
|
||||
|
||||
template <>
|
||||
const IMAGE_DEBUG_MISC* MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
const IMAGE_DEBUG_MISC* misc =
|
||||
TMinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(file_contents,
|
||||
location);
|
||||
if (!misc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (misc->DataType != IMAGE_DEBUG_MISC_EXENAME) {
|
||||
EXPECT_EQ(static_cast<uint32_t>(IMAGE_DEBUG_MISC_EXENAME), misc->DataType);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (misc->Length != location.DataSize) {
|
||||
EXPECT_EQ(location.DataSize, misc->Length);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (misc->Unicode == 0) {
|
||||
size_t string_length = misc->Length - offsetof(IMAGE_DEBUG_MISC, Data) - 1;
|
||||
if (misc->Data[string_length] != '\0') {
|
||||
EXPECT_EQ('\0', misc->Data[string_length]);
|
||||
return nullptr;
|
||||
}
|
||||
} else if (misc->Unicode == 1) {
|
||||
if (misc->Length % sizeof(char16) != 0) {
|
||||
EXPECT_EQ(0u, misc->Length % sizeof(char16));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t string_length =
|
||||
(misc->Length - offsetof(IMAGE_DEBUG_MISC, Data)) / sizeof(char16) - 1;
|
||||
const char16* data16 = reinterpret_cast<const char16*>(misc->Data);
|
||||
if (data16[string_length] != '\0') {
|
||||
EXPECT_EQ('\0', data16[string_length]);
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
ADD_FAILURE() << "misc->Unicode " << misc->Unicode;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return misc;
|
||||
}
|
||||
|
||||
template <>
|
||||
const MINIDUMP_HEADER* MinidumpWritableAtLocationDescriptor<MINIDUMP_HEADER>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
const MINIDUMP_HEADER* header =
|
||||
TMinidumpWritableAtLocationDescriptor<MINIDUMP_HEADER>(file_contents,
|
||||
location);
|
||||
if (!header) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (header->Signature != MINIDUMP_SIGNATURE) {
|
||||
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature);
|
||||
return nullptr;
|
||||
}
|
||||
if (header->Version != MINIDUMP_VERSION) {
|
||||
EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct MinidumpMemoryListTraits {
|
||||
typedef MINIDUMP_MEMORY_LIST ListType;
|
||||
static constexpr size_t kElementSize = sizeof(MINIDUMP_MEMORY_DESCRIPTOR);
|
||||
static size_t ElementCount(const ListType* list) {
|
||||
return list->NumberOfMemoryRanges;
|
||||
}
|
||||
};
|
||||
|
||||
struct MinidumpModuleListTraits {
|
||||
typedef MINIDUMP_MODULE_LIST ListType;
|
||||
static constexpr size_t kElementSize = sizeof(MINIDUMP_MODULE);
|
||||
static size_t ElementCount(const ListType* list) {
|
||||
return list->NumberOfModules;
|
||||
}
|
||||
};
|
||||
|
||||
struct MinidumpThreadListTraits {
|
||||
typedef MINIDUMP_THREAD_LIST ListType;
|
||||
static constexpr size_t kElementSize = sizeof(MINIDUMP_THREAD);
|
||||
static size_t ElementCount(const ListType* list) {
|
||||
return list->NumberOfThreads;
|
||||
}
|
||||
};
|
||||
|
||||
struct MinidumpSimpleStringDictionaryListTraits {
|
||||
typedef MinidumpSimpleStringDictionary ListType;
|
||||
static constexpr size_t kElementSize =
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry);
|
||||
static size_t ElementCount(const ListType* list) {
|
||||
return list->count;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const typename T::ListType* MinidumpListAtLocationDescriptor(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
const typename T::ListType* list =
|
||||
TMinidumpWritableAtLocationDescriptor<typename T::ListType>(file_contents,
|
||||
location);
|
||||
if (!list) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t expected_size =
|
||||
sizeof(typename T::ListType) + T::ElementCount(list) * T::kElementSize;
|
||||
if (location.DataSize != expected_size) {
|
||||
EXPECT_EQ(expected_size, location.DataSize);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
const MINIDUMP_MEMORY_LIST* MinidumpWritableAtLocationDescriptor<
|
||||
MINIDUMP_MEMORY_LIST>(const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return MinidumpListAtLocationDescriptor<MinidumpMemoryListTraits>(
|
||||
file_contents, location);
|
||||
}
|
||||
|
||||
template <>
|
||||
const MINIDUMP_MODULE_LIST* MinidumpWritableAtLocationDescriptor<
|
||||
MINIDUMP_MODULE_LIST>(const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return MinidumpListAtLocationDescriptor<MinidumpModuleListTraits>(
|
||||
file_contents, location);
|
||||
}
|
||||
|
||||
template <>
|
||||
const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor<
|
||||
MINIDUMP_THREAD_LIST>(const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return MinidumpListAtLocationDescriptor<MinidumpThreadListTraits>(
|
||||
file_contents, location);
|
||||
}
|
||||
|
||||
template <>
|
||||
const MinidumpSimpleStringDictionary*
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return MinidumpListAtLocationDescriptor<
|
||||
MinidumpSimpleStringDictionaryListTraits>(file_contents, location);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
const T* MinidumpCVPDBAtLocationDescriptor(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
const T* cv_pdb =
|
||||
TMinidumpWritableAtLocationDescriptor<T>(file_contents, location);
|
||||
if (!cv_pdb) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cv_pdb->signature != T::kSignature) {
|
||||
EXPECT_EQ(T::kSignature, cv_pdb->signature);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t string_length = location.DataSize - offsetof(T, pdb_name) - 1;
|
||||
if (cv_pdb->pdb_name[string_length] != '\0') {
|
||||
EXPECT_EQ('\0', cv_pdb->pdb_name[string_length]);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return cv_pdb;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
const MinidumpModuleCodeViewRecordPDB20*
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return MinidumpCVPDBAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
||||
file_contents, location);
|
||||
}
|
||||
|
||||
template <>
|
||||
const MinidumpModuleCodeViewRecordPDB70*
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return MinidumpCVPDBAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>(
|
||||
file_contents, location);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
@ -16,10 +16,12 @@
|
||||
#define CRASHPAD_MINIDUMP_TEST_MINIDUMP_WRITABLE_TEST_UTIL_H_
|
||||
|
||||
#include <dbghelp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_extensions.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
@ -47,12 +49,18 @@ const void* MinidumpWritableAtRVAInternal(const std::string& file_contents,
|
||||
//! \param[in] file_contents The contents of the minidump file.
|
||||
//! \param[in] location A MINIDUMP_LOCATION_DESCRIPTOR giving the offset within
|
||||
//! the minidump file of the desired object, as well as its size.
|
||||
//! \param[in] expected_minimum_size The minimum size allowable for the object.
|
||||
//! \param[in] expected_size The expected size of the object. If \a
|
||||
//! allow_oversized_data is `true`, \a expected_size is treated as the
|
||||
//! minimum size of \a location, but it is permitted to be larger. If \a
|
||||
//! allow_oversized_data is `false`, the size of \a location must match
|
||||
//! \a expected_size exactly.
|
||||
//! \param[in] allow_oversized_data Controls whether \a expected_size is a
|
||||
//! minimum limit (`true`) or an exact match is required (`false`).
|
||||
//!
|
||||
//! \return If the size of \a location is at least as big as \a
|
||||
//! expected_minimum_size, and if \a location is within the range of \a
|
||||
//! file_contents, returns a pointer into \a file_contents at offset \a rva.
|
||||
//! Otherwise, raises a gtest assertion failure and returns `nullptr`.
|
||||
//! \return If the size of \a location is agrees with \a expected_size, and if
|
||||
//! \a location is within the range of \a file_contents, returns a pointer
|
||||
//! into \a file_contents at offset \a rva. Otherwise, raises a gtest
|
||||
//! assertion failure and returns `nullptr`.
|
||||
//!
|
||||
//! Do not call this function. Use the typed version,
|
||||
//! MinidumpWritableAtLocationDescriptor<>(), or another type-specific function.
|
||||
@ -61,7 +69,54 @@ const void* MinidumpWritableAtRVAInternal(const std::string& file_contents,
|
||||
const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location,
|
||||
size_t expected_minimum_size);
|
||||
size_t expected_size,
|
||||
bool allow_oversized_data);
|
||||
|
||||
//! \brief A traits class defining whether a minidump object type is required to
|
||||
//! appear only as a fixed-size object or if it is variable-sized.
|
||||
//!
|
||||
//! Variable-sized data is data referenced by a MINIDUMP_LOCATION_DESCRIPTOR
|
||||
//! whose DataSize field may be larger than the size of the basic object type’s
|
||||
//! structure. This can happen for types that appear only as variable-sized
|
||||
//! lists, or types whose final fields are variable-sized lists or other
|
||||
//! variable-sized data.
|
||||
template <typename T>
|
||||
struct MinidumpWritableTraits {
|
||||
//! \brief `true` if \a T should be treated as a variable-sized data type,
|
||||
//! where its base size is used solely as a minimum bound. `false` if \a
|
||||
//! T is a fixed-sized type, which should only appear at its base size.
|
||||
static const bool kAllowOversizedData = false;
|
||||
};
|
||||
|
||||
#define MINIDUMP_ALLOW_OVERSIZED_DATA(x) \
|
||||
template <> \
|
||||
struct MinidumpWritableTraits<x> { \
|
||||
static const bool kAllowOversizedData = true; \
|
||||
}
|
||||
|
||||
// This type appears only as a variable-sized list.
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_DIRECTORY);
|
||||
|
||||
// These types are permitted to be oversized because their final fields are
|
||||
// variable-sized lists.
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MEMORY_LIST);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MODULE_LIST);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_THREAD_LIST);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary);
|
||||
|
||||
// These types have final fields carrying variable-sized data (typically string
|
||||
// data).
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(IMAGE_DEBUG_MISC);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_STRING);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCodeViewRecordPDB20);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCodeViewRecordPDB70);
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpUTF8String);
|
||||
|
||||
// minidump_file_writer_test accesses its variable-sized test streams via a
|
||||
// uint8_t*.
|
||||
MINIDUMP_ALLOW_OVERSIZED_DATA(uint8_t);
|
||||
|
||||
#undef MINIDUMP_ALLOW_OVERSIZED_DATA
|
||||
|
||||
//! \brief Returns a typed minidump object located within a minidump file’s
|
||||
//! contents, where the offset of the object is known.
|
||||
@ -83,6 +138,42 @@ const T* MinidumpWritableAtRVA(const std::string& file_contents, RVA rva) {
|
||||
//! \brief Returns a typed minidump object located within a minidump file’s
|
||||
//! contents, where the offset and size of the object are known.
|
||||
//!
|
||||
//! This function is similar to MinidumpWritableAtLocationDescriptor<>() and is
|
||||
//! used to implement that function. It exists independently so that template
|
||||
//! specializations are able to call this function, which provides the default
|
||||
//! implementation.
|
||||
//!
|
||||
//! Do not call this function directly. Use
|
||||
//! MinidumpWritableAtLocationDescriptor<>() instead.
|
||||
template <typename T>
|
||||
const T* TMinidumpWritableAtLocationDescriptor(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return reinterpret_cast<const T*>(
|
||||
MinidumpWritableAtLocationDescriptorInternal(
|
||||
file_contents,
|
||||
location,
|
||||
sizeof(T),
|
||||
MinidumpWritableTraits<T>::kAllowOversizedData));
|
||||
}
|
||||
|
||||
//! \brief Returns a typed minidump object located within a minidump file’s
|
||||
//! contents, where the offset and size of the object are known.
|
||||
//!
|
||||
//! This function has template specializations that perform more stringent
|
||||
//! checking than the default implementation:
|
||||
//! - 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,
|
||||
//! 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.
|
||||
//! - With an IMAGE_DEBUG_MISC, MinidumpModuleCodeViewRecordPDB20, or
|
||||
//! MinidumpModuleCodeViewRecordPDB70 template parameter, template
|
||||
//! specializations ensure that the structure has the expected format
|
||||
//! including any magic number and the `NUL`-terminated string.
|
||||
//!
|
||||
//! \param[in] file_contents The contents of the minidump file.
|
||||
//! \param[in] location A MINIDUMP_LOCATION_DESCRIPTOR giving the offset within
|
||||
//! the minidump file of the desired object, as well as its size.
|
||||
@ -97,11 +188,52 @@ template <typename T>
|
||||
const T* MinidumpWritableAtLocationDescriptor(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||
return reinterpret_cast<const T*>(
|
||||
MinidumpWritableAtLocationDescriptorInternal(
|
||||
file_contents, location, sizeof(T)));
|
||||
return TMinidumpWritableAtLocationDescriptor<T>(file_contents, location);
|
||||
}
|
||||
|
||||
template <>
|
||||
const IMAGE_DEBUG_MISC* MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
template <>
|
||||
const MINIDUMP_HEADER* MinidumpWritableAtLocationDescriptor<MINIDUMP_HEADER>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
template <>
|
||||
const MINIDUMP_MEMORY_LIST* MinidumpWritableAtLocationDescriptor<
|
||||
MINIDUMP_MEMORY_LIST>(const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
template <>
|
||||
const MINIDUMP_MODULE_LIST* MinidumpWritableAtLocationDescriptor<
|
||||
MINIDUMP_MODULE_LIST>(const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
template <>
|
||||
const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor<
|
||||
MINIDUMP_THREAD_LIST>(const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
template <>
|
||||
const MinidumpModuleCodeViewRecordPDB20*
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
template <>
|
||||
const MinidumpModuleCodeViewRecordPDB70*
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
template <>
|
||||
const MinidumpSimpleStringDictionary*
|
||||
MinidumpWritableAtLocationDescriptor<MinidumpSimpleStringDictionary>(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user