Index: source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp =================================================================== --- source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp +++ source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp @@ -39,7 +39,7 @@ return false; } HANDLE file_handle = ::CreateFileW(wide_name.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - const auto result = ::MiniDumpWriteDump(process_handle, process_sp->GetID(), file_handle, MiniDumpNormal, NULL, NULL, NULL); + const auto result = ::MiniDumpWriteDump(process_handle, process_sp->GetID(), file_handle, MiniDumpWithFullMemoryInfo, NULL, NULL, NULL); ::CloseHandle(file_handle); ::CloseHandle(process_handle); if (!result) Index: source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h =================================================================== --- source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h +++ source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h @@ -84,6 +84,9 @@ lldb_private::ArchSpec GetArchitecture(); + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &range_info) override; + protected: void Clear(); Index: source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp =================================================================== --- source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp +++ source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp @@ -27,6 +27,7 @@ #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/UnixSignals.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -272,6 +273,60 @@ return overlap; } + +Error +ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) +{ + Error error; + size_t size; + const auto list = reinterpret_cast(FindDumpStream(MemoryInfoListStream, &size)); + if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST)) + { + error.SetErrorString("the mini dump contains no memory range information"); + return error; + } + + if (list->SizeOfEntry < sizeof(MINIDUMP_MEMORY_INFO)) + { + error.SetErrorString("the entries in the mini dump memory info list are smaller than expected"); + return error; + } + + if (size < list->SizeOfHeader + list->SizeOfEntry * list->NumberOfEntries) + { + error.SetErrorString("the mini dump memory info list is incomplete"); + return error; + } + + const auto entries = reinterpret_cast(reinterpret_cast(list) + list->SizeOfHeader); + + for (int i = 0; i < list->NumberOfEntries; ++i) + { + const auto entry = reinterpret_cast(reinterpret_cast(list) + list->SizeOfHeader + i*list->SizeOfEntry); + const auto head = entry->BaseAddress; + const auto tail = head + entry->RegionSize; + if (head <= load_addr && load_addr < tail) + { + // The Windows page protection bits are not independent masks that can + // be bitwise-ORed together. For example, PAGE_EXECUTE_READ is not + // (PAGE_EXECUTE | PAGE_READ). To test for an access type, it's + // necessary to test for any of the bits that provide that access type. + const bool readable = entry->Protect & (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_READONLY | PAGE_READWRITE); + info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + const bool writable = entry->Protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOPY); + info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + const bool executable = entry->Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); + info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + return error; + } + } + // Note that the memory info list doesn't seem to contain ranges in kernel space, + // so if you're walking a stack that has kernel frames, the stack may appear + // truncated. + error.SetErrorString("address is not in a known range"); + return error; +} + void ProcessWinMiniDump::Clear() {