mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-15 12:09:51 +00:00
Update MinidumpYAML to use minidump::Exception for exception stream
Reviewers: labath, jhenderson, clayborg, MaskRay, grimar Reviewed By: grimar Subscribers: lldb-commits, grimar, MaskRay, hiraditya, llvm-commits Tags: #llvm, #lldb Differential Revision: https://reviews.llvm.org/D68657 llvm-svn: 375242
This commit is contained in:
parent
6c7d7eebda
commit
a50272f826
@ -14,7 +14,10 @@ Streams:
|
||||
Module Name: '/tmp/test/linux-x86_64'
|
||||
CodeView Record: 4C457042E35C283BC327C28762DB788BF5A4078BE2351448
|
||||
- Type: Exception
|
||||
Content: DD740000000000000B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D0040000F8310000
|
||||
Thread ID: 0x000074DD
|
||||
Exception Record:
|
||||
Exception Code: 0x0000000B
|
||||
Thread Context: 00000000
|
||||
- Type: SystemInfo
|
||||
Processor Arch: AMD64
|
||||
Processor Level: 6
|
||||
|
@ -26,6 +26,7 @@ namespace MinidumpYAML {
|
||||
/// from Types to Kinds is fixed and given by the static getKind function.
|
||||
struct Stream {
|
||||
enum class StreamKind {
|
||||
Exception,
|
||||
MemoryInfoList,
|
||||
MemoryList,
|
||||
ModuleList,
|
||||
@ -103,6 +104,25 @@ using ModuleListStream = detail::ListStream<detail::ParsedModule>;
|
||||
using ThreadListStream = detail::ListStream<detail::ParsedThread>;
|
||||
using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>;
|
||||
|
||||
/// ExceptionStream minidump stream.
|
||||
struct ExceptionStream : public Stream {
|
||||
minidump::ExceptionStream MDExceptionStream;
|
||||
yaml::BinaryRef ThreadContext;
|
||||
|
||||
ExceptionStream()
|
||||
: Stream(StreamKind::Exception, minidump::StreamType::Exception),
|
||||
MDExceptionStream({}) {}
|
||||
|
||||
explicit ExceptionStream(const minidump::ExceptionStream &MDExceptionStream,
|
||||
ArrayRef<uint8_t> ThreadContext)
|
||||
: Stream(StreamKind::Exception, minidump::StreamType::Exception),
|
||||
MDExceptionStream(MDExceptionStream), ThreadContext(ThreadContext) {}
|
||||
|
||||
static bool classof(const Stream *S) {
|
||||
return S->Kind == StreamKind::Exception;
|
||||
}
|
||||
};
|
||||
|
||||
/// A structure containing the list of MemoryInfo entries comprising a
|
||||
/// MemoryInfoList stream.
|
||||
struct MemoryInfoListStream : public Stream {
|
||||
@ -239,6 +259,7 @@ LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType)
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo)
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo)
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info)
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::Exception)
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::MemoryInfo)
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo)
|
||||
|
||||
|
@ -118,6 +118,23 @@ static LocationDescriptor layout(BlobAllocator &File, yaml::BinaryRef Data) {
|
||||
support::ulittle32_t(File.allocateBytes(Data))};
|
||||
}
|
||||
|
||||
static size_t layout(BlobAllocator &File, MinidumpYAML::ExceptionStream &S) {
|
||||
File.allocateObject(S.MDExceptionStream);
|
||||
|
||||
size_t DataEnd = File.tell();
|
||||
|
||||
// Lay out the thread context data, (which is not a part of the stream).
|
||||
// TODO: This usually (always?) matches the thread context of the
|
||||
// corresponding thread, and may overlap memory regions as well. We could
|
||||
// add a level of indirection to the MinidumpYAML format (like an array of
|
||||
// Blobs that the LocationDescriptors index into) to be able to distinguish
|
||||
// the cases where location descriptions overlap vs happen to reference
|
||||
// identical data.
|
||||
S.MDExceptionStream.ThreadContext = layout(File, S.ThreadContext);
|
||||
|
||||
return DataEnd;
|
||||
}
|
||||
|
||||
static void layout(BlobAllocator &File, MemoryListStream::entry_type &Range) {
|
||||
Range.Entry.Memory = layout(File, Range.Content);
|
||||
}
|
||||
@ -158,6 +175,9 @@ static Directory layout(BlobAllocator &File, Stream &S) {
|
||||
Result.Location.RVA = File.tell();
|
||||
Optional<size_t> DataEnd;
|
||||
switch (S.Kind) {
|
||||
case Stream::StreamKind::Exception:
|
||||
DataEnd = layout(File, cast<MinidumpYAML::ExceptionStream>(S));
|
||||
break;
|
||||
case Stream::StreamKind::MemoryInfoList: {
|
||||
MemoryInfoListStream &InfoList = cast<MemoryInfoListStream>(S);
|
||||
File.allocateNewObject<minidump::MemoryInfoListHeader>(
|
||||
|
@ -69,6 +69,8 @@ Stream::~Stream() = default;
|
||||
|
||||
Stream::StreamKind Stream::getKind(StreamType Type) {
|
||||
switch (Type) {
|
||||
case StreamType::Exception:
|
||||
return StreamKind::Exception;
|
||||
case StreamType::MemoryInfoList:
|
||||
return StreamKind::MemoryInfoList;
|
||||
case StreamType::MemoryList:
|
||||
@ -95,6 +97,8 @@ Stream::StreamKind Stream::getKind(StreamType Type) {
|
||||
std::unique_ptr<Stream> Stream::create(StreamType Type) {
|
||||
StreamKind Kind = getKind(Type);
|
||||
switch (Kind) {
|
||||
case StreamKind::Exception:
|
||||
return std::make_unique<ExceptionStream>();
|
||||
case StreamKind::MemoryInfoList:
|
||||
return std::make_unique<MemoryInfoListStream>();
|
||||
case StreamKind::MemoryList:
|
||||
@ -274,8 +278,7 @@ void yaml::MappingTraits<ModuleListStream::entry_type>::mapping(
|
||||
mapRequiredHex(IO, "Base of Image", M.Entry.BaseOfImage);
|
||||
mapRequiredHex(IO, "Size of Image", M.Entry.SizeOfImage);
|
||||
mapOptionalHex(IO, "Checksum", M.Entry.Checksum, 0);
|
||||
IO.mapOptional("Time Date Stamp", M.Entry.TimeDateStamp,
|
||||
support::ulittle32_t(0));
|
||||
mapOptional(IO, "Time Date Stamp", M.Entry.TimeDateStamp, 0);
|
||||
IO.mapRequired("Module Name", M.Name);
|
||||
IO.mapOptional("Version Info", M.Entry.VersionInfo, VSFixedFileInfo());
|
||||
IO.mapRequired("CodeView Record", M.CvRecord);
|
||||
@ -367,6 +370,32 @@ static void streamMapping(yaml::IO &IO, ThreadListStream &Stream) {
|
||||
IO.mapRequired("Threads", Stream.Entries);
|
||||
}
|
||||
|
||||
static void streamMapping(yaml::IO &IO, MinidumpYAML::ExceptionStream &Stream) {
|
||||
mapRequiredHex(IO, "Thread ID", Stream.MDExceptionStream.ThreadId);
|
||||
IO.mapRequired("Exception Record", Stream.MDExceptionStream.ExceptionRecord);
|
||||
IO.mapRequired("Thread Context", Stream.ThreadContext);
|
||||
}
|
||||
|
||||
void yaml::MappingTraits<minidump::Exception>::mapping(
|
||||
yaml::IO &IO, minidump::Exception &Exception) {
|
||||
mapRequiredHex(IO, "Exception Code", Exception.ExceptionCode);
|
||||
mapOptionalHex(IO, "Exception Flags", Exception.ExceptionFlags, 0);
|
||||
mapOptionalHex(IO, "Exception Record", Exception.ExceptionRecord, 0);
|
||||
mapOptionalHex(IO, "Exception Address", Exception.ExceptionAddress, 0);
|
||||
mapOptional(IO, "Number of Parameters", Exception.NumberParameters, 0);
|
||||
|
||||
for (size_t Index = 0; Index < Exception.MaxParameters; ++Index) {
|
||||
SmallString<16> Name("Parameter ");
|
||||
Twine(Index).toVector(Name);
|
||||
support::ulittle64_t &Field = Exception.ExceptionInformation[Index];
|
||||
|
||||
if (Index < Exception.NumberParameters)
|
||||
mapRequiredHex(IO, Name.c_str(), Field);
|
||||
else
|
||||
mapOptionalHex(IO, Name.c_str(), Field, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(
|
||||
yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) {
|
||||
StreamType Type;
|
||||
@ -377,6 +406,9 @@ void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping(
|
||||
if (!IO.outputting())
|
||||
S = MinidumpYAML::Stream::create(Type);
|
||||
switch (S->Kind) {
|
||||
case MinidumpYAML::Stream::StreamKind::Exception:
|
||||
streamMapping(IO, llvm::cast<MinidumpYAML::ExceptionStream>(*S));
|
||||
break;
|
||||
case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
|
||||
streamMapping(IO, llvm::cast<MemoryInfoListStream>(*S));
|
||||
break;
|
||||
@ -406,6 +438,7 @@ StringRef yaml::MappingTraits<std::unique_ptr<Stream>>::validate(
|
||||
switch (S->Kind) {
|
||||
case MinidumpYAML::Stream::StreamKind::RawContent:
|
||||
return streamValidate(cast<RawContentStream>(*S));
|
||||
case MinidumpYAML::Stream::StreamKind::Exception:
|
||||
case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
|
||||
case MinidumpYAML::Stream::StreamKind::MemoryList:
|
||||
case MinidumpYAML::Stream::StreamKind::ModuleList:
|
||||
@ -429,6 +462,18 @@ Expected<std::unique_ptr<Stream>>
|
||||
Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
|
||||
StreamKind Kind = getKind(StreamDesc.Type);
|
||||
switch (Kind) {
|
||||
case StreamKind::Exception: {
|
||||
Expected<const minidump::ExceptionStream &> ExpectedExceptionStream =
|
||||
File.getExceptionStream();
|
||||
if (!ExpectedExceptionStream)
|
||||
return ExpectedExceptionStream.takeError();
|
||||
Expected<ArrayRef<uint8_t>> ExpectedThreadContext =
|
||||
File.getRawData(ExpectedExceptionStream->ThreadContext);
|
||||
if (!ExpectedThreadContext)
|
||||
return ExpectedThreadContext.takeError();
|
||||
return std::make_unique<ExceptionStream>(*ExpectedExceptionStream,
|
||||
*ExpectedThreadContext);
|
||||
}
|
||||
case StreamKind::MemoryInfoList: {
|
||||
if (auto ExpectedList = File.getMemoryInfoList())
|
||||
return std::make_unique<MemoryInfoListStream>(*ExpectedList);
|
||||
|
@ -51,6 +51,17 @@ Streams:
|
||||
Stack:
|
||||
Start of Memory Range: 0x6C6D6E6F70717273
|
||||
Content: '7475767778797A7B'
|
||||
- Type: Exception
|
||||
Thread ID: 0x7
|
||||
Exception Record:
|
||||
Exception Code: 0x10
|
||||
Exception Flags: 0x5
|
||||
Exception Record: 0x0102030405060708
|
||||
Exception Address: 0x0A0B0C0D0E0F1011
|
||||
Number of Parameters: 2
|
||||
Parameter 0: 0x22
|
||||
Parameter 1: 0x24
|
||||
Thread Context: '8182838485868788'
|
||||
- Type: MemoryList
|
||||
Memory Ranges:
|
||||
- Start of Memory Range: 0x7C7D7E7F80818283
|
||||
@ -129,6 +140,17 @@ Streams:
|
||||
# CHECK-NEXT: Stack:
|
||||
# CHECK-NEXT: Start of Memory Range: 0x6C6D6E6F70717273
|
||||
# CHECK-NEXT: Content: 7475767778797A7B
|
||||
# CHECK-NEXT: - Type: Exception
|
||||
# CHECK-NEXT: Thread ID: 0x00000007
|
||||
# CHECK-NEXT: Exception Record:
|
||||
# CHECK-NEXT: Exception Code: 0x00000010
|
||||
# CHECK-NEXT: Exception Flags: 0x00000005
|
||||
# CHECK-NEXT: Exception Record: 0x0102030405060708
|
||||
# CHECK-NEXT: Exception Address: 0x0A0B0C0D0E0F1011
|
||||
# CHECK-NEXT: Number of Parameters: 2
|
||||
# CHECK-NEXT: Parameter 0: 0x0000000000000022
|
||||
# CHECK-NEXT: Parameter 1: 0x0000000000000024
|
||||
# CHECK-NEXT: Thread Context: '8182838485868788'
|
||||
# CHECK-NEXT: - Type: MemoryList
|
||||
# CHECK-NEXT: Memory Ranges:
|
||||
# CHECK-NEXT: - Start of Memory Range: 0x7C7D7E7F80818283
|
||||
|
@ -0,0 +1,21 @@
|
||||
# RUN: not yaml2obj %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
## Test that we report an error for an ExceptionStream where the specified
|
||||
## number of parameters is greater than the number of ExceptionInformation
|
||||
## elements listed.
|
||||
|
||||
--- !minidump
|
||||
Streams:
|
||||
- Type: Exception
|
||||
Thread ID: 0x7
|
||||
Exception Record:
|
||||
Exception Code: 0x23
|
||||
Exception Flags: 0x5
|
||||
Exception Record: 0x0102030405060708
|
||||
Exception Address: 0x0a0b0c0d0e0f1011
|
||||
Number of Parameters: 4
|
||||
Parameter 0: 0x99
|
||||
Parameter 1: 0x23
|
||||
Parameter 2: 0x42
|
||||
# CHECK: error: missing required key 'Parameter 3'
|
||||
Thread Context: 3DeadBeefDefacedABadCafe)");
|
@ -139,3 +139,200 @@ Streams:
|
||||
(ArrayRef<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
|
||||
makeArrayRef(SysInfo.CPU.Other.ProcessorFeatures));
|
||||
}
|
||||
|
||||
// Test that we can parse a normal-looking ExceptionStream.
|
||||
TEST(MinidumpYAML, ExceptionStream) {
|
||||
SmallString<0> Storage;
|
||||
auto ExpectedFile = toBinary(Storage, R"(
|
||||
--- !minidump
|
||||
Streams:
|
||||
- Type: Exception
|
||||
Thread ID: 0x7
|
||||
Exception Record:
|
||||
Exception Code: 0x23
|
||||
Exception Flags: 0x5
|
||||
Exception Record: 0x0102030405060708
|
||||
Exception Address: 0x0a0b0c0d0e0f1011
|
||||
Number of Parameters: 2
|
||||
Parameter 0: 0x22
|
||||
Parameter 1: 0x24
|
||||
Thread Context: 3DeadBeefDefacedABadCafe)");
|
||||
ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
|
||||
object::MinidumpFile &File = **ExpectedFile;
|
||||
|
||||
ASSERT_EQ(1u, File.streams().size());
|
||||
|
||||
Expected<const minidump::ExceptionStream &> ExpectedStream =
|
||||
File.getExceptionStream();
|
||||
|
||||
ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
|
||||
|
||||
const minidump::ExceptionStream &Stream = *ExpectedStream;
|
||||
EXPECT_EQ(0x7u, Stream.ThreadId);
|
||||
const minidump::Exception &Exception = Stream.ExceptionRecord;
|
||||
EXPECT_EQ(0x23u, Exception.ExceptionCode);
|
||||
EXPECT_EQ(0x5u, Exception.ExceptionFlags);
|
||||
EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord);
|
||||
EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress);
|
||||
EXPECT_EQ(2u, Exception.NumberParameters);
|
||||
EXPECT_EQ(0x22u, Exception.ExceptionInformation[0]);
|
||||
EXPECT_EQ(0x24u, Exception.ExceptionInformation[1]);
|
||||
|
||||
Expected<ArrayRef<uint8_t>> ExpectedContext =
|
||||
File.getRawData(Stream.ThreadContext);
|
||||
ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
|
||||
EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
|
||||
0xab, 0xad, 0xca, 0xfe}),
|
||||
*ExpectedContext);
|
||||
}
|
||||
|
||||
// Test that we can parse an exception stream with no ExceptionInformation.
|
||||
TEST(MinidumpYAML, ExceptionStream_NoParameters) {
|
||||
SmallString<0> Storage;
|
||||
auto ExpectedFile = toBinary(Storage, R"(
|
||||
--- !minidump
|
||||
Streams:
|
||||
- Type: Exception
|
||||
Thread ID: 0x7
|
||||
Exception Record:
|
||||
Exception Code: 0x23
|
||||
Exception Flags: 0x5
|
||||
Exception Record: 0x0102030405060708
|
||||
Exception Address: 0x0a0b0c0d0e0f1011
|
||||
Thread Context: 3DeadBeefDefacedABadCafe)");
|
||||
ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
|
||||
object::MinidumpFile &File = **ExpectedFile;
|
||||
|
||||
ASSERT_EQ(1u, File.streams().size());
|
||||
|
||||
Expected<const minidump::ExceptionStream &> ExpectedStream =
|
||||
File.getExceptionStream();
|
||||
|
||||
ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
|
||||
|
||||
const minidump::ExceptionStream &Stream = *ExpectedStream;
|
||||
EXPECT_EQ(0x7u, Stream.ThreadId);
|
||||
const minidump::Exception &Exception = Stream.ExceptionRecord;
|
||||
EXPECT_EQ(0x23u, Exception.ExceptionCode);
|
||||
EXPECT_EQ(0x5u, Exception.ExceptionFlags);
|
||||
EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord);
|
||||
EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress);
|
||||
EXPECT_EQ(0u, Exception.NumberParameters);
|
||||
|
||||
Expected<ArrayRef<uint8_t>> ExpectedContext =
|
||||
File.getRawData(Stream.ThreadContext);
|
||||
ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
|
||||
EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
|
||||
0xab, 0xad, 0xca, 0xfe}),
|
||||
*ExpectedContext);
|
||||
}
|
||||
|
||||
// Test that we can parse an ExceptionStream where the stated number of
|
||||
// parameters is greater than the actual size of the ExceptionInformation
|
||||
// array.
|
||||
TEST(MinidumpYAML, ExceptionStream_TooManyParameters) {
|
||||
SmallString<0> Storage;
|
||||
auto ExpectedFile = toBinary(Storage, R"(
|
||||
--- !minidump
|
||||
Streams:
|
||||
- Type: Exception
|
||||
Thread ID: 0x8
|
||||
Exception Record:
|
||||
Exception Code: 0
|
||||
Number of Parameters: 16
|
||||
Parameter 0: 0x0
|
||||
Parameter 1: 0xff
|
||||
Parameter 2: 0xee
|
||||
Parameter 3: 0xdd
|
||||
Parameter 4: 0xcc
|
||||
Parameter 5: 0xbb
|
||||
Parameter 6: 0xaa
|
||||
Parameter 7: 0x99
|
||||
Parameter 8: 0x88
|
||||
Parameter 9: 0x77
|
||||
Parameter 10: 0x66
|
||||
Parameter 11: 0x55
|
||||
Parameter 12: 0x44
|
||||
Parameter 13: 0x33
|
||||
Parameter 14: 0x22
|
||||
Thread Context: 3DeadBeefDefacedABadCafe)");
|
||||
ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
|
||||
object::MinidumpFile &File = **ExpectedFile;
|
||||
|
||||
ASSERT_EQ(1u, File.streams().size());
|
||||
|
||||
Expected<const minidump::ExceptionStream &> ExpectedStream =
|
||||
File.getExceptionStream();
|
||||
|
||||
ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
|
||||
|
||||
const minidump::ExceptionStream &Stream = *ExpectedStream;
|
||||
EXPECT_EQ(0x8u, Stream.ThreadId);
|
||||
const minidump::Exception &Exception = Stream.ExceptionRecord;
|
||||
EXPECT_EQ(0x0u, Exception.ExceptionCode);
|
||||
EXPECT_EQ(0x0u, Exception.ExceptionFlags);
|
||||
EXPECT_EQ(0x00u, Exception.ExceptionRecord);
|
||||
EXPECT_EQ(0x0u, Exception.ExceptionAddress);
|
||||
EXPECT_EQ(16u, Exception.NumberParameters);
|
||||
EXPECT_EQ(0x0u, Exception.ExceptionInformation[0]);
|
||||
for (int Index = 1; Index < 15; ++Index) {
|
||||
EXPECT_EQ(0x110u - Index * 0x11, Exception.ExceptionInformation[Index]);
|
||||
}
|
||||
|
||||
Expected<ArrayRef<uint8_t>> ExpectedContext =
|
||||
File.getRawData(Stream.ThreadContext);
|
||||
ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
|
||||
EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
|
||||
0xab, 0xad, 0xca, 0xfe}),
|
||||
*ExpectedContext);
|
||||
}
|
||||
|
||||
// Test that we can parse an ExceptionStream where the number of
|
||||
// ExceptionInformation parameters provided is greater than the
|
||||
// specified Number of Parameters.
|
||||
TEST(MinidumpYAML, ExceptionStream_ExtraParameter) {
|
||||
SmallString<0> Storage;
|
||||
auto ExpectedFile = toBinary(Storage, R"(
|
||||
--- !minidump
|
||||
Streams:
|
||||
- Type: Exception
|
||||
Thread ID: 0x7
|
||||
Exception Record:
|
||||
Exception Code: 0x23
|
||||
Exception Flags: 0x5
|
||||
Exception Record: 0x0102030405060708
|
||||
Exception Address: 0x0a0b0c0d0e0f1011
|
||||
Number of Parameters: 2
|
||||
Parameter 0: 0x99
|
||||
Parameter 1: 0x23
|
||||
Parameter 2: 0x42
|
||||
Thread Context: 3DeadBeefDefacedABadCafe)");
|
||||
ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
|
||||
object::MinidumpFile &File = **ExpectedFile;
|
||||
|
||||
ASSERT_EQ(1u, File.streams().size());
|
||||
|
||||
Expected<const minidump::ExceptionStream &> ExpectedStream =
|
||||
File.getExceptionStream();
|
||||
|
||||
ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
|
||||
|
||||
const minidump::ExceptionStream &Stream = *ExpectedStream;
|
||||
EXPECT_EQ(0x7u, Stream.ThreadId);
|
||||
const minidump::Exception &Exception = Stream.ExceptionRecord;
|
||||
EXPECT_EQ(0x23u, Exception.ExceptionCode);
|
||||
EXPECT_EQ(0x5u, Exception.ExceptionFlags);
|
||||
EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord);
|
||||
EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress);
|
||||
EXPECT_EQ(2u, Exception.NumberParameters);
|
||||
EXPECT_EQ(0x99u, Exception.ExceptionInformation[0]);
|
||||
EXPECT_EQ(0x23u, Exception.ExceptionInformation[1]);
|
||||
EXPECT_EQ(0x42u, Exception.ExceptionInformation[2]);
|
||||
|
||||
Expected<ArrayRef<uint8_t>> ExpectedContext =
|
||||
File.getRawData(Stream.ThreadContext);
|
||||
ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
|
||||
EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
|
||||
0xab, 0xad, 0xca, 0xfe}),
|
||||
*ExpectedContext);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user