https://git.reactos.org/?p=reactos.git;a=commitdiff;h=34d40a5f3d90373e40fb5418f99046dce3ff9528

commit 34d40a5f3d90373e40fb5418f99046dce3ff9528
Author:     winesync <[email protected]>
AuthorDate: Fri Sep 11 15:55:33 2020 +0200
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Wed Sep 16 10:35:40 2020 +0200

    [WINESYNC] dbghelp: Support full memory dumps.
    
    Add support of flag MinidumpWithFullMemory in function
    MinidumpWriteDump. A Memory64ListStream is added to the minidump
    streams and all memory regions of the process with MEM_COMMIT state
    are written to the last part of the minidump file.
    
    Signed-off-by: Eric Bissonnette <[email protected]>
    Signed-off-by: Alexandre Julliard <[email protected]>
    
    wine commit id b90bbcbe750f6af0ce13f2577984f4818e05a013 by Eric Bissonnette 
<[email protected]>
---
 dll/win32/dbghelp/dbghelp_private.h |   9 +++
 dll/win32/dbghelp/minidump.c        | 129 ++++++++++++++++++++++++++++++++++--
 sdk/include/psdk/dbghelp.h          |  13 ++++
 sdk/tools/winesync/dbghelp.cfg      |   2 +-
 4 files changed, 145 insertions(+), 8 deletions(-)

diff --git a/dll/win32/dbghelp/dbghelp_private.h 
b/dll/win32/dbghelp/dbghelp_private.h
index 2138bd65154..565399ebcc1 100644
--- a/dll/win32/dbghelp/dbghelp_private.h
+++ b/dll/win32/dbghelp/dbghelp_private.h
@@ -500,6 +500,12 @@ struct dump_memory
     ULONG                               rva;
 };
 
+struct dump_memory64
+{
+    ULONG64                             base;
+    ULONG64                             size;
+};
+
 struct dump_module
 {
     unsigned                            is_elf;
@@ -538,6 +544,9 @@ struct dump_context
     struct dump_memory*                 mem;
     unsigned                            num_mem;
     unsigned                            alloc_mem;
+    struct dump_memory64*               mem64;
+    unsigned                            num_mem64;
+    unsigned                            alloc_mem64;
     /* callback information */
     MINIDUMP_CALLBACK_INFORMATION*      cb;
 };
diff --git a/dll/win32/dbghelp/minidump.c b/dll/win32/dbghelp/minidump.c
index f72177e6d2d..4e2c7641c9d 100644
--- a/dll/win32/dbghelp/minidump.c
+++ b/dll/win32/dbghelp/minidump.c
@@ -294,6 +294,49 @@ static BOOL fetch_macho_module_info_cb(const WCHAR* name, 
unsigned long base,
     return TRUE;
 }
 
+void minidump_add_memory64_block(struct dump_context* dc, ULONG64 base, 
ULONG64 size)
+{
+    if (!dc->mem64)
+    {
+        dc->alloc_mem64 = 32;
+        dc->mem64 = HeapAlloc(GetProcessHeap(), 0, dc->alloc_mem64 * 
sizeof(*dc->mem64));
+    }
+    else if (dc->num_mem64 >= dc->alloc_mem64)
+    {
+        dc->alloc_mem64 *= 2;
+        dc->mem64 = HeapReAlloc(GetProcessHeap(), 0, dc->mem64,
+                                dc->alloc_mem64 * sizeof(*dc->mem64));
+    }
+    if (dc->mem64)
+    {
+        dc->mem64[dc->num_mem64].base = base;
+        dc->mem64[dc->num_mem64].size = size;
+        dc->num_mem64++;
+    }
+    else dc->num_mem64 = dc->alloc_mem64 = 0;
+}
+
+static void fetch_memory64_info(struct dump_context* dc)
+{
+    ULONG_PTR                   addr;
+    MEMORY_BASIC_INFORMATION    mbi;
+
+    addr = 0;
+    while (VirtualQueryEx(dc->hProcess, (LPCVOID)addr, &mbi, sizeof(mbi)) != 0)
+    {
+        /* Memory regions with state MEM_COMMIT will be added to the dump */
+        if (mbi.State == MEM_COMMIT)
+        {
+            minidump_add_memory64_block(dc, (ULONG_PTR)mbi.BaseAddress, 
mbi.RegionSize);
+        }
+
+        if ((addr + mbi.RegionSize) < addr)
+            break;
+
+        addr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
+    }
+}
+
 static void fetch_modules_info(struct dump_context* dc)
 {
     EnumerateLoadedModulesW64(dc->hProcess, fetch_pe_module_info_cb, dc);
@@ -853,6 +896,60 @@ static unsigned         dump_memory_info(struct 
dump_context* dc)
     return sz;
 }
 
+/******************************************************************
+ *             dump_memory64_info
+ *
+ * dumps information about the memory of the process (virtual memory)
+ */
+static unsigned         dump_memory64_info(struct dump_context* dc)
+{
+    MINIDUMP_MEMORY64_LIST          mdMem64List;
+    MINIDUMP_MEMORY_DESCRIPTOR64    mdMem64;
+    DWORD                           written;
+    unsigned                        i, len, sz;
+    RVA                             rva_base;
+    char                            tmp[1024];
+    ULONG64                         pos;
+    LARGE_INTEGER                   filepos;
+
+    sz = sizeof(mdMem64List.NumberOfMemoryRanges) +
+            sizeof(mdMem64List.BaseRva) +
+            dc->num_mem64 * sizeof(mdMem64);
+
+    mdMem64List.NumberOfMemoryRanges = dc->num_mem64;
+    mdMem64List.BaseRva = dc->rva + sz;
+
+    append(dc, &mdMem64List.NumberOfMemoryRanges,
+           sizeof(mdMem64List.NumberOfMemoryRanges));
+    append(dc, &mdMem64List.BaseRva,
+           sizeof(mdMem64List.BaseRva));
+
+    rva_base = dc->rva;
+    dc->rva += dc->num_mem64 * sizeof(mdMem64);
+
+    /* dc->rva is not updated past this point. The end of the dump
+     * is just the full memory data. */
+    filepos.QuadPart = dc->rva;
+    for (i = 0; i < dc->num_mem64; i++)
+    {
+        mdMem64.StartOfMemoryRange = dc->mem64[i].base;
+        mdMem64.DataSize = dc->mem64[i].size;
+        SetFilePointerEx(dc->hFile, filepos, NULL, FILE_BEGIN);
+        for (pos = 0; pos < dc->mem64[i].size; pos += sizeof(tmp))
+        {
+            len = min(dc->mem64[i].size - pos, sizeof(tmp));
+            if (ReadProcessMemory(dc->hProcess,
+                                  (void*)(ULONG_PTR)(dc->mem64[i].base + pos),
+                                  tmp, len, NULL))
+                WriteFile(dc->hFile, tmp, len, &written, NULL);
+        }
+        filepos.QuadPart += mdMem64.DataSize;
+        writeat(dc, rva_base + i * sizeof(mdMem64), &mdMem64, sizeof(mdMem64));
+    }
+
+    return sz;
+}
+
 static unsigned         dump_misc_info(struct dump_context* dc)
 {
     MINIDUMP_MISC_INFO  mmi;
@@ -898,6 +995,9 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, 
HANDLE hFile,
     dc.mem = NULL;
     dc.num_mem = 0;
     dc.alloc_mem = 0;
+    dc.mem64 = NULL;
+    dc.num_mem64 = 0;
+    dc.alloc_mem64 = 0;
     dc.rva = 0;
 
     if (!fetch_process_info(&dc)) return FALSE;
@@ -912,8 +1012,6 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, 
HANDLE hFile,
 
     if (DumpType & MiniDumpWithDataSegs)
         FIXME("NIY MiniDumpWithDataSegs\n");
-    if (DumpType & MiniDumpWithFullMemory)
-        FIXME("NIY MiniDumpWithFullMemory\n");
     if (DumpType & MiniDumpWithHandleData)
         FIXME("NIY MiniDumpWithHandleData\n");
     if (DumpType & MiniDumpFilterMemory)
@@ -962,11 +1060,15 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD 
pid, HANDLE hFile,
     writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
             &mdDir, sizeof(mdDir));
 
-    mdDir.StreamType = MemoryListStream;
-    mdDir.Location.Rva = dc.rva;
-    mdDir.Location.DataSize = dump_memory_info(&dc);
-    writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
-            &mdDir, sizeof(mdDir));
+
+    if (!(DumpType & MiniDumpWithFullMemory))
+    {
+        mdDir.StreamType = MemoryListStream;
+        mdDir.Location.Rva = dc.rva;
+        mdDir.Location.DataSize = dump_memory_info(&dc);
+        writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+                &mdDir, sizeof(mdDir));
+    }
 
     mdDir.StreamType = MiscInfoStream;
     mdDir.Location.Rva = dc.rva;
@@ -999,12 +1101,25 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD 
pid, HANDLE hFile,
         }
     }
 
+    /* 3.4) write full memory (if requested) */
+    if (DumpType & MiniDumpWithFullMemory)
+    {
+        fetch_memory64_info(&dc);
+
+        mdDir.StreamType = Memory64ListStream;
+        mdDir.Location.Rva = dc.rva;
+        mdDir.Location.DataSize = dump_memory64_info(&dc);
+        writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+                &mdDir, sizeof(mdDir));
+    }
+
     /* fill the remaining directory entries with 0's (unused stream types) */
     /* NOTE: this should always come last in the dump! */
     for (i = idx_stream; i < nStreams; i++)
         writeat(&dc, mdHead.StreamDirectoryRva + i * sizeof(emptyDir), 
&emptyDir, sizeof(emptyDir));
 
     HeapFree(GetProcessHeap(), 0, dc.mem);
+    HeapFree(GetProcessHeap(), 0, dc.mem64);
     HeapFree(GetProcessHeap(), 0, dc.modules);
     HeapFree(GetProcessHeap(), 0, dc.threads);
 
diff --git a/sdk/include/psdk/dbghelp.h b/sdk/include/psdk/dbghelp.h
index aa0cdff1c69..5da7c94e574 100644
--- a/sdk/include/psdk/dbghelp.h
+++ b/sdk/include/psdk/dbghelp.h
@@ -807,6 +807,19 @@ typedef struct _MINIDUMP_MEMORY_LIST
     MINIDUMP_MEMORY_DESCRIPTOR  MemoryRanges[1]; /* FIXME: 0-sized array not 
supported */
 } MINIDUMP_MEMORY_LIST, *PMINIDUMP_MEMORY_LIST;
 
+typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64
+{
+    ULONG64                     StartOfMemoryRange;
+    ULONG64                     DataSize;
+} MINIDUMP_MEMORY_DESCRIPTOR64, *PMINIDUMP_MEMORY_DESCRIPTOR64;
+
+typedef struct _MINIDUMP_MEMORY64_LIST
+{
+    ULONG64                     NumberOfMemoryRanges;
+    RVA64                       BaseRva;
+    MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges[1]; /* FIXME: 0-sized array not 
supported */
+} MINIDUMP_MEMORY64_LIST, *PMINIDUMP_MEMORY64_LIST;
+
 #define MINIDUMP_MISC1_PROCESS_ID       0x00000001
 #define MINIDUMP_MISC1_PROCESS_TIMES    0x00000002
 
diff --git a/sdk/tools/winesync/dbghelp.cfg b/sdk/tools/winesync/dbghelp.cfg
index 5b1c15a7d2a..97e98a51f55 100644
--- a/sdk/tools/winesync/dbghelp.cfg
+++ b/sdk/tools/winesync/dbghelp.cfg
@@ -4,4 +4,4 @@ files:
   include/dbghelp.h: sdk/include/psdk/dbghelp.h
   include/wine/mscvpdb.h: sdk/include/reactos/wine/mscvpdb.h
 tags:
-  wine: edcff4046c5aa70c047c1a523a93a5cc5782fb44
+  wine: b90bbcbe750f6af0ce13f2577984f4818e05a013

Reply via email to