amccarth created this revision.
amccarth added a reviewer: zturner.
amccarth added a subscriber: lldb-commits.

Also tweaked process save-core to include the memory info list so that we can 
see the regions in the list.

There are no commands or SBInterfaces yet that make it possible to test this 
directly, but I'll look for an opportunity to do so as I continue to work 
toward working backtraces from mini dumps.

http://reviews.llvm.org/D15218

Files:
  source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
  source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
  source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h

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<const MINIDUMP_MEMORY_INFO_LIST 
*>(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<const MINIDUMP_MEMORY_INFO 
*>(reinterpret_cast<const char *>(list) + list->SizeOfHeader);
+
+    for (int i = 0; i < list->NumberOfEntries; ++i)
+    {
+        const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO 
*>(reinterpret_cast<const char *>(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()
 {
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<const MINIDUMP_MEMORY_INFO_LIST *>(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<const MINIDUMP_MEMORY_INFO *>(reinterpret_cast<const char *>(list) + list->SizeOfHeader);
+
+    for (int i = 0; i < list->NumberOfEntries; ++i)
+    {
+        const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO *>(reinterpret_cast<const char *>(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()
 {
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)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to