[Lldb-commits] [lldb] r275778 - Implement GetMemoryRegions() for Windows Minidumps and live processes.

Howard Hellyer via lldb-commits lldb-commits at lists.llvm.org
Mon Jul 18 01:26:00 PDT 2016


Author: hhellyer
Date: Mon Jul 18 03:25:59 2016
New Revision: 275778

URL: http://llvm.org/viewvc/llvm-project?rev=275778&view=rev
Log:
Implement GetMemoryRegions() for Windows Minidumps and live processes.

Summary:
This patch fills in the implementation of GetMemoryRegions() on the Windows live process and minidump implementations of lldb_private::Process (ProcessWindowsLive::GetMemoryRegionInfo and ProcessWinMiniDump::Impl::GetMemoryRegionInfo.) The GetMemoryRegions API was added under: http://reviews.llvm.org/D20565

The existing Windows implementations didn’t fill in the start and end addresses within MemoryRegionInfo. This patch fixes that and adds support for the new mapped flag on MemoryRegionInfo that says whether a memory range is mapped into the process address space or not.

The behaviour of both live and core implementations should match the behaviour documented on Process::GetMemoryRegionInfo (in Process.h) which in turn should match the behaviour of the qMemoryRegionInfo query documented in lldb-gdb-remote.txt.

Reviewers: clayborg, amccarth

Subscribers: amccarth, lldb-commits

Differential Revision: https://reviews.llvm.org/D22352

Modified:
    lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
    lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp

Modified: lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp?rev=275778&r1=275777&r2=275778&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp Mon Jul 18 03:25:59 2016
@@ -748,6 +748,7 @@ ProcessWindowsLive::GetMemoryRegionInfo(
 {
     Error error;
     llvm::sys::ScopedLock lock(m_mutex);
+    info.Clear();
 
     if (!m_session_data)
     {
@@ -755,7 +756,6 @@ ProcessWindowsLive::GetMemoryRegionInfo(
         WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString());
         return error;
     }
-
     HostProcess process = m_session_data->m_debugger->GetProcess();
     lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
     if (handle == nullptr || handle == LLDB_INVALID_PROCESS)
@@ -772,22 +772,67 @@ ProcessWindowsLive::GetMemoryRegionInfo(
     SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
     if (result == 0)
     {
-        error.SetError(::GetLastError(), eErrorTypeWin32);
-        WINERR_IFALL(WINDOWS_LOG_MEMORY,
-                     "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x",
-                     error.GetError(), vm_addr);
-        return error;
+        if (::GetLastError() == ERROR_INVALID_PARAMETER)
+        {
+            // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an address
+            // past the highest accessible address. We should return a range from the vm_addr
+            // to LLDB_INVALID_ADDRESS
+            info.GetRange().SetRangeBase(vm_addr);
+            info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
+            info.SetReadable(MemoryRegionInfo::eNo);
+            info.SetExecutable(MemoryRegionInfo::eNo);
+            info.SetWritable(MemoryRegionInfo::eNo);
+            info.SetMapped(MemoryRegionInfo::eNo);
+            return error;
+        }
+        else
+        {
+            error.SetError(::GetLastError(), eErrorTypeWin32);
+            WINERR_IFALL(WINDOWS_LOG_MEMORY,
+                    "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x",
+                    error.GetError(), vm_addr);
+            return error;
+        }
+    }
+
+    // Protect bits are only valid for MEM_COMMIT regions.
+    if (mem_info.State == MEM_COMMIT) {
+        const bool readable = IsPageReadable(mem_info.Protect);
+        const bool executable = IsPageExecutable(mem_info.Protect);
+        const bool writable = IsPageWritable(mem_info.Protect);
+        info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
+        info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
+        info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
+    }
+    else
+    {
+        info.SetReadable(MemoryRegionInfo::eNo);
+        info.SetExecutable(MemoryRegionInfo::eNo);
+        info.SetWritable(MemoryRegionInfo::eNo);
+    }
+
+    // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
+    if (mem_info.State != MEM_FREE) {
+        info.GetRange().SetRangeBase(reinterpret_cast<addr_t>(mem_info.AllocationBase));
+        info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + mem_info.RegionSize);
+        info.SetMapped(MemoryRegionInfo::eYes);
+    }
+    else
+    {
+        // In the unmapped case we need to return the distance to the next block of memory.
+        // VirtualQueryEx nearly does that except that it gives the distance from the start
+        // of the page containing vm_addr.
+        SYSTEM_INFO data;
+        GetSystemInfo(&data);
+        DWORD page_offset = vm_addr % data.dwPageSize;
+        info.GetRange().SetRangeBase(vm_addr);
+        info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
+        info.SetMapped(MemoryRegionInfo::eNo);
     }
-    const bool readable = IsPageReadable(mem_info.Protect);
-    const bool executable = IsPageExecutable(mem_info.Protect);
-    const bool writable = IsPageWritable(mem_info.Protect);
-    info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
-    info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
-    info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
 
     error.SetError(::GetLastError(), eErrorTypeWin32);
     WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: readable=%s, executable=%s, writable=%s",
-                  BOOL_STR(readable), BOOL_STR(executable), BOOL_STR(writable));
+                  BOOL_STR(info.GetReadable()), BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable()));
     return error;
 }
 

Modified: lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp?rev=275778&r1=275777&r2=275778&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp Mon Jul 18 03:25:59 2016
@@ -277,6 +277,7 @@ ProcessWinMiniDump::Impl::GetMemoryRegio
 {
     Error error;
     size_t size;
+    info.Clear();
     const auto list = reinterpret_cast<const MINIDUMP_MEMORY_INFO_LIST *>(FindDumpStream(MemoryInfoListStream, &size));
     if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST))
     {
@@ -296,6 +297,8 @@ ProcessWinMiniDump::Impl::GetMemoryRegio
         return error;
     }
 
+    const MINIDUMP_MEMORY_INFO *next_entry = nullptr;
+
     for (int i = 0; i < list->NumberOfEntries; ++i)
     {
         const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO *>(reinterpret_cast<const char *>(list) +
@@ -304,16 +307,34 @@ ProcessWinMiniDump::Impl::GetMemoryRegio
         const auto tail = head + entry->RegionSize;
         if (head <= load_addr && load_addr < tail)
         {
+            info.GetRange().SetRangeBase((entry->State != MEM_FREE) ? head : load_addr);
+            info.GetRange().SetRangeEnd(tail);
             info.SetReadable(IsPageReadable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
             info.SetWritable(IsPageWritable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
             info.SetExecutable(IsPageExecutable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
+            info.SetMapped((entry->State != MEM_FREE) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
             return error;
         }
+        else if (head > load_addr && (next_entry == nullptr || head < next_entry->BaseAddress) )
+        {
+            // In case there is no region containing load_addr keep track of the nearest region
+            // after load_addr so we can return the distance to it.
+            next_entry = entry;
+        }
     }
+
+    // No containing region found. Create an unmapped region that extends to the next region
+    // or LLDB_INVALID_ADDRESS
+    info.GetRange().SetRangeBase(load_addr);
+    info.GetRange().SetRangeEnd((next_entry != nullptr)?next_entry->BaseAddress:LLDB_INVALID_ADDRESS);
+    info.SetReadable(MemoryRegionInfo::eNo);
+    info.SetWritable(MemoryRegionInfo::eNo);
+    info.SetExecutable(MemoryRegionInfo::eNo);
+    info.SetMapped(MemoryRegionInfo::eNo);
+
     // 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;
 }
 




More information about the lldb-commits mailing list