[Lldb-commits] [lldb] r246558 - Implement DoReadMemory for Windows mini dumps.

Adrian McCarthy via lldb-commits lldb-commits at lists.llvm.org
Tue Sep 1 09:59:31 PDT 2015


Author: amccarth
Date: Tue Sep  1 11:59:31 2015
New Revision: 246558

URL: http://llvm.org/viewvc/llvm-project?rev=246558&view=rev
Log:
Implement DoReadMemory for Windows mini dumps.
Differential Revision: http://reviews.llvm.org/D12507

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

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=246558&r1=246557&r2=246558&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp Tue Sep  1 11:59:31 2015
@@ -227,19 +227,42 @@ ProcessWinMiniDump::IsAlive()
     return true;
 }
 
+bool
+ProcessWinMiniDump::WarnBeforeDetach () const
+{
+    // Since this is post-mortem debugging, there's no need to warn the user
+    // that quitting the debugger will terminate the process.
+    return false;
+}
+
 size_t
 ProcessWinMiniDump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error)
 {
     // Don't allow the caching that lldb_private::Process::ReadMemory does
-    // since in core files we have it all cached our our core file anyway.
+    // since we have it all cached our our dump file anyway.
     return DoReadMemory(addr, buf, size, error);
 }
 
 size_t
 ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error)
 {
-    // TODO
-    return 0;
+    // I don't have a sense of how frequently this is called or how many memory
+    // ranges a mini dump typically has, so I'm not sure if searching for the
+    // appropriate range linearly each time is stupid.  Perhaps we should build
+    // an index for faster lookups.
+    Range range = {0};
+    if (!FindMemoryRange(addr, &range))
+    {
+        return 0;
+    }
+
+    // There's at least some overlap between the beginning of the desired range
+    // (addr) and the current range.  Figure out where the overlap begins and
+    // how much overlap there is, then copy it to the destination buffer.
+    const size_t offset = range.start - addr;
+    const size_t overlap = std::min(size, range.size - offset);
+    std::memcpy(buf, range.ptr + offset, overlap);
+    return overlap;
 }
 
 void
@@ -307,6 +330,54 @@ ProcessWinMiniDump::Data::~Data()
     }
 }
 
+bool
+ProcessWinMiniDump::FindMemoryRange(lldb::addr_t addr, Range *range_out) const
+{
+    size_t stream_size = 0;
+    auto mem_list_stream = static_cast<const MINIDUMP_MEMORY_LIST *>(FindDumpStream(MemoryListStream, &stream_size));
+    if (mem_list_stream)
+    {
+        for (ULONG32 i = 0; i < mem_list_stream->NumberOfMemoryRanges; ++i) {
+            const MINIDUMP_MEMORY_DESCRIPTOR &mem_desc = mem_list_stream->MemoryRanges[i];
+            const MINIDUMP_LOCATION_DESCRIPTOR &loc_desc = mem_desc.Memory;
+            const lldb::addr_t range_start = mem_desc.StartOfMemoryRange;
+            const size_t range_size = loc_desc.DataSize;
+            if (range_start <= addr && addr < range_start + range_size)
+            {
+                range_out->start = range_start;
+                range_out->size = range_size;
+                range_out->ptr = reinterpret_cast<const uint8_t *>(m_data_up->m_base_addr) + loc_desc.Rva;
+                return true;
+            }
+        }
+    }
+
+    // Some mini dumps have a Memory64ListStream that captures all the heap
+    // memory.  We can't exactly use the same loop as above, because the mini
+    // dump uses slightly different data structures to describe those.
+    auto mem_list64_stream = static_cast<const MINIDUMP_MEMORY64_LIST *>(FindDumpStream(Memory64ListStream, &stream_size));
+    if (mem_list64_stream)
+    {
+        size_t base_rva = mem_list64_stream->BaseRva;
+        for (ULONG32 i = 0; i < mem_list64_stream->NumberOfMemoryRanges; ++i) {
+            const MINIDUMP_MEMORY_DESCRIPTOR64 &mem_desc = mem_list64_stream->MemoryRanges[i];
+            const lldb::addr_t range_start = mem_desc.StartOfMemoryRange;
+            const size_t range_size = mem_desc.DataSize;
+            if (range_start <= addr && addr < range_start + range_size)
+            {
+                range_out->start = range_start;
+                range_out->size = range_size;
+                range_out->ptr = reinterpret_cast<const uint8_t *>(m_data_up->m_base_addr) + base_rva;
+                return true;
+            }
+            base_rva += range_size;
+        }
+    }
+
+    return false;
+}
+
+
 Error
 ProcessWinMiniDump::MapMiniDumpIntoMemory(const char *file)
 {
@@ -397,7 +468,8 @@ ProcessWinMiniDump::ReadModuleList() {
 }
 
 void *
-ProcessWinMiniDump::FindDumpStream(unsigned stream_number, size_t *size_out) {
+ProcessWinMiniDump::FindDumpStream(unsigned stream_number, size_t *size_out) const
+{
     void *stream = nullptr;
     *size_out = 0;
 

Modified: lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h?rev=246558&r1=246557&r2=246558&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h (original)
+++ lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h Tue Sep  1 11:59:31 2015
@@ -70,6 +70,9 @@ public:
     bool
     IsAlive() override;
 
+    bool
+    WarnBeforeDetach () const override;
+
     size_t
     ReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
 
@@ -91,6 +94,19 @@ protected:
                      lldb_private::ThreadList &new_thread_list) override;
 
 private:
+    // Describes a range of memory captured in the mini dump.
+    struct Range {
+      lldb::addr_t start;  // virtual address of the beginning of the range
+      size_t size;         // size of the range in bytes
+      const uint8_t *ptr;  // absolute pointer to the first byte of the range
+    };
+
+    // If the mini dump has a memory range that contains the desired address, it
+    // returns true with the details of the range in *range_out.  Otherwise, it
+    // returns false.
+    bool
+    FindMemoryRange(lldb::addr_t addr, Range *range_out) const;
+
     lldb_private::Error
     MapMiniDumpIntoMemory(const char *file);
 
@@ -107,7 +123,7 @@ private:
     // checks.  If there's a failure (e.g., if the requested stream doesn't exist),
     // the function returns nullptr and sets *size_out to 0.
     void *
-    FindDumpStream(unsigned stream_number, size_t *size_out);
+    FindDumpStream(unsigned stream_number, size_t *size_out) const;
 
     // Isolate the data to keep Windows-specific types out of this header.  Can't
     // use the typical pimpl idiom because the implementation of this class also




More information about the lldb-commits mailing list