ReactOS 0.4.15-dev-8116-gf69e256
minidump.c File Reference
#include <time.h>
#include "ntstatus.h"
#include "dbghelp_private.h"
#include "winternl.h"
#include "psapi.h"
#include "wine/asm.h"
#include "wine/debug.h"
Include dependency graph for minidump.c:

Go to the source code of this file.

Macros

#define NONAMELESSUNION
 
#define NONAMELESSSTRUCT
 
#define WIN32_NO_STATUS
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (dbghelp)
 
static BOOL fetch_process_info (struct dump_context *dc)
 
static void fetch_thread_stack (struct dump_context *dc, const void *teb_addr, const CONTEXT *ctx, MINIDUMP_MEMORY_DESCRIPTOR *mmd)
 
static BOOL fetch_thread_info (struct dump_context *dc, int thd_idx, const MINIDUMP_EXCEPTION_INFORMATION *except, MINIDUMP_THREAD *mdThd, CONTEXT *ctx)
 
static BOOL add_module (struct dump_context *dc, const WCHAR *name, DWORD64 base, DWORD size, DWORD timestamp, DWORD checksum, BOOL is_elf)
 
static BOOL WINAPI fetch_pe_module_info_cb (PCWSTR name, DWORD64 base, ULONG size, PVOID user)
 
static BOOL fetch_host_module_info_cb (const WCHAR *name, ULONG_PTR base, void *user)
 
static void minidump_add_memory64_block (struct dump_context *dc, ULONG64 base, ULONG64 size)
 
static void fetch_memory64_info (struct dump_context *dc)
 
static void fetch_modules_info (struct dump_context *dc)
 
static void fetch_module_versioninfo (LPCWSTR filename, VS_FIXEDFILEINFO *ffi)
 
void minidump_add_memory_block (struct dump_context *dc, ULONG64 base, ULONG size, ULONG rva)
 
static void writeat (struct dump_context *dc, RVA rva, const void *data, unsigned size)
 
static void append (struct dump_context *dc, const void *data, unsigned size)
 
static unsigned dump_exception_info (struct dump_context *dc, const MINIDUMP_EXCEPTION_INFORMATION *except)
 
static unsigned dump_modules (struct dump_context *dc, BOOL dump_elf)
 
static void do_x86cpuid (unsigned int ax, unsigned int *p)
 
static int have_x86cpuid (void)
 
static unsigned dump_system_info (struct dump_context *dc)
 
static unsigned dump_threads (struct dump_context *dc, const MINIDUMP_EXCEPTION_INFORMATION *except)
 
static unsigned dump_memory_info (struct dump_context *dc)
 
static unsigned dump_memory64_info (struct dump_context *dc)
 
static unsigned dump_misc_info (struct dump_context *dc)
 
BOOL WINAPI MiniDumpWriteDump (HANDLE hProcess, DWORD pid, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam)
 
BOOL WINAPI MiniDumpReadDumpStream (PVOID base, ULONG str_idx, PMINIDUMP_DIRECTORY *pdir, PVOID *stream, ULONG *size)
 

Macro Definition Documentation

◆ NONAMELESSSTRUCT

#define NONAMELESSSTRUCT

Definition at line 24 of file minidump.c.

◆ NONAMELESSUNION

#define NONAMELESSUNION

Definition at line 23 of file minidump.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 27 of file minidump.c.

Function Documentation

◆ add_module()

static BOOL add_module ( struct dump_context dc,
const WCHAR name,
DWORD64  base,
DWORD  size,
DWORD  timestamp,
DWORD  checksum,
BOOL  is_elf 
)
static

Definition at line 195 of file minidump.c.

198{
199 if (!dc->modules)
200 {
201 dc->alloc_modules = 32;
202 dc->modules = HeapAlloc(GetProcessHeap(), 0,
203 dc->alloc_modules * sizeof(*dc->modules));
204 }
205 else if(dc->num_modules >= dc->alloc_modules)
206 {
207 dc->alloc_modules *= 2;
208 dc->modules = HeapReAlloc(GetProcessHeap(), 0, dc->modules,
209 dc->alloc_modules * sizeof(*dc->modules));
210 }
211 if (!dc->modules)
212 {
213 dc->alloc_modules = dc->num_modules = 0;
214 return FALSE;
215 }
216 if (is_elf ||
217 !GetModuleFileNameExW(dc->process->handle, (HMODULE)(DWORD_PTR)base,
218 dc->modules[dc->num_modules].name,
219 ARRAY_SIZE(dc->modules[dc->num_modules].name)))
220 lstrcpynW(dc->modules[dc->num_modules].name, name,
221 ARRAY_SIZE(dc->modules[dc->num_modules].name));
222 dc->modules[dc->num_modules].base = base;
223 dc->modules[dc->num_modules].size = size;
224 dc->modules[dc->num_modules].timestamp = timestamp;
225 dc->modules[dc->num_modules].checksum = checksum;
226 dc->modules[dc->num_modules].is_elf = is_elf;
227 dc->num_modules++;
228
229 return TRUE;
230}
#define ARRAY_SIZE(A)
Definition: main.h:33
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
#define GetProcessHeap()
Definition: compat.h:736
#define GetModuleFileNameExW(w, x, y, z)
Definition: compat.h:922
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define lstrcpynW
Definition: compat.h:738
GLsizeiptr size
Definition: glext.h:5919
static const WCHAR dc[]
Definition: name.c:39
uint32_t DWORD_PTR
Definition: typedefs.h:65

Referenced by fetch_host_module_info_cb(), and fetch_pe_module_info_cb().

◆ append()

static void append ( struct dump_context dc,
const void data,
unsigned  size 
)
static

Definition at line 397 of file minidump.c.

398{
399 writeat(dc, dc->rva, data, size);
400 dc->rva += size;
401}
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static void writeat(struct dump_context *dc, RVA rva, const void *data, unsigned size)
Definition: minidump.c:383

Referenced by _tcscat(), copy(), debugcontrol_GetLogFile(), debugcontrol_OpenLogFile(), DECLARE_INTERFACE_(), dump_exception_info(), dump_memory64_info(), dump_memory_info(), dump_misc_info(), dump_modules(), dump_system_info(), dump_threads(), ME_AppendString(), MiniDumpWriteDump(), Subdivider::monotonize(), SynthPortImpl_IDirectMusicPortDownload_GetAppend(), zipOpen(), zipOpen2(), zipOpen2_64(), zipOpen3(), and zipOpen64().

◆ do_x86cpuid()

static void do_x86cpuid ( unsigned int  ax,
unsigned int p 
)
static

Definition at line 613 of file minidump.c.

614{
615}

Referenced by dump_system_info().

◆ dump_exception_info()

static unsigned dump_exception_info ( struct dump_context dc,
const MINIDUMP_EXCEPTION_INFORMATION except 
)
static

Definition at line 408 of file minidump.c.

410{
412 EXCEPTION_RECORD rec, *prec;
413 CONTEXT ctx, *pctx;
414 DWORD i;
415
416 mdExcpt.ThreadId = except->ThreadId;
417 mdExcpt.__alignment = 0;
418 if (except->ClientPointers)
419 {
421
422 ReadProcessMemory(dc->process->handle,
423 except->ExceptionPointers, &ep, sizeof(ep), NULL);
424 ReadProcessMemory(dc->process->handle,
425 ep.ExceptionRecord, &rec, sizeof(rec), NULL);
426 ReadProcessMemory(dc->process->handle,
427 ep.ContextRecord, &ctx, sizeof(ctx), NULL);
428 prec = &rec;
429 pctx = &ctx;
430 }
431 else
432 {
433 prec = except->ExceptionPointers->ExceptionRecord;
434 pctx = except->ExceptionPointers->ContextRecord;
435 }
442 for (i = 0; i < mdExcpt.ExceptionRecord.NumberParameters; i++)
444 mdExcpt.ThreadContext.DataSize = sizeof(*pctx);
445 mdExcpt.ThreadContext.Rva = dc->rva + sizeof(mdExcpt);
446
447 append(dc, &mdExcpt, sizeof(mdExcpt));
448 append(dc, pctx, sizeof(*pctx));
449 return sizeof(mdExcpt);
450}
#define except(x)
Definition: btrfs_drv.h:136
#define NULL
Definition: types.h:112
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:758
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void append(struct dump_context *dc, const void *data, unsigned size)
Definition: minidump.c:397
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext
Definition: dbghelp.h:783
MINIDUMP_EXCEPTION ExceptionRecord
Definition: dbghelp.h:782
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
PCONTEXT ContextRecord
Definition: rtltypes.h:201
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
DWORD ExceptionCode
Definition: compat.h:208
DWORD NumberParameters
Definition: compat.h:212
DWORD ExceptionFlags
Definition: compat.h:209
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
PVOID ExceptionAddress
Definition: compat.h:211
ULONG64 ExceptionRecord
Definition: dbghelp.h:764
ULONG __unusedAlignment
Definition: dbghelp.h:767
ULONG ExceptionFlags
Definition: dbghelp.h:763
ULONG NumberParameters
Definition: dbghelp.h:766
ULONG64 ExceptionAddress
Definition: dbghelp.h:765
ULONG64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: dbghelp.h:768
#define DWORD_PTR
Definition: treelist.c:76

Referenced by MiniDumpWriteDump().

◆ dump_memory64_info()

static unsigned dump_memory64_info ( struct dump_context dc)
static

Definition at line 875 of file minidump.c.

876{
877 MINIDUMP_MEMORY64_LIST mdMem64List;
879 DWORD written;
880 unsigned i, len, sz;
881 RVA rva_base;
882 char tmp[1024];
883 ULONG64 pos;
884 LARGE_INTEGER filepos;
885
886 sz = sizeof(mdMem64List.NumberOfMemoryRanges) +
887 sizeof(mdMem64List.BaseRva) +
888 dc->num_mem64 * sizeof(mdMem64);
889
890 mdMem64List.NumberOfMemoryRanges = dc->num_mem64;
891 mdMem64List.BaseRva = dc->rva + sz;
892
893 append(dc, &mdMem64List.NumberOfMemoryRanges,
894 sizeof(mdMem64List.NumberOfMemoryRanges));
895 append(dc, &mdMem64List.BaseRva,
896 sizeof(mdMem64List.BaseRva));
897
898 rva_base = dc->rva;
899 dc->rva += dc->num_mem64 * sizeof(mdMem64);
900
901 /* dc->rva is not updated past this point. The end of the dump
902 * is just the full memory data. */
903 filepos.QuadPart = dc->rva;
904 for (i = 0; i < dc->num_mem64; i++)
905 {
906 mdMem64.StartOfMemoryRange = dc->mem64[i].base;
907 mdMem64.DataSize = dc->mem64[i].size;
908 SetFilePointerEx(dc->hFile, filepos, NULL, FILE_BEGIN);
909 for (pos = 0; pos < dc->mem64[i].size; pos += sizeof(tmp))
910 {
911 len = min(dc->mem64[i].size - pos, sizeof(tmp));
912 if (read_process_memory(dc->process, dc->mem64[i].base + pos, tmp, len))
913 WriteFile(dc->hFile, tmp, len, &written, NULL);
914 }
915 filepos.QuadPart += mdMem64.DataSize;
916 writeat(dc, rva_base + i * sizeof(mdMem64), &mdMem64, sizeof(mdMem64));
917 }
918
919 return sz;
920}
static BOOL read_process_memory(const struct process *process, UINT64 addr, void *buf, size_t size)
#define FILE_BEGIN
Definition: compat.h:761
DWORD RVA
Definition: compat.h:1262
BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
Definition: fileinfo.c:177
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
GLenum GLsizei len
Definition: glext.h:6722
unsigned __int64 ULONG64
Definition: imports.h:198
#define min(a, b)
Definition: monoChain.cc:55
ULONG64 NumberOfMemoryRanges
Definition: dbghelp.h:821
LONGLONG QuadPart
Definition: typedefs.h:114

Referenced by MiniDumpWriteDump().

◆ dump_memory_info()

static unsigned dump_memory_info ( struct dump_context dc)
static

Definition at line 830 of file minidump.c.

831{
832 MINIDUMP_MEMORY_LIST mdMemList;
834 DWORD written;
835 unsigned i, pos, len, sz;
836 RVA rva_base;
837 char tmp[1024];
838
839 mdMemList.NumberOfMemoryRanges = dc->num_mem;
840 append(dc, &mdMemList.NumberOfMemoryRanges,
841 sizeof(mdMemList.NumberOfMemoryRanges));
842 rva_base = dc->rva;
843 sz = mdMemList.NumberOfMemoryRanges * sizeof(mdMem);
844 dc->rva += sz;
845 sz += sizeof(mdMemList.NumberOfMemoryRanges);
846
847 for (i = 0; i < dc->num_mem; i++)
848 {
849 mdMem.StartOfMemoryRange = dc->mem[i].base;
850 mdMem.Memory.Rva = dc->rva;
851 mdMem.Memory.DataSize = dc->mem[i].size;
852 SetFilePointer(dc->hFile, dc->rva, NULL, FILE_BEGIN);
853 for (pos = 0; pos < dc->mem[i].size; pos += sizeof(tmp))
854 {
855 len = min(dc->mem[i].size - pos, sizeof(tmp));
856 if (read_process_memory(dc->process, dc->mem[i].base + pos, tmp, len))
857 WriteFile(dc->hFile, tmp, len, &written, NULL);
858 }
859 dc->rva += mdMem.Memory.DataSize;
860 writeat(dc, rva_base + i * sizeof(mdMem), &mdMem, sizeof(mdMem));
861 if (dc->mem[i].rva)
862 {
863 writeat(dc, dc->mem[i].rva, &mdMem.Memory.Rva, sizeof(mdMem.Memory.Rva));
864 }
865 }
866
867 return sz;
868}
#define SetFilePointer
Definition: compat.h:743
MINIDUMP_LOCATION_DESCRIPTOR Memory
Definition: dbghelp.h:804
ULONG NumberOfMemoryRanges
Definition: dbghelp.h:809

Referenced by MiniDumpWriteDump().

◆ dump_misc_info()

static unsigned dump_misc_info ( struct dump_context dc)
static

Definition at line 922 of file minidump.c.

923{
925
926 mmi.SizeOfInfo = sizeof(mmi);
928 mmi.ProcessId = dc->pid;
929 /* FIXME: create/user/kernel time */
930 mmi.ProcessCreateTime = 0;
931 mmi.ProcessKernelTime = 0;
932 mmi.ProcessUserTime = 0;
933
934 append(dc, &mmi, sizeof(mmi));
935 return sizeof(mmi);
936}
#define MINIDUMP_MISC1_PROCESS_ID
Definition: dbghelp.h:826
ULONG ProcessCreateTime
Definition: dbghelp.h:834
ULONG ProcessUserTime
Definition: dbghelp.h:835
ULONG ProcessKernelTime
Definition: dbghelp.h:836

Referenced by MiniDumpWriteDump().

◆ dump_modules()

static unsigned dump_modules ( struct dump_context dc,
BOOL  dump_elf 
)
static

Definition at line 457 of file minidump.c.

458{
460 MINIDUMP_MODULE_LIST mdModuleList;
461 char tmp[1024];
463 ULONG i, nmod;
464 RVA rva_base;
465 DWORD flags_out;
466 unsigned sz;
467
468 for (i = nmod = 0; i < dc->num_modules; i++)
469 {
470 if ((dc->modules[i].is_elf && dump_elf) ||
471 (!dc->modules[i].is_elf && !dump_elf))
472 nmod++;
473 }
474
475 mdModuleList.NumberOfModules = 0;
476 /* reserve space for mdModuleList
477 * FIXME: since we don't support 0 length arrays, we cannot use the
478 * size of mdModuleList
479 * FIXME: if we don't ask for all modules in cb, we'll get a hole in the file
480 */
481
482 /* the stream size is just the size of the module index. It does not include the data for the
483 names of each module. *Technically* the names are supposed to go into the common string table
484 in the minidump file. Since each string is referenced by RVA they can all safely be located
485 anywhere between streams in the file, so the end of this stream is sufficient. */
486 rva_base = dc->rva;
487 dc->rva += sz = sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod;
488 for (i = 0; i < dc->num_modules; i++)
489 {
490 if ((dc->modules[i].is_elf && !dump_elf) ||
491 (!dc->modules[i].is_elf && dump_elf))
492 continue;
493
495 if (dc->type & MiniDumpWithDataSegs)
496 flags_out |= ModuleWriteDataSeg;
498 flags_out |= ModuleWriteTlsData;
499 if (dc->type & MiniDumpWithCodeSegs)
500 flags_out |= ModuleWriteCodeSegs;
501 ms->Length = (lstrlenW(dc->modules[i].name) + 1) * sizeof(WCHAR);
502 if (sizeof(ULONG) + ms->Length > sizeof(tmp))
503 FIXME("Buffer overflow!!!\n");
504 lstrcpyW(ms->Buffer, dc->modules[i].name);
505
506 if (dc->cb)
507 {
510
511 cbin.ProcessId = dc->pid;
512 cbin.ProcessHandle = dc->process->handle;
514
515 cbin.u.Module.FullPath = ms->Buffer;
516 cbin.u.Module.BaseOfImage = dc->modules[i].base;
517 cbin.u.Module.SizeOfImage = dc->modules[i].size;
518 cbin.u.Module.CheckSum = dc->modules[i].checksum;
519 cbin.u.Module.TimeDateStamp = dc->modules[i].timestamp;
520 memset(&cbin.u.Module.VersionInfo, 0, sizeof(cbin.u.Module.VersionInfo));
521 cbin.u.Module.CvRecord = NULL;
522 cbin.u.Module.SizeOfCvRecord = 0;
523 cbin.u.Module.MiscRecord = NULL;
524 cbin.u.Module.SizeOfMiscRecord = 0;
525
526 cbout.u.ModuleWriteFlags = flags_out;
527 if (!dc->cb->CallbackRoutine(dc->cb->CallbackParam, &cbin, &cbout))
528 continue;
529 flags_out &= cbout.u.ModuleWriteFlags;
530 }
531 if (flags_out & ModuleWriteModule)
532 {
533 /* fetch CPU dependent module info (like UNWIND_INFO) */
534 dbghelp_current_cpu->fetch_minidump_module(dc, i, flags_out);
535
536 mdModule.BaseOfImage = dc->modules[i].base;
537 mdModule.SizeOfImage = dc->modules[i].size;
538 mdModule.CheckSum = dc->modules[i].checksum;
539 mdModule.TimeDateStamp = dc->modules[i].timestamp;
540 mdModule.ModuleNameRva = dc->rva;
541 ms->Length -= sizeof(WCHAR);
542 append(dc, ms, sizeof(ULONG) + ms->Length + sizeof(WCHAR));
543 fetch_module_versioninfo(ms->Buffer, &mdModule.VersionInfo);
544 mdModule.CvRecord.DataSize = 0; /* FIXME */
545 mdModule.CvRecord.Rva = 0; /* FIXME */
546 mdModule.MiscRecord.DataSize = 0; /* FIXME */
547 mdModule.MiscRecord.Rva = 0; /* FIXME */
548 mdModule.Reserved0 = 0; /* FIXME */
549 mdModule.Reserved1 = 0; /* FIXME */
550 writeat(dc,
551 rva_base + sizeof(mdModuleList.NumberOfModules) +
552 mdModuleList.NumberOfModules++ * sizeof(mdModule),
553 &mdModule, sizeof(mdModule));
554 }
555 }
556 writeat(dc, rva_base, &mdModuleList.NumberOfModules,
557 sizeof(mdModuleList.NumberOfModules));
558
559 return sz;
560}
#define FIXME(fmt,...)
Definition: debug.h:114
mdToken mdModule
Definition: cordebug.idl:72
@ ModuleCallback
Definition: dbghelp.h:625
@ ModuleWriteDataSeg
Definition: dbghelp.h:693
@ ModuleWriteMiscRecord
Definition: dbghelp.h:694
@ ModuleWriteCodeSegs
Definition: dbghelp.h:698
@ ModuleWriteCvRecord
Definition: dbghelp.h:695
@ ModuleWriteTlsData
Definition: dbghelp.h:697
@ ModuleWriteModule
Definition: dbghelp.h:692
@ MiniDumpWithCodeSegs
Definition: compat.h:1280
@ MiniDumpWithDataSegs
Definition: compat.h:1267
@ MiniDumpWithProcessThreadData
Definition: compat.h:1275
#define lstrcpyW
Definition: compat.h:749
#define lstrlenW
Definition: compat.h:750
struct cpu * dbghelp_current_cpu
Definition: dbghelp.c:169
static void fetch_module_versioninfo(LPCWSTR filename, VS_FIXEDFILEINFO *ffi)
Definition: minidump.c:325
#define memset(x, y, z)
Definition: compat.h:39
MINIDUMP_MODULE_CALLBACK Module
Definition: compat.h:1332
VS_FIXEDFILEINFO VersionInfo
Definition: compat.h:1309
WCHAR Buffer[1]
Definition: dbghelp.h:862
uint32_t ULONG
Definition: typedefs.h:59
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by MiniDumpWriteDump().

◆ dump_system_info()

static unsigned dump_system_info ( struct dump_context dc)
static

Definition at line 628 of file minidump.c.

629{
630 MINIDUMP_SYSTEM_INFO mdSysInfo;
631 SYSTEM_INFO sysInfo;
632 OSVERSIONINFOW osInfo;
633 DWORD written;
634 ULONG slen;
635 DWORD wine_extra = 0;
636
637 const char *(CDECL *wine_get_build_id)(void);
638 void (CDECL *wine_get_host_version)(const char **sysname, const char **release);
639 const char* build_id = NULL;
640 const char* sys_name = NULL;
641 const char* release_name = NULL;
642
643 GetSystemInfo(&sysInfo);
644 osInfo.dwOSVersionInfoSize = sizeof(osInfo);
645 GetVersionExW(&osInfo);
646
647 wine_get_build_id = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_build_id");
648 wine_get_host_version = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_host_version");
649 if (wine_get_build_id && wine_get_host_version)
650 {
651 /* cheat minidump system information by adding specific wine information */
652 wine_extra = 4 + 4 * sizeof(slen);
653 build_id = wine_get_build_id();
654 wine_get_host_version(&sys_name, &release_name);
655 wine_extra += strlen(build_id) + 1 + strlen(sys_name) + 1 + strlen(release_name) + 1;
656 }
657
658 mdSysInfo.ProcessorArchitecture = sysInfo.u.s.wProcessorArchitecture;
659 mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel;
660 mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision;
661 mdSysInfo.u.s.NumberOfProcessors = sysInfo.dwNumberOfProcessors;
662 mdSysInfo.u.s.ProductType = VER_NT_WORKSTATION; /* FIXME */
663 mdSysInfo.MajorVersion = osInfo.dwMajorVersion;
664 mdSysInfo.MinorVersion = osInfo.dwMinorVersion;
665 mdSysInfo.BuildNumber = osInfo.dwBuildNumber;
666 mdSysInfo.PlatformId = osInfo.dwPlatformId;
667
668 mdSysInfo.CSDVersionRva = dc->rva + sizeof(mdSysInfo) + wine_extra;
669 mdSysInfo.u1.Reserved1 = 0;
670 mdSysInfo.u1.s.SuiteMask = VER_SUITE_TERMINAL;
671
672 if (have_x86cpuid())
673 {
674 unsigned regs0[4], regs1[4];
675
676 do_x86cpuid(0, regs0);
677 mdSysInfo.Cpu.X86CpuInfo.VendorId[0] = regs0[1];
678 mdSysInfo.Cpu.X86CpuInfo.VendorId[1] = regs0[3];
679 mdSysInfo.Cpu.X86CpuInfo.VendorId[2] = regs0[2];
680 do_x86cpuid(1, regs1);
681 mdSysInfo.Cpu.X86CpuInfo.VersionInformation = regs1[0];
682 mdSysInfo.Cpu.X86CpuInfo.FeatureInformation = regs1[3];
683 mdSysInfo.Cpu.X86CpuInfo.AMDExtendedCpuFeatures = 0;
684 if (regs0[1] == 0x68747541 /* "Auth" */ &&
685 regs0[3] == 0x69746e65 /* "enti" */ &&
686 regs0[2] == 0x444d4163 /* "cAMD" */)
687 {
688 do_x86cpuid(0x80000000, regs1); /* get vendor cpuid level */
689 if (regs1[0] >= 0x80000001)
690 {
691 do_x86cpuid(0x80000001, regs1); /* get vendor features */
692 mdSysInfo.Cpu.X86CpuInfo.AMDExtendedCpuFeatures = regs1[3];
693 }
694 }
695 }
696 else
697 {
698 unsigned i;
699 ULONG64 one = 1;
700
701 mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[0] = 0;
702 mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[1] = 0;
703
704 for (i = 0; i < sizeof(mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[0]) * 8; i++)
706 mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[0] |= one << i;
707 }
708 append(dc, &mdSysInfo, sizeof(mdSysInfo));
709
710 /* write Wine specific system information just behind the structure, and before any string */
711 if (wine_extra)
712 {
713 static const char code[] = {'W','I','N','E'};
714
715 WriteFile(dc->hFile, code, 4, &written, NULL);
716 /* number of sub-info, so that we can extend structure if needed */
717 slen = 3;
718 WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL);
719 /* we store offsets from just after the WINE marker */
720 slen = 4 * sizeof(DWORD);
721 WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL);
722 slen += strlen(build_id) + 1;
723 WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL);
724 slen += strlen(sys_name) + 1;
725 WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL);
726 WriteFile(dc->hFile, build_id, strlen(build_id) + 1, &written, NULL);
727 WriteFile(dc->hFile, sys_name, strlen(sys_name) + 1, &written, NULL);
728 WriteFile(dc->hFile, release_name, strlen(release_name) + 1, &written, NULL);
729 dc->rva += wine_extra;
730 }
731
732 /* write the service pack version string after this stream. It is referenced within the
733 stream by its RVA in the file. */
734 slen = lstrlenW(osInfo.szCSDVersion) * sizeof(WCHAR);
735 WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL);
736 WriteFile(dc->hFile, osInfo.szCSDVersion, slen, &written, NULL);
737 dc->rva += sizeof(ULONG) + slen;
738
739 return sizeof(mdSysInfo);
740}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define CDECL
Definition: compat.h:29
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:143
BOOL WINAPI IsProcessorFeaturePresent(IN DWORD ProcessorFeature)
Definition: sysinfo.c:169
BOOL WINAPI GetVersionExW(IN LPOSVERSIONINFOW lpVersionInformation)
Definition: version.c:37
static void do_x86cpuid(unsigned int ax, unsigned int *p)
Definition: minidump.c:613
static int have_x86cpuid(void)
Definition: minidump.c:617
#define DWORD
Definition: nt_native.h:44
#define VER_SUITE_TERMINAL
int one
Definition: sehframes.cpp:28
UCHAR NumberOfProcessors
Definition: dbghelp.h:875
union _MINIDUMP_SYSTEM_INFO::_CPU_INFORMATION Cpu
USHORT ProcessorArchitecture
Definition: dbghelp.h:867
USHORT ProcessorRevision
Definition: dbghelp.h:869
ULONG dwMinorVersion
Definition: rtltypes.h:248
ULONG dwPlatformId
Definition: rtltypes.h:250
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:246
ULONG dwMajorVersion
Definition: rtltypes.h:247
ULONG dwBuildNumber
Definition: rtltypes.h:249
WCHAR szCSDVersion[128]
Definition: rtltypes.h:251
DWORD dwNumberOfProcessors
Definition: winbase.h:1177
WORD wProcessorLevel
Definition: winbase.h:1180
WORD wProcessorRevision
Definition: winbase.h:1181
WORD wProcessorArchitecture
Definition: winbase.h:1169
Definition: inflate.c:139
struct _MINIDUMP_SYSTEM_INFO::_CPU_INFORMATION::@2838 OtherCpuInfo
struct _MINIDUMP_SYSTEM_INFO::_CPU_INFORMATION::@2837 X86CpuInfo
#define VER_NT_WORKSTATION

Referenced by MiniDumpWriteDump().

◆ dump_threads()

static unsigned dump_threads ( struct dump_context dc,
const MINIDUMP_EXCEPTION_INFORMATION except 
)
static

Definition at line 747 of file minidump.c.

749{
750 MINIDUMP_THREAD mdThd;
751 MINIDUMP_THREAD_LIST mdThdList;
752 unsigned i, sz;
753 RVA rva_base;
754 DWORD flags_out;
755 CONTEXT ctx;
756
757 mdThdList.NumberOfThreads = 0;
758
759 rva_base = dc->rva;
760 dc->rva += sz = sizeof(mdThdList.NumberOfThreads) + dc->num_threads * sizeof(mdThd);
761
762 for (i = 0; i < dc->num_threads; i++)
763 {
764 fetch_thread_info(dc, i, except, &mdThd, &ctx);
765
769 flags_out |= ThreadWriteThreadData;
770 if (dc->type & MiniDumpWithThreadInfo)
771 flags_out |= ThreadWriteThreadInfo;
772
773 if (dc->cb)
774 {
777
778 cbin.ProcessId = dc->pid;
779 cbin.ProcessHandle = dc->process->handle;
781 cbin.u.Thread.ThreadId = dc->threads[i].tid;
782 cbin.u.Thread.ThreadHandle = 0; /* FIXME */
783 cbin.u.Thread.Context = ctx;
784 cbin.u.Thread.SizeOfContext = sizeof(CONTEXT);
786 cbin.u.Thread.StackEnd = mdThd.Stack.StartOfMemoryRange +
787 mdThd.Stack.Memory.DataSize;
788
789 cbout.u.ThreadWriteFlags = flags_out;
790 if (!dc->cb->CallbackRoutine(dc->cb->CallbackParam, &cbin, &cbout))
791 continue;
792 flags_out &= cbout.u.ThreadWriteFlags;
793 }
794 if (flags_out & ThreadWriteThread)
795 {
796 if (ctx.ContextFlags && (flags_out & ThreadWriteContext))
797 {
798 mdThd.ThreadContext.Rva = dc->rva;
799 mdThd.ThreadContext.DataSize = sizeof(CONTEXT);
800 append(dc, &ctx, sizeof(CONTEXT));
801 }
802 if (mdThd.Stack.Memory.DataSize && (flags_out & ThreadWriteStack))
803 {
805 mdThd.Stack.Memory.DataSize,
806 rva_base + sizeof(mdThdList.NumberOfThreads) +
807 mdThdList.NumberOfThreads * sizeof(mdThd) +
808 FIELD_OFFSET(MINIDUMP_THREAD, Stack.Memory.Rva));
809 }
810 writeat(dc,
811 rva_base + sizeof(mdThdList.NumberOfThreads) +
812 mdThdList.NumberOfThreads * sizeof(mdThd),
813 &mdThd, sizeof(mdThd));
814 mdThdList.NumberOfThreads++;
815 }
816 /* fetch CPU dependent thread info (like 256 bytes around program counter */
817 dbghelp_current_cpu->fetch_minidump_thread(dc, i, flags_out, &ctx);
818 }
819 writeat(dc, rva_base,
820 &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads));
821
822 return sz;
823}
@ ThreadCallback
Definition: dbghelp.h:626
@ ThreadWriteInstructionWindow
Definition: compat.h:1150
@ ThreadWriteThreadData
Definition: compat.h:1151
@ ThreadWriteThreadInfo
Definition: compat.h:1152
@ ThreadWriteContext
Definition: compat.h:1148
@ ThreadWriteThread
Definition: compat.h:1146
@ ThreadWriteStack
Definition: compat.h:1147
@ MiniDumpWithThreadInfo
Definition: compat.h:1279
void minidump_add_memory_block(struct dump_context *dc, ULONG64 base, ULONG size, ULONG rva)
Definition: minidump.c:355
static BOOL fetch_thread_info(struct dump_context *dc, int thd_idx, const MINIDUMP_EXCEPTION_INFORMATION *except, MINIDUMP_THREAD *mdThd, CONTEXT *ctx)
Definition: minidump.c:121
struct _CONTEXT CONTEXT
MINIDUMP_THREAD_CALLBACK Thread
Definition: compat.h:1330
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext
Definition: dbghelp.h:920
MINIDUMP_MEMORY_DESCRIPTOR Stack
Definition: dbghelp.h:919
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639

Referenced by MiniDumpWriteDump().

◆ fetch_host_module_info_cb()

static BOOL fetch_host_module_info_cb ( const WCHAR name,
ULONG_PTR  base,
void user 
)
static

Definition at line 257 of file minidump.c.

259{
260 struct dump_context* dc = user;
261 DWORD_PTR rbase;
263
264 /* FIXME: there's no relevant timestamp on ELF modules */
265 if (!dc->process->loader->fetch_file_info(dc->process, name, base, &rbase, &size, &checksum))
266 size = checksum = 0;
267 add_module(dc, name, base ? base : rbase, size, 0 /* FIXME */, checksum, TRUE);
268 return TRUE;
269}
void user(int argc, const char *argv[])
Definition: cmds.c:1350
static BOOL add_module(struct dump_context *dc, const WCHAR *name, DWORD64 base, DWORD size, DWORD timestamp, DWORD checksum, BOOL is_elf)
Definition: minidump.c:195

Referenced by fetch_modules_info().

◆ fetch_memory64_info()

static void fetch_memory64_info ( struct dump_context dc)
static

Definition at line 293 of file minidump.c.

294{
297
298 addr = 0;
299 while (VirtualQueryEx(dc->process->handle, (LPCVOID)addr, &mbi, sizeof(mbi)) != 0)
300 {
301 /* Memory regions with state MEM_COMMIT will be added to the dump */
302 if (mbi.State == MEM_COMMIT)
303 {
305 }
306
307 if ((addr + mbi.RegionSize) < addr)
308 break;
309
311 }
312}
#define ULONG_PTR
Definition: config.h:101
GLenum const GLvoid * addr
Definition: glext.h:9621
static void minidump_add_memory64_block(struct dump_context *dc, ULONG64 base, ULONG64 size)
Definition: minidump.c:271
#define MEM_COMMIT
Definition: nt_native.h:1313
uint32_t ULONG_PTR
Definition: typedefs.h:65
SIZE_T NTAPI VirtualQueryEx(IN HANDLE hProcess, IN LPCVOID lpAddress, OUT PMEMORY_BASIC_INFORMATION lpBuffer, IN SIZE_T dwLength)
Definition: virtmem.c:227
CONST void * LPCVOID
Definition: windef.h:191

Referenced by MiniDumpWriteDump().

◆ fetch_module_versioninfo()

static void fetch_module_versioninfo ( LPCWSTR  filename,
VS_FIXEDFILEINFO ffi 
)
static

Definition at line 325 of file minidump.c.

326{
328 DWORD sz;
329 static const WCHAR backslashW[] = {'\\', '\0'};
330
331 memset(ffi, 0, sizeof(*ffi));
333 {
334 void* info = HeapAlloc(GetProcessHeap(), 0, sz);
336 {
338 UINT len;
339
340 if (VerQueryValueW(info, backslashW, (void*)&ptr, &len))
341 memcpy(ffi, ptr, min(len, sizeof(*ffi)));
342 }
344 }
345}
static const WCHAR backslashW[]
#define HeapFree(x, y, z)
Definition: compat.h:735
BOOL WINAPI GetFileVersionInfoW(LPCWSTR filename, DWORD handle, DWORD datasize, LPVOID data)
Definition: version.c:845
BOOL WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:1049
DWORD WINAPI GetFileVersionInfoSizeW(LPCWSTR filename, LPDWORD handle)
Definition: version.c:611
const char * filename
Definition: ioapi.h:137
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
unsigned int UINT
Definition: ndis.h:50

Referenced by dump_modules().

◆ fetch_modules_info()

static void fetch_modules_info ( struct dump_context dc)
static

Definition at line 314 of file minidump.c.

315{
317 /* Since we include ELF modules in a separate stream from the regular PE ones,
318 * we can always include those ELF modules (they don't eat lots of space)
319 * And it's always a good idea to have a trace of the loaded ELF modules for
320 * a given application in a post mortem debugging condition.
321 */
322 dc->process->loader->enum_modules(dc->process, fetch_host_module_info_cb, dc);
323}
BOOL WINAPI EnumerateLoadedModulesW64(HANDLE hProcess, PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, PVOID UserContext)
Definition: module.c:1112
static BOOL fetch_host_module_info_cb(const WCHAR *name, ULONG_PTR base, void *user)
Definition: minidump.c:257
static BOOL WINAPI fetch_pe_module_info_cb(PCWSTR name, DWORD64 base, ULONG size, PVOID user)
Definition: minidump.c:237

Referenced by MiniDumpWriteDump().

◆ fetch_pe_module_info_cb()

static BOOL WINAPI fetch_pe_module_info_cb ( PCWSTR  name,
DWORD64  base,
ULONG  size,
PVOID  user 
)
static

Definition at line 237 of file minidump.c.

239{
240 struct dump_context* dc = user;
242
243 if (!validate_addr64(base)) return FALSE;
244
245 if (pe_load_nt_header(dc->process->handle, base, &nth))
248 FALSE);
249 return TRUE;
250}
BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS *nth) DECLSPEC_HIDDEN
Definition: pe_module.c:881
BOOL validate_addr64(DWORD64 addr)
Definition: dbghelp.c:112
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183

Referenced by fetch_modules_info().

◆ fetch_process_info()

static BOOL fetch_process_info ( struct dump_context dc)
static

Definition at line 42 of file minidump.c.

43{
44 ULONG buf_size = 0x1000;
45 NTSTATUS nts;
46 void* pcs_buffer = NULL;
47
48 if (!(pcs_buffer = HeapAlloc(GetProcessHeap(), 0, buf_size))) return FALSE;
49 for (;;)
50 {
52 pcs_buffer, buf_size, NULL);
53 if (nts != STATUS_INFO_LENGTH_MISMATCH) break;
54 pcs_buffer = HeapReAlloc(GetProcessHeap(), 0, pcs_buffer, buf_size *= 2);
55 if (!pcs_buffer) return FALSE;
56 }
57
58 if (nts == STATUS_SUCCESS)
59 {
60 SYSTEM_PROCESS_INFORMATION* spi = pcs_buffer;
61 unsigned i;
62
63 for (;;)
64 {
65 if (HandleToUlong(spi->UniqueProcessId) == dc->pid)
66 {
67 dc->num_threads = spi->dwThreadCount;
68 dc->threads = HeapAlloc(GetProcessHeap(), 0,
69 dc->num_threads * sizeof(dc->threads[0]));
70 if (!dc->threads) goto failed;
71 for (i = 0; i < dc->num_threads; i++)
72 {
73 dc->threads[i].tid = HandleToULong(spi->ti[i].ClientId.UniqueThread);
74 dc->threads[i].prio_class = spi->ti[i].dwBasePriority; /* FIXME */
75 dc->threads[i].curr_prio = spi->ti[i].dwCurrentPriority;
76 }
77 HeapFree(GetProcessHeap(), 0, pcs_buffer);
78 return TRUE;
79 }
80 if (!spi->NextEntryOffset) break;
81 spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->NextEntryOffset);
82 }
83 }
84failed:
85 HeapFree(GetProcessHeap(), 0, pcs_buffer);
86 return FALSE;
87}
LONG NTSTATUS
Definition: precomp.h:26
#define HandleToUlong(h)
Definition: basetsd.h:79
#define HandleToULong(h)
Definition: basetsd.h:95
@ SystemProcessInformation
Definition: ntddk_ex.h:16
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133

Referenced by MiniDumpWriteDump().

◆ fetch_thread_info()

static BOOL fetch_thread_info ( struct dump_context dc,
int  thd_idx,
const MINIDUMP_EXCEPTION_INFORMATION except,
MINIDUMP_THREAD mdThd,
CONTEXT ctx 
)
static

Definition at line 121 of file minidump.c.

124{
125 DWORD tid = dc->threads[thd_idx].tid;
128
129 memset(ctx, 0, sizeof(*ctx));
130
131 mdThd->ThreadId = tid;
132 mdThd->SuspendCount = 0;
133 mdThd->Teb = 0;
134 mdThd->Stack.StartOfMemoryRange = 0;
135 mdThd->Stack.Memory.DataSize = 0;
136 mdThd->Stack.Memory.Rva = 0;
137 mdThd->ThreadContext.DataSize = 0;
138 mdThd->ThreadContext.Rva = 0;
139 mdThd->PriorityClass = dc->threads[thd_idx].prio_class;
140 mdThd->Priority = dc->threads[thd_idx].curr_prio;
141
143 {
144 FIXME("Couldn't open thread %u (%u)\n", tid, GetLastError());
145 return FALSE;
146 }
147
149 &tbi, sizeof(tbi), NULL) == STATUS_SUCCESS)
150 {
151 mdThd->Teb = (ULONG_PTR)tbi.TebBaseAddress;
152 if (tbi.ExitStatus == STILL_ACTIVE)
153 {
154 if (tid != GetCurrentThreadId() &&
155 (mdThd->SuspendCount = SuspendThread(hThread)) != (DWORD)-1)
156 {
157 ctx->ContextFlags = CONTEXT_FULL;
159 memset(ctx, 0, sizeof(*ctx));
160
163 }
164 else if (tid == GetCurrentThreadId() && except)
165 {
166 CONTEXT lctx, *pctx;
167 mdThd->SuspendCount = 1;
168 if (except->ClientPointers)
169 {
171
172 ReadProcessMemory(dc->process->handle, except->ExceptionPointers,
173 &ep, sizeof(ep), NULL);
174 ReadProcessMemory(dc->process->handle, ep.ContextRecord,
175 &lctx, sizeof(lctx), NULL);
176 pctx = &lctx;
177 }
178 else pctx = except->ExceptionPointers->ContextRecord;
179
180 *ctx = *pctx;
181 fetch_thread_stack(dc, tbi.TebBaseAddress, pctx, &mdThd->Stack);
182 }
183 else mdThd->SuspendCount = 0;
184 }
185 }
187 return TRUE;
188}
#define CloseHandle
Definition: compat.h:739
@ ThreadBasicInformation
Definition: compat.h:935
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
DWORD WINAPI SuspendThread(IN HANDLE hThread)
Definition: thread.c:642
HANDLE WINAPI OpenThread(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwThreadId)
Definition: thread.c:403
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
if(dx< 0)
Definition: linetemp.h:194
static void fetch_thread_stack(struct dump_context *dc, const void *teb_addr, const CONTEXT *ctx, MINIDUMP_MEMORY_DESCRIPTOR *mmd)
Definition: minidump.c:89
static TfClientId tid
HANDLE hThread
Definition: wizard.c:28
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define CONTEXT_FULL
Definition: nt_native.h:1375
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
ULONG Priority
Definition: dbghelp.h:917
ULONG ThreadId
Definition: dbghelp.h:914
ULONG64 Teb
Definition: dbghelp.h:918
ULONG PriorityClass
Definition: dbghelp.h:916
ULONG SuspendCount
Definition: dbghelp.h:915
#define STILL_ACTIVE
Definition: winbase.h:233
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459

Referenced by dump_threads().

◆ fetch_thread_stack()

static void fetch_thread_stack ( struct dump_context dc,
const void teb_addr,
const CONTEXT ctx,
MINIDUMP_MEMORY_DESCRIPTOR mmd 
)
static

Definition at line 89 of file minidump.c.

91{
92 NT_TIB tib;
94
95 if (ReadProcessMemory(dc->process->handle, teb_addr, &tib, sizeof(tib), NULL) &&
97 dbghelp_current_cpu->get_addr(NULL /* FIXME */, ctx, cpu_addr_stack, &addr) && addr.Mode == AddrModeFlat)
98 {
99 if (addr.Offset)
100 {
101 addr.Offset -= dbghelp_current_cpu->word_size;
102 /* make sure stack pointer is within the established range of the stack. It could have
103 been clobbered by whatever caused the original exception. */
104 if (addr.Offset < (ULONG_PTR)tib.StackLimit || addr.Offset > (ULONG_PTR)tib.StackBase)
106
107 else
108 mmd->StartOfMemoryRange = addr.Offset;
109 }
110 else
113 }
114}
@ cpu_addr_stack
@ AddrModeFlat
Definition: compat.h:1159
PVOID StackLimit
Definition: compat.h:713
PVOID StackBase
Definition: compat.h:712

Referenced by fetch_thread_info().

◆ have_x86cpuid()

static int have_x86cpuid ( void  )
static

Definition at line 617 of file minidump.c.

618{
619 return 0;
620}

Referenced by dump_system_info().

◆ minidump_add_memory64_block()

static void minidump_add_memory64_block ( struct dump_context dc,
ULONG64  base,
ULONG64  size 
)
static

Definition at line 271 of file minidump.c.

272{
273 if (!dc->mem64)
274 {
275 dc->alloc_mem64 = 32;
276 dc->mem64 = HeapAlloc(GetProcessHeap(), 0, dc->alloc_mem64 * sizeof(*dc->mem64));
277 }
278 else if (dc->num_mem64 >= dc->alloc_mem64)
279 {
280 dc->alloc_mem64 *= 2;
281 dc->mem64 = HeapReAlloc(GetProcessHeap(), 0, dc->mem64,
282 dc->alloc_mem64 * sizeof(*dc->mem64));
283 }
284 if (dc->mem64)
285 {
286 dc->mem64[dc->num_mem64].base = base;
287 dc->mem64[dc->num_mem64].size = size;
288 dc->num_mem64++;
289 }
290 else dc->num_mem64 = dc->alloc_mem64 = 0;
291}

Referenced by fetch_memory64_info().

◆ minidump_add_memory_block()

void minidump_add_memory_block ( struct dump_context dc,
ULONG64  base,
ULONG  size,
ULONG  rva 
)

Definition at line 355 of file minidump.c.

356{
357 if (!dc->mem)
358 {
359 dc->alloc_mem = 32;
360 dc->mem = HeapAlloc(GetProcessHeap(), 0, dc->alloc_mem * sizeof(*dc->mem));
361 }
362 else if (dc->num_mem >= dc->alloc_mem)
363 {
364 dc->alloc_mem *= 2;
365 dc->mem = HeapReAlloc(GetProcessHeap(), 0, dc->mem,
366 dc->alloc_mem * sizeof(*dc->mem));
367 }
368 if (dc->mem)
369 {
370 dc->mem[dc->num_mem].base = base;
371 dc->mem[dc->num_mem].size = size;
372 dc->mem[dc->num_mem].rva = rva;
373 dc->num_mem++;
374 }
375 else dc->num_mem = dc->alloc_mem = 0;
376}

Referenced by arm64_fetch_minidump_thread(), arm_fetch_minidump_thread(), dump_threads(), i386_fetch_minidump_thread(), x86_64_fetch_minidump_module(), and x86_64_fetch_minidump_thread().

◆ MiniDumpReadDumpStream()

BOOL WINAPI MiniDumpReadDumpStream ( PVOID  base,
ULONG  str_idx,
PMINIDUMP_DIRECTORY pdir,
PVOID stream,
ULONG size 
)

Definition at line 1116 of file minidump.c.

1119{
1120 MINIDUMP_HEADER* mdHead = base;
1121
1122 if (mdHead->Signature == MINIDUMP_SIGNATURE)
1123 {
1125 DWORD i;
1126
1127 dir = (MINIDUMP_DIRECTORY*)((char*)base + mdHead->StreamDirectoryRva);
1128 for (i = 0; i < mdHead->NumberOfStreams; i++, dir++)
1129 {
1130 if (dir->StreamType == str_idx)
1131 {
1132 if (pdir) *pdir = dir;
1133 if (stream) *stream = (char*)base + dir->Location.Rva;
1134 if (size) *size = dir->Location.DataSize;
1135 return TRUE;
1136 }
1137 }
1138 }
1140 return FALSE;
1141}
unsigned int dir
Definition: maze.c:112
#define MINIDUMP_SIGNATURE
Definition: dbghelp.h:598
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
DWORD NumberOfStreams
Definition: dbghelp.h:790
DWORD Signature
Definition: dbghelp.h:788
RVA StreamDirectoryRva
Definition: dbghelp.h:791
Definition: parse.h:23

◆ MiniDumpWriteDump()

BOOL WINAPI MiniDumpWriteDump ( HANDLE  hProcess,
DWORD  pid,
HANDLE  hFile,
MINIDUMP_TYPE  DumpType,
PMINIDUMP_EXCEPTION_INFORMATION  ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION  UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION  CallbackParam 
)

Definition at line 942 of file minidump.c.

947{
948 static const MINIDUMP_DIRECTORY emptyDir = {UnusedStream, {0, 0}};
949 MINIDUMP_HEADER mdHead;
950 MINIDUMP_DIRECTORY mdDir;
951 DWORD i, nStreams, idx_stream;
952 struct dump_context dc;
953 BOOL sym_initialized = FALSE;
954
955 if (!(dc.process = process_find_by_handle(hProcess)))
956 {
957 if (!(sym_initialized = SymInitializeW(hProcess, NULL, TRUE)))
958 {
959 WARN("failed to initialize process\n");
960 return FALSE;
961 }
963 }
964
965 dc.hFile = hFile;
966 dc.pid = pid;
967 dc.modules = NULL;
968 dc.num_modules = 0;
969 dc.alloc_modules = 0;
970 dc.threads = NULL;
971 dc.num_threads = 0;
972 dc.cb = CallbackParam;
973 dc.type = DumpType;
974 dc.mem = NULL;
975 dc.num_mem = 0;
976 dc.alloc_mem = 0;
977 dc.mem64 = NULL;
978 dc.num_mem64 = 0;
979 dc.alloc_mem64 = 0;
980 dc.rva = 0;
981
982 if (!fetch_process_info(&dc)) return FALSE;
984
985 /* 1) init */
986 nStreams = 6 + (ExceptionParam ? 1 : 0) +
987 (UserStreamParam ? UserStreamParam->UserStreamCount : 0);
988
989 /* pad the directory size to a multiple of 4 for alignment purposes */
990 nStreams = (nStreams + 3) & ~3;
991
993 FIXME("NIY MiniDumpWithDataSegs\n");
995 FIXME("NIY MiniDumpWithHandleData\n");
997 FIXME("NIY MiniDumpFilterMemory\n");
999 FIXME("NIY MiniDumpScanMemory\n");
1000
1001 /* 2) write header */
1003 mdHead.Version = MINIDUMP_VERSION; /* NOTE: native puts in an 'implementation specific' value in the high order word of this member */
1004 mdHead.NumberOfStreams = nStreams;
1005 mdHead.CheckSum = 0; /* native sets a 0 checksum in its files */
1006 mdHead.StreamDirectoryRva = sizeof(mdHead);
1007 mdHead.u.TimeDateStamp = time(NULL);
1008 mdHead.Flags = DumpType;
1009 append(&dc, &mdHead, sizeof(mdHead));
1010
1011 /* 3) write stream directories */
1012 dc.rva += nStreams * sizeof(mdDir);
1013 idx_stream = 0;
1014
1015 /* 3.1) write data stream directories */
1016
1017 /* must be first in minidump */
1019 mdDir.Location.Rva = dc.rva;
1021 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1022 &mdDir, sizeof(mdDir));
1023
1025 mdDir.Location.Rva = dc.rva;
1026 mdDir.Location.DataSize = dump_threads(&dc, ExceptionParam);
1027 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1028 &mdDir, sizeof(mdDir));
1029
1031 mdDir.Location.Rva = dc.rva;
1033 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1034 &mdDir, sizeof(mdDir));
1035
1036 mdDir.StreamType = 0xfff0; /* FIXME: this is part of MS reserved streams */
1037 mdDir.Location.Rva = dc.rva;
1039 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1040 &mdDir, sizeof(mdDir));
1041
1042
1044 {
1046 mdDir.Location.Rva = dc.rva;
1048 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1049 &mdDir, sizeof(mdDir));
1050 }
1051
1052 mdDir.StreamType = MiscInfoStream;
1053 mdDir.Location.Rva = dc.rva;
1055 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1056 &mdDir, sizeof(mdDir));
1057
1058 /* 3.2) write exception information (if any) */
1059 if (ExceptionParam)
1060 {
1062 mdDir.Location.Rva = dc.rva;
1063 mdDir.Location.DataSize = dump_exception_info(&dc, ExceptionParam);
1064 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1065 &mdDir, sizeof(mdDir));
1066 }
1067
1068 /* 3.3) write user defined streams (if any) */
1069 if (UserStreamParam)
1070 {
1071 for (i = 0; i < UserStreamParam->UserStreamCount; i++)
1072 {
1073 mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type;
1074 mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize;
1075 mdDir.Location.Rva = dc.rva;
1076 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1077 &mdDir, sizeof(mdDir));
1078 append(&dc, UserStreamParam->UserStreamArray[i].Buffer,
1079 UserStreamParam->UserStreamArray[i].BufferSize);
1080 }
1081 }
1082
1083 /* 3.4) write full memory (if requested) */
1085 {
1087
1089 mdDir.Location.Rva = dc.rva;
1091 writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
1092 &mdDir, sizeof(mdDir));
1093 }
1094
1095 /* fill the remaining directory entries with 0's (unused stream types) */
1096 /* NOTE: this should always come last in the dump! */
1097 for (i = idx_stream; i < nStreams; i++)
1098 writeat(&dc, mdHead.StreamDirectoryRva + i * sizeof(emptyDir), &emptyDir, sizeof(emptyDir));
1099
1100 if (sym_initialized)
1102
1103 HeapFree(GetProcessHeap(), 0, dc.mem);
1104 HeapFree(GetProcessHeap(), 0, dc.mem64);
1105 HeapFree(GetProcessHeap(), 0, dc.modules);
1106 HeapFree(GetProcessHeap(), 0, dc.threads);
1107
1108 return TRUE;
1109}
#define WARN(fmt,...)
Definition: debug.h:115
@ MiscInfoStream
Definition: dbghelp.h:959
@ MemoryListStream
Definition: dbghelp.h:949
@ SystemInfoStream
Definition: dbghelp.h:951
@ UnusedStream
Definition: dbghelp.h:944
@ ThreadListStream
Definition: dbghelp.h:947
@ ExceptionStream
Definition: dbghelp.h:950
@ Memory64ListStream
Definition: dbghelp.h:953
@ ModuleListStream
Definition: dbghelp.h:948
#define MINIDUMP_VERSION
Definition: dbghelp.h:599
INT nStreams
Definition: api.c:60
BOOL WINAPI SymCleanup(HANDLE hProcess)
Definition: dbghelp.c:557
@ MiniDumpScanMemory
Definition: compat.h:1271
@ MiniDumpWithHandleData
Definition: compat.h:1269
@ MiniDumpFilterMemory
Definition: compat.h:1270
@ MiniDumpWithFullMemory
Definition: compat.h:1268
BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess)
Definition: dbghelp.c:464
struct process * process_find_by_handle(HANDLE hProcess)
Definition: dbghelp.c:99
unsigned int BOOL
Definition: ntddk_ex.h:94
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
static unsigned dump_memory64_info(struct dump_context *dc)
Definition: minidump.c:875
static unsigned dump_misc_info(struct dump_context *dc)
Definition: minidump.c:922
static void fetch_modules_info(struct dump_context *dc)
Definition: minidump.c:314
static BOOL fetch_process_info(struct dump_context *dc)
Definition: minidump.c:42
static unsigned dump_threads(struct dump_context *dc, const MINIDUMP_EXCEPTION_INFORMATION *except)
Definition: minidump.c:747
static unsigned dump_modules(struct dump_context *dc, BOOL dump_elf)
Definition: minidump.c:457
static unsigned dump_exception_info(struct dump_context *dc, const MINIDUMP_EXCEPTION_INFORMATION *except)
Definition: minidump.c:408
static void fetch_memory64_info(struct dump_context *dc)
Definition: minidump.c:293
static unsigned dump_system_info(struct dump_context *dc)
Definition: minidump.c:628
static unsigned dump_memory_info(struct dump_context *dc)
Definition: minidump.c:830
__u16 time
Definition: mkdosfs.c:8
_In_ HANDLE hFile
Definition: mswsock.h:90
MINIDUMP_LOCATION_DESCRIPTOR Location
Definition: dbghelp.h:757
DWORD TimeDateStamp
Definition: dbghelp.h:796
ULONG64 Flags
Definition: dbghelp.h:798
DWORD CheckSum
Definition: dbghelp.h:792
PMINIDUMP_USER_STREAM UserStreamArray
Definition: dbghelp.h:939
VOID DumpType(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers)
Definition: symdump.c:695
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837

Referenced by WriteMinidump().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( dbghelp  )

◆ writeat()

static void writeat ( struct dump_context dc,
RVA  rva,
const void data,
unsigned  size 
)
static

Definition at line 383 of file minidump.c.

384{
385 DWORD written;
386
387 SetFilePointer(dc->hFile, rva, NULL, FILE_BEGIN);
388 WriteFile(dc->hFile, data, size, &written, NULL);
389}

Referenced by append(), dump_memory64_info(), dump_memory_info(), dump_modules(), dump_threads(), and MiniDumpWriteDump().