support::ulittle32_t SizeOfHeader;
support::ulittle32_t SizeOfEntry;
support::ulittle64_t NumberOfEntries;
+
+ MemoryInfoListHeader() = default;
+ MemoryInfoListHeader(uint32_t SizeOfHeader, uint32_t SizeOfEntry,
+ uint64_t NumberOfEntries)
+ : SizeOfHeader(SizeOfHeader), SizeOfEntry(SizeOfEntry),
+ NumberOfEntries(NumberOfEntries) {}
};
static_assert(sizeof(MemoryInfoListHeader) == 16, "");
enum class MemoryState : uint32_t {
#define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME) NAME = CODE,
#include "llvm/BinaryFormat/MinidumpConstants.def"
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
};
enum class MemoryType : uint32_t {
#define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME) NAME = CODE,
#include "llvm/BinaryFormat/MinidumpConstants.def"
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
};
struct MemoryInfo {
/// from Types to Kinds is fixed and given by the static getKind function.
struct Stream {
enum class StreamKind {
+ MemoryInfoList,
MemoryList,
ModuleList,
RawContent,
using ThreadListStream = detail::ListStream<detail::ParsedThread>;
using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>;
+/// A structure containing the list of MemoryInfo entries comprising a
+/// MemoryInfoList stream.
+struct MemoryInfoListStream : public Stream {
+ std::vector<minidump::MemoryInfo> Infos;
+
+ MemoryInfoListStream()
+ : Stream(StreamKind::MemoryInfoList,
+ minidump::StreamType::MemoryInfoList) {}
+
+ explicit MemoryInfoListStream(
+ iterator_range<object::MinidumpFile::MemoryInfoIterator> Range)
+ : Stream(StreamKind::MemoryInfoList,
+ minidump::StreamType::MemoryInfoList),
+ Infos(Range.begin(), Range.end()) {}
+
+ static bool classof(const Stream *S) {
+ return S->Kind == StreamKind::MemoryInfoList;
+ }
+};
+
/// A minidump stream represented as a sequence of hex bytes. This is used as a
/// fallback when no other stream kind is suitable.
struct RawContentStream : public Stream {
minidump::SystemInfo Info;
std::string CSDVersion;
- explicit SystemInfoStream(const minidump::SystemInfo &Info,
- std::string CSDVersion)
- : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo),
- Info(Info), CSDVersion(std::move(CSDVersion)) {}
-
SystemInfoStream()
: Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo) {
memset(&Info, 0, sizeof(Info));
}
+ explicit SystemInfoStream(const minidump::SystemInfo &Info,
+ std::string CSDVersion)
+ : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo),
+ Info(Info), CSDVersion(std::move(CSDVersion)) {}
+
static bool classof(const Stream *S) {
return S->Kind == StreamKind::SystemInfo;
}
} // namespace llvm
+LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryProtection)
+LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryState)
+LLVM_YAML_DECLARE_BITSET_TRAITS(llvm::minidump::MemoryType)
+
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture)
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform)
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::MemoryInfo)
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo)
LLVM_YAML_DECLARE_MAPPING_TRAITS(
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::MemoryListStream::entry_type)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ModuleListStream::entry_type)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ThreadListStream::entry_type)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::minidump::MemoryInfo)
LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object)
Result.Location.RVA = File.tell();
Optional<size_t> DataEnd;
switch (S.Kind) {
+ case Stream::StreamKind::MemoryInfoList: {
+ MemoryInfoListStream &InfoList = cast<MemoryInfoListStream>(S);
+ File.allocateNewObject<minidump::MemoryInfoListHeader>(
+ sizeof(minidump::MemoryInfoListHeader), sizeof(minidump::MemoryInfo),
+ InfoList.Infos.size());
+ File.allocateArray(makeArrayRef(InfoList.Infos));
+ break;
+ }
case Stream::StreamKind::MemoryList:
DataEnd = layout(File, cast<MemoryListStream>(S));
break;
Stream::StreamKind Stream::getKind(StreamType Type) {
switch (Type) {
+ case StreamType::MemoryInfoList:
+ return StreamKind::MemoryInfoList;
case StreamType::MemoryList:
return StreamKind::MemoryList;
case StreamType::ModuleList:
std::unique_ptr<Stream> Stream::create(StreamType Type) {
StreamKind Kind = getKind(Type);
switch (Kind) {
+ case StreamKind::MemoryInfoList:
+ return std::make_unique<MemoryInfoListStream>();
case StreamKind::MemoryList:
return std::make_unique<MemoryListStream>();
case StreamKind::ModuleList:
llvm_unreachable("Unhandled stream kind!");
}
+void yaml::ScalarBitSetTraits<MemoryProtection>::bitset(
+ IO &IO, MemoryProtection &Protect) {
+#define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME) \
+ IO.bitSetCase(Protect, #NATIVENAME, MemoryProtection::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+}
+
+void yaml::ScalarBitSetTraits<MemoryState>::bitset(IO &IO, MemoryState &State) {
+#define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME) \
+ IO.bitSetCase(State, #NATIVENAME, MemoryState::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+}
+
+void yaml::ScalarBitSetTraits<MemoryType>::bitset(IO &IO, MemoryType &Type) {
+#define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME) \
+ IO.bitSetCase(Type, #NATIVENAME, MemoryType::NAME);
+#include "llvm/BinaryFormat/MinidumpConstants.def"
+}
+
void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration(
IO &IO, ProcessorArchitecture &Arch) {
#define HANDLE_MDMP_ARCH(CODE, NAME) \
mapOptionalHex(IO, "AMD Extended Features", Info.AMDExtendedFeatures, 0);
}
+void yaml::MappingTraits<MemoryInfo>::mapping(IO &IO, MemoryInfo &Info) {
+ mapRequiredHex(IO, "Base Address", Info.BaseAddress);
+ mapOptionalHex(IO, "Allocation Base", Info.AllocationBase, Info.BaseAddress);
+ mapRequiredAs<MemoryProtection>(IO, "Allocation Protect",
+ Info.AllocationProtect);
+ mapOptionalHex(IO, "Reserved0", Info.Reserved0, 0);
+ mapRequiredHex(IO, "Region Size", Info.RegionSize);
+ mapRequiredAs<MemoryState>(IO, "State", Info.State);
+ mapOptionalAs<MemoryProtection>(IO, "Protect", Info.Protect,
+ Info.AllocationProtect);
+ mapRequiredAs<MemoryType>(IO, "Type", Info.Type);
+ mapOptionalHex(IO, "Reserved1", Info.Reserved1, 0);
+}
+
void yaml::MappingTraits<VSFixedFileInfo>::mapping(IO &IO,
VSFixedFileInfo &Info) {
mapOptionalHex(IO, "Signature", Info.Signature, 0);
IO, Range.Entry, Range.Content);
}
+static void streamMapping(yaml::IO &IO, MemoryInfoListStream &Stream) {
+ IO.mapRequired("Memory Ranges", Stream.Infos);
+}
+
static void streamMapping(yaml::IO &IO, MemoryListStream &Stream) {
IO.mapRequired("Memory Ranges", Stream.Entries);
}
if (!IO.outputting())
S = MinidumpYAML::Stream::create(Type);
switch (S->Kind) {
+ case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
+ streamMapping(IO, llvm::cast<MemoryInfoListStream>(*S));
+ break;
case MinidumpYAML::Stream::StreamKind::MemoryList:
streamMapping(IO, llvm::cast<MemoryListStream>(*S));
break;
switch (S->Kind) {
case MinidumpYAML::Stream::StreamKind::RawContent:
return streamValidate(cast<RawContentStream>(*S));
+ case MinidumpYAML::Stream::StreamKind::MemoryInfoList:
case MinidumpYAML::Stream::StreamKind::MemoryList:
case MinidumpYAML::Stream::StreamKind::ModuleList:
case MinidumpYAML::Stream::StreamKind::SystemInfo:
Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
StreamKind Kind = getKind(StreamDesc.Type);
switch (Kind) {
+ case StreamKind::MemoryInfoList: {
+ if (auto ExpectedList = File.getMemoryInfoList())
+ return std::make_unique<MemoryInfoListStream>(*ExpectedList);
+ else
+ return ExpectedList.takeError();
+ }
case StreamKind::MemoryList: {
auto ExpectedList = File.getMemoryList();
if (!ExpectedList)
Memory Ranges:
- Start of Memory Range: 0x7C7D7E7F80818283
Content: '8485868788'
+ - Type: MemoryInfoList
+ Memory Ranges:
+ - Base Address: 0x0000000000000000
+ Allocation Protect: [ ]
+ Region Size: 0x0000000000010000
+ State: [ MEM_FREE ]
+ Protect: [ PAGE_NO_ACCESS ]
+ Type: [ ]
+ - Base Address: 0x0000000000010000
+ Allocation Protect: [ PAGE_READ_WRITE ]
+ Region Size: 0x0000000000010000
+ State: [ MEM_COMMIT ]
+ Type: [ MEM_MAPPED ]
+ - Base Address: 0x0000000000020000
+ Allocation Base: 0x0000000000000000
+ Allocation Protect: [ PAGE_READ_WRITE, PAGE_WRITECOMBINE ]
+ Reserved0: 0xDEADBEEF
+ Region Size: 0x0000000000010000
+ State: [ MEM_COMMIT, MEM_FREE ]
+ Type: [ MEM_PRIVATE, MEM_MAPPED ]
+ Reserved1: 0xBAADF00D
...
# CHECK: --- !minidump
# CHECK-NEXT: Memory Ranges:
# CHECK-NEXT: - Start of Memory Range: 0x7C7D7E7F80818283
# CHECK-NEXT: Content: '8485868788'
+# CHECK-NEXT: - Type: MemoryInfoList
+# CHECK-NEXT: Memory Ranges:
+# CHECK-NEXT: - Base Address: 0x0000000000000000
+# CHECK-NEXT: Allocation Protect: [ ]
+# CHECK-NEXT: Region Size: 0x0000000000010000
+# CHECK-NEXT: State: [ MEM_FREE ]
+# CHECK-NEXT: Protect: [ PAGE_NO_ACCESS ]
+# CHECK-NEXT: Type: [ ]
+# CHECK-NEXT: - Base Address: 0x0000000000010000
+# CHECK-NEXT: Allocation Protect: [ PAGE_READ_WRITE ]
+# CHECK-NEXT: Region Size: 0x0000000000010000
+# CHECK-NEXT: State: [ MEM_COMMIT ]
+# CHECK-NEXT: Type: [ MEM_MAPPED ]
+# CHECK-NEXT: - Base Address: 0x0000000000020000
+# CHECK-NEXT: Allocation Base: 0x0000000000000000
+# CHECK-NEXT: Allocation Protect: [ PAGE_READ_WRITE, PAGE_WRITECOMBINE ]
+# CHECK-NEXT: Reserved0: 0xDEADBEEF
+# CHECK-NEXT: Region Size: 0x0000000000010000
+# CHECK-NEXT: State: [ MEM_COMMIT, MEM_FREE ]
+# CHECK-NEXT: Type: [ MEM_PRIVATE, MEM_MAPPED ]
+# CHECK-NEXT: Reserved1: 0xBAADF00D
# CHECK-NEXT: ...