mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 22:26:06 +00:00
[minidump] Extend minidump string writer support for RVA64 strings
To support MINIDUMP_THREAD_NAME_LIST (which uses 64-bit RVAs for the thread name MINIDUMP_STRING), this adds minidump string writing and reading support for the new 64-bit RVA64 and MINIDUMP_LOCATION_DESCRIPTOR64 types. Bug: crashpad:327 Change-Id: Iffefffef358517dfc6deac02051dff9dbb8eb214 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3673779 Reviewed-by: Joshua Peraza <jperaza@chromium.org> Commit-Queue: Ben Hamilton <benhamilton@google.com>
This commit is contained in:
parent
fc0b157a8e
commit
91cec09d93
@ -16,6 +16,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/notreached.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_context.h"
|
||||
#include "minidump/test/minidump_context_test_util.h"
|
||||
@ -28,7 +32,7 @@ namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
template <typename Writer, typename Context>
|
||||
template <typename Writer, typename Context, typename RVAType>
|
||||
void EmptyContextTest(void (*expect_context)(uint32_t, const Context*, bool)) {
|
||||
Writer context_writer;
|
||||
StringFile string_file;
|
||||
@ -36,13 +40,34 @@ void EmptyContextTest(void (*expect_context)(uint32_t, const Context*, bool)) {
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(Context));
|
||||
|
||||
const Context* observed =
|
||||
MinidumpWritableAtRVA<Context>(string_file.string(), 0);
|
||||
MinidumpWritableAtRVA<Context>(string_file.string(), RVAType(0));
|
||||
ASSERT_TRUE(observed);
|
||||
|
||||
expect_context(0, observed, false);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
class TestTypeNames {
|
||||
public:
|
||||
template <typename T>
|
||||
static std::string GetName(int) {
|
||||
if (std::is_same<T, RVA>()) {
|
||||
return "RVA";
|
||||
}
|
||||
if (std::is_same<T, RVA64>()) {
|
||||
return "RVA64";
|
||||
}
|
||||
NOTREACHED();
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RVAType>
|
||||
class MinidumpContextWriter : public ::testing::Test {};
|
||||
|
||||
using RVATypes = ::testing::Types<RVA, RVA64>;
|
||||
TYPED_TEST_SUITE(MinidumpContextWriter, RVATypes, TestTypeNames);
|
||||
|
||||
TYPED_TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
StringFile string_file;
|
||||
|
||||
{
|
||||
@ -50,7 +75,7 @@ TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
// context.
|
||||
SCOPED_TRACE("zero");
|
||||
|
||||
EmptyContextTest<MinidumpContextX86Writer, MinidumpContextX86>(
|
||||
EmptyContextTest<MinidumpContextX86Writer, MinidumpContextX86, TypeParam>(
|
||||
ExpectMinidumpContextX86);
|
||||
}
|
||||
|
||||
@ -67,14 +92,15 @@ TEST(MinidumpContextWriter, MinidumpContextX86Writer) {
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(MinidumpContextX86));
|
||||
|
||||
const MinidumpContextX86* observed =
|
||||
MinidumpWritableAtRVA<MinidumpContextX86>(string_file.string(), 0);
|
||||
MinidumpWritableAtRVA<MinidumpContextX86>(string_file.string(),
|
||||
TypeParam(0));
|
||||
ASSERT_TRUE(observed);
|
||||
|
||||
ExpectMinidumpContextX86(kSeed, observed, false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
TYPED_TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
{
|
||||
// Make sure that a heap-allocated context writer has the proper alignment,
|
||||
// because it may be nonstandard.
|
||||
@ -91,8 +117,9 @@ TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
// context.
|
||||
SCOPED_TRACE("zero");
|
||||
|
||||
EmptyContextTest<MinidumpContextAMD64Writer, MinidumpContextAMD64>(
|
||||
ExpectMinidumpContextAMD64);
|
||||
EmptyContextTest<MinidumpContextAMD64Writer,
|
||||
MinidumpContextAMD64,
|
||||
TypeParam>(ExpectMinidumpContextAMD64);
|
||||
}
|
||||
|
||||
{
|
||||
@ -108,52 +135,53 @@ TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) {
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(MinidumpContextAMD64));
|
||||
|
||||
const MinidumpContextAMD64* observed =
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(string_file.string(), 0);
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(string_file.string(),
|
||||
TypeParam(0));
|
||||
ASSERT_TRUE(observed);
|
||||
|
||||
ExpectMinidumpContextAMD64(kSeed, observed, false);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Writer, typename Context>
|
||||
template <typename Writer, typename Context, typename RVAType>
|
||||
void FromSnapshotTest(const CPUContext& snapshot_context,
|
||||
void (*expect_context)(uint32_t, const Context*, bool),
|
||||
uint32_t seed) {
|
||||
std::unique_ptr<MinidumpContextWriter> context_writer =
|
||||
MinidumpContextWriter::CreateFromSnapshot(&snapshot_context);
|
||||
std::unique_ptr<::crashpad::MinidumpContextWriter> context_writer =
|
||||
::crashpad::MinidumpContextWriter::CreateFromSnapshot(&snapshot_context);
|
||||
ASSERT_TRUE(context_writer);
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(context_writer->WriteEverything(&string_file));
|
||||
|
||||
const Context* observed =
|
||||
MinidumpWritableAtRVA<Context>(string_file.string(), 0);
|
||||
MinidumpWritableAtRVA<Context>(string_file.string(), RVAType(0));
|
||||
ASSERT_TRUE(observed);
|
||||
|
||||
expect_context(seed, observed, true);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, X86_FromSnapshot) {
|
||||
TYPED_TEST(MinidumpContextWriter, X86_FromSnapshot) {
|
||||
constexpr uint32_t kSeed = 32;
|
||||
CPUContextX86 context_x86;
|
||||
CPUContext context;
|
||||
context.x86 = &context_x86;
|
||||
InitializeCPUContextX86(&context, kSeed);
|
||||
FromSnapshotTest<MinidumpContextX86Writer, MinidumpContextX86>(
|
||||
FromSnapshotTest<MinidumpContextX86Writer, MinidumpContextX86, TypeParam>(
|
||||
context, ExpectMinidumpContextX86, kSeed);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, AMD64_FromSnapshot) {
|
||||
TYPED_TEST(MinidumpContextWriter, AMD64_FromSnapshot) {
|
||||
constexpr uint32_t kSeed = 64;
|
||||
CPUContextX86_64 context_x86_64;
|
||||
CPUContext context;
|
||||
context.x86_64 = &context_x86_64;
|
||||
InitializeCPUContextX86_64(&context, kSeed);
|
||||
FromSnapshotTest<MinidumpContextAMD64Writer, MinidumpContextAMD64>(
|
||||
FromSnapshotTest<MinidumpContextAMD64Writer, MinidumpContextAMD64, TypeParam>(
|
||||
context, ExpectMinidumpContextAMD64, kSeed);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, AMD64_CetFromSnapshot) {
|
||||
TYPED_TEST(MinidumpContextWriter, AMD64_CetFromSnapshot) {
|
||||
constexpr uint32_t kSeed = 77;
|
||||
CPUContextX86_64 context_x86_64;
|
||||
CPUContext context;
|
||||
@ -163,78 +191,81 @@ TEST(MinidumpContextWriter, AMD64_CetFromSnapshot) {
|
||||
context_x86_64.xstate.cet_u.cetmsr = 1;
|
||||
context_x86_64.xstate.cet_u.ssp = kSeed * kSeed;
|
||||
// We cannot use FromSnapshotTest as we write more than the fixed context.
|
||||
std::unique_ptr<MinidumpContextWriter> context_writer =
|
||||
MinidumpContextWriter::CreateFromSnapshot(&context);
|
||||
std::unique_ptr<::crashpad::MinidumpContextWriter> context_writer =
|
||||
::crashpad::MinidumpContextWriter::CreateFromSnapshot(&context);
|
||||
ASSERT_TRUE(context_writer);
|
||||
|
||||
StringFile string_file;
|
||||
ASSERT_TRUE(context_writer->WriteEverything(&string_file));
|
||||
|
||||
const MinidumpContextAMD64* observed =
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(string_file.string(), 0);
|
||||
MinidumpWritableAtRVA<MinidumpContextAMD64>(string_file.string(),
|
||||
TypeParam(0));
|
||||
ASSERT_TRUE(observed);
|
||||
|
||||
ExpectMinidumpContextAMD64(kSeed, observed, true);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, ARM_Zeros) {
|
||||
EmptyContextTest<MinidumpContextARMWriter, MinidumpContextARM>(
|
||||
TYPED_TEST(MinidumpContextWriter, ARM_Zeros) {
|
||||
EmptyContextTest<MinidumpContextARMWriter, MinidumpContextARM, TypeParam>(
|
||||
ExpectMinidumpContextARM);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWRiter, ARM64_Zeros) {
|
||||
EmptyContextTest<MinidumpContextARM64Writer, MinidumpContextARM64>(
|
||||
TYPED_TEST(MinidumpContextWriter, ARM64_Zeros) {
|
||||
EmptyContextTest<MinidumpContextARM64Writer, MinidumpContextARM64, TypeParam>(
|
||||
ExpectMinidumpContextARM64);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, ARM_FromSnapshot) {
|
||||
TYPED_TEST(MinidumpContextWriter, ARM_FromSnapshot) {
|
||||
constexpr uint32_t kSeed = 32;
|
||||
CPUContextARM context_arm;
|
||||
CPUContext context;
|
||||
context.arm = &context_arm;
|
||||
InitializeCPUContextARM(&context, kSeed);
|
||||
FromSnapshotTest<MinidumpContextARMWriter, MinidumpContextARM>(
|
||||
FromSnapshotTest<MinidumpContextARMWriter, MinidumpContextARM, TypeParam>(
|
||||
context, ExpectMinidumpContextARM, kSeed);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, ARM64_FromSnapshot) {
|
||||
TYPED_TEST(MinidumpContextWriter, ARM64_FromSnapshot) {
|
||||
constexpr uint32_t kSeed = 64;
|
||||
CPUContextARM64 context_arm64;
|
||||
CPUContext context;
|
||||
context.arm64 = &context_arm64;
|
||||
InitializeCPUContextARM64(&context, kSeed);
|
||||
FromSnapshotTest<MinidumpContextARM64Writer, MinidumpContextARM64>(
|
||||
FromSnapshotTest<MinidumpContextARM64Writer, MinidumpContextARM64, TypeParam>(
|
||||
context, ExpectMinidumpContextARM64, kSeed);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, MIPS_Zeros) {
|
||||
EmptyContextTest<MinidumpContextMIPSWriter, MinidumpContextMIPS>(
|
||||
TYPED_TEST(MinidumpContextWriter, MIPS_Zeros) {
|
||||
EmptyContextTest<MinidumpContextMIPSWriter, MinidumpContextMIPS, TypeParam>(
|
||||
ExpectMinidumpContextMIPS);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, MIPS64_Zeros) {
|
||||
EmptyContextTest<MinidumpContextMIPS64Writer, MinidumpContextMIPS64>(
|
||||
ExpectMinidumpContextMIPS64);
|
||||
TYPED_TEST(MinidumpContextWriter, MIPS64_Zeros) {
|
||||
EmptyContextTest<MinidumpContextMIPS64Writer,
|
||||
MinidumpContextMIPS64,
|
||||
TypeParam>(ExpectMinidumpContextMIPS64);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, MIPS_FromSnapshot) {
|
||||
TYPED_TEST(MinidumpContextWriter, MIPS_FromSnapshot) {
|
||||
constexpr uint32_t kSeed = 32;
|
||||
CPUContextMIPS context_mips;
|
||||
CPUContext context;
|
||||
context.mipsel = &context_mips;
|
||||
InitializeCPUContextMIPS(&context, kSeed);
|
||||
FromSnapshotTest<MinidumpContextMIPSWriter, MinidumpContextMIPS>(
|
||||
FromSnapshotTest<MinidumpContextMIPSWriter, MinidumpContextMIPS, TypeParam>(
|
||||
context, ExpectMinidumpContextMIPS, kSeed);
|
||||
}
|
||||
|
||||
TEST(MinidumpContextWriter, MIPS64_FromSnapshot) {
|
||||
TYPED_TEST(MinidumpContextWriter, MIPS64_FromSnapshot) {
|
||||
constexpr uint32_t kSeed = 64;
|
||||
CPUContextMIPS64 context_mips;
|
||||
CPUContext context;
|
||||
context.mips64 = &context_mips;
|
||||
InitializeCPUContextMIPS64(&context, kSeed);
|
||||
FromSnapshotTest<MinidumpContextMIPS64Writer, MinidumpContextMIPS64>(
|
||||
context, ExpectMinidumpContextMIPS64, kSeed);
|
||||
FromSnapshotTest<MinidumpContextMIPS64Writer,
|
||||
MinidumpContextMIPS64,
|
||||
TypeParam>(context, ExpectMinidumpContextMIPS64, kSeed);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/format_macros.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "gtest/gtest.h"
|
||||
@ -30,7 +32,28 @@ namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
|
||||
class TestTypeNames {
|
||||
public:
|
||||
template <typename T>
|
||||
static std::string GetName(int) {
|
||||
if (std::is_same<T, RVA>()) {
|
||||
return "RVA";
|
||||
}
|
||||
if (std::is_same<T, RVA64>()) {
|
||||
return "RVA64";
|
||||
}
|
||||
NOTREACHED();
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RVAType>
|
||||
class MinidumpStringWriter : public ::testing::Test {};
|
||||
|
||||
using RVATypes = ::testing::Types<RVA, RVA64>;
|
||||
TYPED_TEST_SUITE(MinidumpStringWriter, RVATypes, TestTypeNames);
|
||||
|
||||
TYPED_TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
|
||||
StringFile string_file;
|
||||
|
||||
{
|
||||
@ -41,9 +64,9 @@ TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
|
||||
ASSERT_EQ(string_file.string().size(), 6u);
|
||||
|
||||
const MINIDUMP_STRING* minidump_string =
|
||||
MinidumpStringAtRVA(string_file.string(), 0);
|
||||
MinidumpStringAtRVA(string_file.string(), TypeParam(0));
|
||||
EXPECT_TRUE(minidump_string);
|
||||
EXPECT_EQ(MinidumpStringAtRVAAsString(string_file.string(), 0),
|
||||
EXPECT_EQ(MinidumpStringAtRVAAsString(string_file.string(), TypeParam(0)),
|
||||
std::u16string());
|
||||
}
|
||||
|
||||
@ -90,16 +113,16 @@ TEST(MinidumpStringWriter, MinidumpUTF16StringWriter) {
|
||||
ASSERT_EQ(string_file.string().size(), sizeof(*tmp) + expected_utf16_bytes);
|
||||
|
||||
const MINIDUMP_STRING* minidump_string =
|
||||
MinidumpStringAtRVA(string_file.string(), 0);
|
||||
MinidumpStringAtRVA(string_file.string(), TypeParam(0));
|
||||
EXPECT_TRUE(minidump_string);
|
||||
std::u16string expect_string = std::u16string(
|
||||
kTestData[index].output_string, kTestData[index].output_length);
|
||||
EXPECT_EQ(MinidumpStringAtRVAAsString(string_file.string(), 0),
|
||||
EXPECT_EQ(MinidumpStringAtRVAAsString(string_file.string(), TypeParam(0)),
|
||||
expect_string);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MinidumpStringWriter, ConvertInvalidUTF8ToUTF16) {
|
||||
TYPED_TEST(MinidumpStringWriter, ConvertInvalidUTF8ToUTF16) {
|
||||
StringFile string_file;
|
||||
|
||||
static constexpr const char* kTestData[] = {
|
||||
@ -125,20 +148,20 @@ TEST(MinidumpStringWriter, ConvertInvalidUTF8ToUTF16) {
|
||||
// data written, and make sure that at least one U+FFFD replacement
|
||||
// character was written.
|
||||
const MINIDUMP_STRING* minidump_string =
|
||||
MinidumpStringAtRVA(string_file.string(), 0);
|
||||
MinidumpStringAtRVA(string_file.string(), TypeParam(0));
|
||||
EXPECT_TRUE(minidump_string);
|
||||
[[maybe_unused]] MINIDUMP_STRING* tmp;
|
||||
EXPECT_EQ(
|
||||
minidump_string->Length,
|
||||
string_file.string().size() - sizeof(*tmp) - sizeof(tmp->Buffer[0]));
|
||||
std::u16string output_string =
|
||||
MinidumpStringAtRVAAsString(string_file.string(), 0);
|
||||
MinidumpStringAtRVAAsString(string_file.string(), TypeParam(0));
|
||||
EXPECT_FALSE(output_string.empty());
|
||||
EXPECT_NE(output_string.find(0xfffd), std::u16string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
||||
TYPED_TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
||||
StringFile string_file;
|
||||
|
||||
{
|
||||
@ -149,10 +172,11 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
||||
ASSERT_EQ(string_file.string().size(), 5u);
|
||||
|
||||
const MinidumpUTF8String* minidump_string =
|
||||
MinidumpUTF8StringAtRVA(string_file.string(), 0);
|
||||
MinidumpUTF8StringAtRVA(string_file.string(), TypeParam(0));
|
||||
EXPECT_TRUE(minidump_string);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(), 0),
|
||||
std::string());
|
||||
EXPECT_EQ(
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(), TypeParam(0)),
|
||||
std::string());
|
||||
}
|
||||
|
||||
static constexpr struct {
|
||||
@ -188,10 +212,11 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
||||
sizeof(MinidumpUTF8String) + expected_utf8_bytes_with_nul);
|
||||
|
||||
const MinidumpUTF8String* minidump_string =
|
||||
MinidumpUTF8StringAtRVA(string_file.string(), 0);
|
||||
MinidumpUTF8StringAtRVA(string_file.string(), TypeParam(0));
|
||||
EXPECT_TRUE(minidump_string);
|
||||
EXPECT_EQ(MinidumpUTF8StringAtRVAAsString(string_file.string(), 0),
|
||||
test_string);
|
||||
EXPECT_EQ(
|
||||
MinidumpUTF8StringAtRVAAsString(string_file.string(), TypeParam(0)),
|
||||
test_string);
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,11 +270,11 @@ void MinidumpStringListTest() {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MinidumpStringWriter, MinidumpUTF16StringList) {
|
||||
TYPED_TEST(MinidumpStringWriter, MinidumpUTF16StringList) {
|
||||
MinidumpStringListTest<MinidumpUTF16StringListWriterTraits>();
|
||||
}
|
||||
|
||||
TEST(MinidumpStringWriter, MinidumpUTF8StringList) {
|
||||
TYPED_TEST(MinidumpStringWriter, MinidumpUTF8StringList) {
|
||||
MinidumpStringListTest<MinidumpUTF8StringListWriterTraits>();
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,11 @@ namespace test {
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
const T* TMinidumpStringAtRVA(const std::string& file_contents, RVA rva) {
|
||||
template <
|
||||
typename T,
|
||||
typename RVAType = RVA,
|
||||
typename MinidumpLocationDescriptorType = MINIDUMP_LOCATION_DESCRIPTOR>
|
||||
const T* TMinidumpStringAtRVA(const std::string& file_contents, RVAType rva) {
|
||||
const T* string_base = MinidumpWritableAtRVA<T>(file_contents, rva);
|
||||
if (!string_base) {
|
||||
return nullptr;
|
||||
@ -41,7 +44,7 @@ const T* TMinidumpStringAtRVA(const std::string& file_contents, RVA rva) {
|
||||
}
|
||||
|
||||
// |Length| does not include space for the required NUL terminator.
|
||||
MINIDUMP_LOCATION_DESCRIPTOR location;
|
||||
MinidumpLocationDescriptorType location;
|
||||
location.DataSize =
|
||||
sizeof(*string_base) + string_base->Length + kCodeUnitSize;
|
||||
location.Rva = rva;
|
||||
@ -62,11 +65,16 @@ const T* TMinidumpStringAtRVA(const std::string& file_contents, RVA rva) {
|
||||
return string;
|
||||
}
|
||||
|
||||
template <typename StringType, typename MinidumpStringType>
|
||||
template <typename StringType,
|
||||
typename MinidumpStringType,
|
||||
typename RVAType,
|
||||
typename MinidumpLocationDescriptorType>
|
||||
StringType TMinidumpStringAtRVAAsString(const std::string& file_contents,
|
||||
RVA rva) {
|
||||
RVAType rva) {
|
||||
const MinidumpStringType* minidump_string =
|
||||
TMinidumpStringAtRVA<MinidumpStringType>(file_contents, rva);
|
||||
TMinidumpStringAtRVA<MinidumpStringType,
|
||||
RVAType,
|
||||
MinidumpLocationDescriptorType>(file_contents, rva);
|
||||
if (!minidump_string) {
|
||||
return StringType();
|
||||
}
|
||||
@ -82,24 +90,69 @@ StringType TMinidumpStringAtRVAAsString(const std::string& file_contents,
|
||||
|
||||
const MINIDUMP_STRING* MinidumpStringAtRVA(const std::string& file_contents,
|
||||
RVA rva) {
|
||||
return TMinidumpStringAtRVA<MINIDUMP_STRING>(file_contents, rva);
|
||||
return TMinidumpStringAtRVA<MINIDUMP_STRING,
|
||||
RVA,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR>(file_contents, rva);
|
||||
}
|
||||
|
||||
const MINIDUMP_STRING* MinidumpStringAtRVA(const std::string& file_contents,
|
||||
RVA64 rva) {
|
||||
return TMinidumpStringAtRVA<MINIDUMP_STRING,
|
||||
RVA64,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64>(file_contents,
|
||||
rva);
|
||||
}
|
||||
|
||||
const MinidumpUTF8String* MinidumpUTF8StringAtRVA(
|
||||
const std::string& file_contents,
|
||||
RVA rva) {
|
||||
return TMinidumpStringAtRVA<MinidumpUTF8String>(file_contents, rva);
|
||||
return TMinidumpStringAtRVA<MinidumpUTF8String,
|
||||
RVA,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR>(file_contents, rva);
|
||||
}
|
||||
|
||||
const MinidumpUTF8String* MinidumpUTF8StringAtRVA(
|
||||
const std::string& file_contents,
|
||||
RVA64 rva) {
|
||||
return TMinidumpStringAtRVA<MinidumpUTF8String,
|
||||
RVA64,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64>(file_contents,
|
||||
rva);
|
||||
}
|
||||
|
||||
std::u16string MinidumpStringAtRVAAsString(const std::string& file_contents,
|
||||
RVA rva) {
|
||||
return TMinidumpStringAtRVAAsString<std::u16string, MINIDUMP_STRING>(
|
||||
return TMinidumpStringAtRVAAsString<std::u16string,
|
||||
MINIDUMP_STRING,
|
||||
RVA,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR>(
|
||||
file_contents, rva);
|
||||
}
|
||||
|
||||
std::u16string MinidumpStringAtRVAAsString(const std::string& file_contents,
|
||||
RVA64 rva) {
|
||||
return TMinidumpStringAtRVAAsString<std::u16string,
|
||||
MINIDUMP_STRING,
|
||||
RVA64,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64>(
|
||||
file_contents, rva);
|
||||
}
|
||||
|
||||
std::string MinidumpUTF8StringAtRVAAsString(const std::string& file_contents,
|
||||
RVA rva) {
|
||||
return TMinidumpStringAtRVAAsString<std::string, MinidumpUTF8String>(
|
||||
return TMinidumpStringAtRVAAsString<std::string,
|
||||
MinidumpUTF8String,
|
||||
RVA,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR>(
|
||||
file_contents, rva);
|
||||
}
|
||||
|
||||
std::string MinidumpUTF8StringAtRVAAsString(const std::string& file_contents,
|
||||
RVA64 rva) {
|
||||
return TMinidumpStringAtRVAAsString<std::string,
|
||||
MinidumpUTF8String,
|
||||
RVA64,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64>(
|
||||
file_contents, rva);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,11 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "minidump/test/minidump_writable_test_util.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
struct MinidumpUTF8String;
|
||||
@ -44,6 +49,10 @@ namespace test {
|
||||
const MINIDUMP_STRING* MinidumpStringAtRVA(const std::string& file_contents,
|
||||
RVA rva);
|
||||
|
||||
//! \brief 64-bit specialization of MinidumpStringAtRVA.
|
||||
const MINIDUMP_STRING* MinidumpStringAtRVA(const std::string& file_contents,
|
||||
RVA64 rva);
|
||||
|
||||
//! \brief Returns a MinidumpUTF8String located within a minidump file’s
|
||||
//! contents.
|
||||
//!
|
||||
@ -64,6 +73,11 @@ const MinidumpUTF8String* MinidumpUTF8StringAtRVA(
|
||||
const std::string& file_contents,
|
||||
RVA rva);
|
||||
|
||||
//! \brief 64-bit specialization of MinidumpUTF8StringAtRVA.
|
||||
const MinidumpUTF8String* MinidumpUTF8StringAtRVA(
|
||||
const std::string& file_contents,
|
||||
RVA64 rva);
|
||||
|
||||
//! \brief Returns the contents of a MINIDUMP_STRING as a `std::u16string`.
|
||||
//!
|
||||
//! This function uses MinidumpStringAtRVA() to obtain a MINIDUMP_STRING, and
|
||||
@ -80,6 +94,10 @@ const MinidumpUTF8String* MinidumpUTF8StringAtRVA(
|
||||
std::u16string MinidumpStringAtRVAAsString(const std::string& file_contents,
|
||||
RVA rva);
|
||||
|
||||
//! \brief 64-bit specialization of MinidumpStringAtRVAAsString.
|
||||
std::u16string MinidumpStringAtRVAAsString(const std::string& file_contents,
|
||||
RVA64 rva);
|
||||
|
||||
//! \brief Returns the contents of a MinidumpUTF8String as a `std::string`.
|
||||
//!
|
||||
//! This function uses MinidumpUTF8StringAtRVA() to obtain a MinidumpUTF8String,
|
||||
@ -96,6 +114,10 @@ std::u16string MinidumpStringAtRVAAsString(const std::string& file_contents,
|
||||
std::string MinidumpUTF8StringAtRVAAsString(const std::string& file_contents,
|
||||
RVA rva);
|
||||
|
||||
//! \brief 64-bit specialization of MinidumpUTF8StringAtRVAAsString.
|
||||
std::string MinidumpUTF8StringAtRVAAsString(const std::string& file_contents,
|
||||
RVA64 rva);
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "util/file/file_writer.h"
|
||||
#include "util/misc/implicit_cast.h"
|
||||
#include "util/numeric/in_range_cast.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
@ -39,25 +40,26 @@ namespace {
|
||||
//!
|
||||
//! Do not call this function. Use the typed version, MinidumpWritableAtRVA<>(),
|
||||
//! or another type-specific function.
|
||||
template <typename RVAType>
|
||||
const void* MinidumpWritableAtRVAInternal(const std::string& file_contents,
|
||||
RVA rva) {
|
||||
if (rva >= file_contents.size()) {
|
||||
EXPECT_LT(rva, file_contents.size());
|
||||
RVAType rva) {
|
||||
const auto rva_offset = crashpad::InRangeCast(rva, file_contents.size());
|
||||
if (rva_offset >= file_contents.size()) {
|
||||
EXPECT_LT(rva_offset, file_contents.size());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &file_contents[rva];
|
||||
return &file_contents[rva_offset];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
template <typename RVAType, typename MinidumpLocationDescriptorType>
|
||||
const void* TMinidumpWritableAtLocationDescriptorInternal(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location,
|
||||
const MinidumpLocationDescriptorType& location,
|
||||
size_t expected_size,
|
||||
bool allow_oversized_data) {
|
||||
if (location.DataSize == 0) {
|
||||
EXPECT_EQ(location.Rva, 0u);
|
||||
EXPECT_EQ(location.Rva, RVAType(0));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -71,17 +73,42 @@ const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RVA end = location.Rva + location.DataSize;
|
||||
RVAType end = location.Rva + location.DataSize;
|
||||
if (end > file_contents.size()) {
|
||||
EXPECT_LE(end, file_contents.size());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const void* rv = MinidumpWritableAtRVAInternal(file_contents, location.Rva);
|
||||
const void* rv =
|
||||
MinidumpWritableAtRVAInternal<RVAType>(file_contents, location.Rva);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location,
|
||||
size_t expected_size,
|
||||
bool allow_oversized_data) {
|
||||
return TMinidumpWritableAtLocationDescriptorInternal<
|
||||
RVA,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR>(
|
||||
file_contents, location, expected_size, allow_oversized_data);
|
||||
}
|
||||
|
||||
const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR64& location,
|
||||
size_t expected_size,
|
||||
bool allow_oversized_data) {
|
||||
return TMinidumpWritableAtLocationDescriptorInternal<
|
||||
RVA64,
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64>(
|
||||
file_contents, location, expected_size, allow_oversized_data);
|
||||
}
|
||||
|
||||
template <>
|
||||
const IMAGE_DEBUG_MISC* MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(
|
||||
const std::string& file_contents,
|
||||
|
@ -59,6 +59,17 @@ const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
size_t expected_size,
|
||||
bool allow_oversized_data);
|
||||
|
||||
//! \brief 64-bit specialization of
|
||||
//! MinidumpWritableAtLocationDescriptorInternal.
|
||||
//!
|
||||
//! Do not call this function. Use the typed version,
|
||||
//! MinidumpWritableAtLocationDescriptor<>(), or another type-specific function.
|
||||
const void* MinidumpWritableAtLocationDescriptorInternal(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR64& location,
|
||||
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.
|
||||
//!
|
||||
@ -134,6 +145,22 @@ const T* TMinidumpWritableAtLocationDescriptor(
|
||||
MinidumpWritableTraits<T>::kAllowOversizedData));
|
||||
}
|
||||
|
||||
//! \brief 64-bit specialization of TMinidumpWritableAtLocationDescriptor.
|
||||
//!
|
||||
//! Do not call this function directly. Use
|
||||
//! MinidumpWritableAtLocationDescriptor<>() instead.
|
||||
template <typename T>
|
||||
const T* TMinidumpWritableAtLocationDescriptor(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR64& 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.
|
||||
//!
|
||||
@ -168,6 +195,14 @@ const T* MinidumpWritableAtLocationDescriptor(
|
||||
return TMinidumpWritableAtLocationDescriptor<T>(file_contents, location);
|
||||
}
|
||||
|
||||
//! \brief 64-bit specialization of MinidumpWritableAtLocationDescriptor.
|
||||
template <typename T>
|
||||
const T* MinidumpWritableAtLocationDescriptor(
|
||||
const std::string& file_contents,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR64& location) {
|
||||
return TMinidumpWritableAtLocationDescriptor<T>(file_contents, location);
|
||||
}
|
||||
|
||||
template <>
|
||||
const IMAGE_DEBUG_MISC* MinidumpWritableAtLocationDescriptor<IMAGE_DEBUG_MISC>(
|
||||
const std::string& file_contents,
|
||||
@ -270,6 +305,15 @@ const T* MinidumpWritableAtRVA(const std::string& file_contents, RVA rva) {
|
||||
return MinidumpWritableAtLocationDescriptor<T>(file_contents, location);
|
||||
}
|
||||
|
||||
//! \brief 64-bit specialization of MinidumpWritableAtRVA.
|
||||
template <typename T>
|
||||
const T* MinidumpWritableAtRVA(const std::string& file_contents, RVA64 rva) {
|
||||
MINIDUMP_LOCATION_DESCRIPTOR64 location;
|
||||
location.DataSize = sizeof(T);
|
||||
location.Rva = rva;
|
||||
return MinidumpWritableAtLocationDescriptor<T>(file_contents, location);
|
||||
}
|
||||
|
||||
//! \brief An internal::MinidumpWritable that carries a `uint32_t` for testing.
|
||||
class TestUInt32MinidumpWritable final : public internal::MinidumpWritable {
|
||||
public:
|
||||
|
@ -24,10 +24,10 @@ namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename StringType>
|
||||
template<typename StringType, typename RVAType>
|
||||
bool ReadMinidumpString(FileReaderInterface* file_reader,
|
||||
RVA rva,
|
||||
StringType* string) {
|
||||
RVAType rva,
|
||||
StringType* string) {
|
||||
if (rva == 0) {
|
||||
string->clear();
|
||||
return true;
|
||||
@ -59,12 +59,24 @@ bool ReadMinidumpUTF8String(FileReaderInterface* file_reader,
|
||||
return ReadMinidumpString(file_reader, rva, string);
|
||||
}
|
||||
|
||||
bool ReadMinidumpUTF8String(FileReaderInterface* file_reader,
|
||||
RVA64 rva,
|
||||
std::string* string) {
|
||||
return ReadMinidumpString(file_reader, rva, string);
|
||||
}
|
||||
|
||||
bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA rva,
|
||||
std::u16string* string) {
|
||||
return ReadMinidumpString(file_reader, rva, string);
|
||||
}
|
||||
|
||||
bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA64 rva,
|
||||
std::u16string* string) {
|
||||
return ReadMinidumpString(file_reader, rva, string);
|
||||
}
|
||||
|
||||
bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA rva,
|
||||
std::string* string) {
|
||||
@ -79,5 +91,19 @@ bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA64 rva,
|
||||
std::string* string) {
|
||||
std::u16string string_raw;
|
||||
|
||||
if (!ReadMinidumpString(file_reader, rva, &string_raw)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
base::UTF16ToUTF8(string_raw.data(), string_raw.size(), string);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "util/file/file_reader.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -34,6 +36,11 @@ bool ReadMinidumpUTF8String(FileReaderInterface* file_reader,
|
||||
RVA rva,
|
||||
std::string* string);
|
||||
|
||||
//! \brief 64-bit specialization of ReadMinidumpUTF8String.
|
||||
bool ReadMinidumpUTF8String(FileReaderInterface* file_reader,
|
||||
RVA64 rva,
|
||||
std::string* string);
|
||||
|
||||
//! \brief Reads a MinidumpUTF16String from a minidump file at offset \a rva in
|
||||
//! \a file_reader, and returns it in \a string.
|
||||
//!
|
||||
@ -43,6 +50,11 @@ bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA rva,
|
||||
std::u16string* string);
|
||||
|
||||
//! \brief 64-bit specialization of ReadMinidumpUTF16String.
|
||||
bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA64 rva,
|
||||
std::u16string* string);
|
||||
|
||||
//! \brief Reads a MinidumpUTF16String from a minidump file at offset \a rva in
|
||||
//! \a file_reader, and returns it in \a string.
|
||||
//!
|
||||
@ -52,6 +64,11 @@ bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA rva,
|
||||
std::string* string);
|
||||
|
||||
//! \brief 64-bit specialization of ReadMinidumpUTF16String.
|
||||
bool ReadMinidumpUTF16String(FileReaderInterface* file_reader,
|
||||
RVA64 rva,
|
||||
std::string* string);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user