CVS: winex/dlls/dbghelp minidump.c,1.3,1.4
[email protected] 30 Aug 2007 14:19:17 -0000
| Newsgroups | gmane.comp.emulators.winex.cvs |
|---|---|
| Message-ID | <[email protected]> |
Subject: winex/dlls/dbghelp minidump.c,1.3,1.4Update of /var/lib/cvsd/cvsroot/winex/dlls/dbghelp
In directory agravaine:/tmp/cvs-serv19541/dlls/dbghelp
Modified Files:
minidump.c
Log Message:
- fixed up the minidump files so that windbg can load them and successfully display the crash information. This is still missing the implementation for NtQuerySystemInformation() though (which will actually cause an access violation in itself at the moment)
Index: minidump.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/dbghelp/minidump.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- minidump.c 30 Aug 2007 14:18:30 -0000 1.3
+++ minidump.c 30 Aug 2007 14:19:15 -0000 1.4
@@ -38,7 +38,7 @@
struct dump_memory
{
- ULONG base;
+ ULONG64 base;
ULONG size;
ULONG rva;
};
@@ -170,6 +170,7 @@
mdThd->PriorityClass = dc->spi->ti[thd_idx].dwBasePriority; /* FIXME */
mdThd->Priority = dc->spi->ti[thd_idx].dwCurrentPriority;
+
if ((hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid)) == 0)
{
FIXME("Couldn't open thread %ld (%ld)\n",
@@ -207,7 +208,10 @@
&ctx, sizeof(ctx), NULL);
pctx = &lctx;
}
- else pctx = except->ExceptionPointers->ContextRecord;
+ else
+ pctx = except->ExceptionPointers->ContextRecord;
+
+ memcpy(ctx, pctx, sizeof(*ctx));
fetch_thread_stack(dc, tbi.TebBaseAddress, pctx, &mdThd->Stack);
}
}
@@ -355,7 +359,8 @@
* Write in File the exception information from pcs
*/
static void dump_exception_info(struct dump_context* dc,
- const MINIDUMP_EXCEPTION_INFORMATION* except)
+ const MINIDUMP_EXCEPTION_INFORMATION* except,
+ ULONG64 *streamSize)
{
MINIDUMP_EXCEPTION_STREAM mdExcpt;
EXCEPTION_RECORD rec, *prec;
@@ -393,8 +398,14 @@
mdExcpt.ThreadContext.DataSize = sizeof(*pctx);
mdExcpt.ThreadContext.Rva = dc->rva + sizeof(mdExcpt);
+ /* the size of this stream should be reported as the size of just the struct. The thread context
+ block exists outside this stream and is referenced by just its RVA. */
+ *streamSize = sizeof(mdExcpt);
+
append(dc, &mdExcpt, sizeof(mdExcpt));
append(dc, pctx, sizeof(*pctx));
+
+ TRACE("wrote out an exception info block {streamSize = %llu, extraSpace = %lu}\n", *streamSize, sizeof(*pctx));
}
/******************************************************************
@@ -402,7 +413,7 @@
*
* Write in File the modules from pcs
*/
-static void dump_modules(struct dump_context* dc, BOOL dump_elf)
+static void dump_modules(struct dump_context* dc, BOOL dump_elf, ULONG64 *streamSize)
{
MINIDUMP_MODULE mdModule;
MINIDUMP_MODULE_LIST mdModuleList;
@@ -427,6 +438,8 @@
*/
rva_base = dc->rva;
dc->rva += sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod;
+
+
for (i = 0; i < dc->num_module; i++)
{
if ((dc->module[i].is_elf && !dump_elf) ||
@@ -494,6 +507,14 @@
}
writeat(dc, rva_base, &mdModuleList.NumberOfModules,
sizeof(mdModuleList.NumberOfModules));
+
+ /* the stream size is just the size of the module index. It does not include the data for the
+ names of each module. *Technically* the names are supposed to go into the common string table
+ in the minidump file. Since each string is referenced by RVA they can all safely be located
+ anywhere between streams in the file, so the end of this stream is sufficient. */
+ *streamSize = sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * mdModuleList.NumberOfModules;
+
+ TRACE("wrote out %lu module info blocks {streamSize = %llu, extraSpace = %lu}\n", mdModuleList.NumberOfModules, *streamSize, dc->rva - rva_base - (ULONG)(*streamSize));
}
/******************************************************************
@@ -501,7 +522,7 @@
*
* Dumps into File the information about the system
*/
-static void dump_system_info(struct dump_context* dc)
+static void dump_system_info(struct dump_context* dc, ULONG64 *streamSize)
{
MINIDUMP_SYSTEM_INFO mdSysInfo;
SYSTEM_INFO sysInfo;
@@ -525,15 +546,24 @@
mdSysInfo.CSDVersionRva = dc->rva + sizeof(mdSysInfo);
mdSysInfo.u1.Reserved1 = 0;
+ mdSysInfo.u1.s.SuiteMask = VER_SUITE_TERMINAL;
+ FIXME("fill in CPU vendorID and feature set\n");
memset(&mdSysInfo.Cpu, 0, sizeof(mdSysInfo.Cpu));
append(dc, &mdSysInfo, sizeof(mdSysInfo));
+
+ *streamSize = sizeof(MINIDUMP_SYSTEM_INFO);
+
+ /* write the service pack version string after this stream. It is referenced within the
+ stream by its RVA in the file. */
slen = lstrlenW(osInfo.szCSDVersion) * sizeof(WCHAR);
WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL);
WriteFile(dc->hFile, osInfo.szCSDVersion, slen, &written, NULL);
dc->rva += sizeof(ULONG) + slen;
+
+ TRACE("wrote out a system information block {streamSize = %llu, extraSpace = %lu}\n", *streamSize, sizeof(ULONG) + slen);
}
/******************************************************************
@@ -542,7 +572,8 @@
* Dumps into File the information about running threads
*/
static void dump_threads(struct dump_context* dc,
- const MINIDUMP_EXCEPTION_INFORMATION* except)
+ const MINIDUMP_EXCEPTION_INFORMATION* except,
+ ULONG64 *streamSize)
{
MINIDUMP_THREAD mdThd;
MINIDUMP_THREAD_LIST mdThdList;
@@ -551,12 +582,14 @@
DWORD flags_out;
CONTEXT ctx;
+
mdThdList.NumberOfThreads = 0;
rva_base = dc->rva;
dc->rva += sizeof(mdThdList.NumberOfThreads) +
dc->spi->dwThreadCount * sizeof(mdThd);
+
for (i = 0; i < dc->spi->dwThreadCount; i++)
{
fetch_thread_info(dc, i, except, &mdThd, &ctx);
@@ -622,6 +655,14 @@
}
writeat(dc, rva_base,
&mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads));
+
+
+ /* size of this stream is the total size of the thread index. The stack memory
+ data and the context records are not included in this count */
+ *streamSize = sizeof(mdThdList.NumberOfThreads) +
+ mdThdList.NumberOfThreads * sizeof(mdThd);
+
+ TRACE("wrote out %lu thread info blocks {streamSize = %llu, extraSpace = %lu}\n", mdThdList.NumberOfThreads, *streamSize, dc->rva - rva_base - (ULONG)(*streamSize));
}
/******************************************************************
@@ -629,21 +670,29 @@
*
* dumps information about the memory of the process (stack of the threads)
*/
-static void dump_memory_info(struct dump_context* dc)
+static void dump_memory_info(struct dump_context* dc, ULONG64 *streamSize)
{
MINIDUMP_MEMORY_LIST mdMemList;
MINIDUMP_MEMORY_DESCRIPTOR mdMem;
DWORD written;
+ DWORD64 totalSize = 0;
unsigned i, pos, len;
RVA rva_base;
char tmp[1024];
+
mdMemList.NumberOfMemoryRanges = dc->num_mem;
append(dc, &mdMemList.NumberOfMemoryRanges,
sizeof(mdMemList.NumberOfMemoryRanges));
rva_base = dc->rva;
dc->rva += mdMemList.NumberOfMemoryRanges * sizeof(mdMem);
+ /* the size of this stream only includes the memory list index. It does not include
+ the size of each memory block. Memory blocks are referenced by RVA so they can
+ safely be stored starting at the end of this stream. */
+ *streamSize = sizeof(mdMemList.NumberOfMemoryRanges) + mdMemList.NumberOfMemoryRanges * sizeof(mdMem);
+
+
for (i = 0; i < dc->num_mem; i++)
{
mdMem.StartOfMemoryRange = dc->mem[i].base;
@@ -658,24 +707,37 @@
tmp, len, NULL))
WriteFile(dc->hFile, tmp, len, &written, NULL);
}
+
dc->rva += mdMem.Memory.DataSize;
+ totalSize += mdMem.Memory.DataSize;
+
writeat(dc, rva_base + i * sizeof(mdMem), &mdMem, sizeof(mdMem));
if (dc->mem[i].rva)
{
writeat(dc, dc->mem[i].rva, &mdMem.Memory.Rva, sizeof(mdMem.Memory.Rva));
}
}
+
+ TRACE("wrote out %u blocks of memory {streamSize = %llu, extraSpace = %llu}\n", dc->num_mem, *streamSize, totalSize);
}
-static void dump_misc_info(struct dump_context* dc)
+static void dump_misc_info(struct dump_context* dc, ULONG64 *streamSize)
{
MINIDUMP_MISC_INFO mmi;
mmi.SizeOfInfo = sizeof(mmi);
mmi.Flags1 = MINIDUMP_MISC1_PROCESS_ID;
mmi.ProcessId = dc->pid;
+
/* FIXME: create/user/kernel time */
+ mmi.ProcessCreateTime = 0;
+ mmi.ProcessKernelTime = 0;
+ mmi.ProcessUserTime = 0;
+
append(dc, &mmi, sizeof(mmi));
+
+ *streamSize = sizeof(mmi);
+ TRACE("wrote out a misc info block {streamSize = %llu}\n", *streamSize);
}
/******************************************************************
@@ -690,9 +752,12 @@
{
MINIDUMP_HEADER mdHead;
MINIDUMP_DIRECTORY mdDir;
+ MINIDUMP_DIRECTORY emptyDir = {UnusedStream, {0, 0}};
DWORD i, nStreams, idx_stream;
+ ULONG64 streamSize;
struct dump_context dc;
+
dc.hProcess = hProcess;
dc.hFile = hFile;
dc.pid = pid;
@@ -705,7 +770,7 @@
dc.rva = 0;
if (!fetch_process_info(&dc)){
- ERR("could not retrieve my process info! {pid = %d}\n", pid);
+ ERR("could not retrieve my process info! {pid = %ld}\n", pid);
return FALSE;
}
@@ -716,6 +781,9 @@
nStreams = 6 + (ExceptionParam ? 1 : 0) +
(UserStreamParam ? UserStreamParam->UserStreamCount : 0);
+ /* pad the directory size to a multiple of 4 for alignment purposes */
+ nStreams = (nStreams + 3) & ~3;
+
if (DumpType & MiniDumpWithDataSegs)
FIXME("NIY MiniDumpWithDataSegs\n");
if (DumpType & MiniDumpWithFullMemory)
@@ -729,10 +797,11 @@
/* 2) write header */
mdHead.Signature = MINIDUMP_SIGNATURE;
- mdHead.Version = MINIDUMP_VERSION;
+ mdHead.Version = MINIDUMP_VERSION; /* NOTE: native puts in an 'implementation specific' value in the high order word of this member */
mdHead.NumberOfStreams = nStreams;
+ mdHead.CheckSum = 0; /* native sets a 0 checksum in its files */
mdHead.StreamDirectoryRva = sizeof(mdHead);
- mdHead.u.TimeDateStamp = time(NULL);
+ mdHead.u.TimeDateStamp = (ULONG32)time(NULL);
mdHead.Flags = DumpType;
append(&dc, &mdHead, sizeof(mdHead));
@@ -744,43 +813,43 @@
mdDir.StreamType = ThreadListStream;
mdDir.Location.Rva = dc.rva;
- dump_threads(&dc, ExceptionParam);
- mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+ dump_threads(&dc, ExceptionParam, &streamSize);
+ mdDir.Location.DataSize = (ULONG32)streamSize; /*dc.rva - mdDir.Location.Rva;*/
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir));
mdDir.StreamType = ModuleListStream;
mdDir.Location.Rva = dc.rva;
- dump_modules(&dc, FALSE);
- mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+ dump_modules(&dc, FALSE, &streamSize);
+ mdDir.Location.DataSize = (ULONG32)streamSize; /*dc.rva - mdDir.Location.Rva;*/
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir));
mdDir.StreamType = 0xfff0; /* FIXME: this is part of MS reserved streams */
mdDir.Location.Rva = dc.rva;
- dump_modules(&dc, TRUE);
- mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+ dump_modules(&dc, TRUE, &streamSize);
+ mdDir.Location.DataSize = (ULONG32)streamSize; /*dc.rva - mdDir.Location.Rva;*/
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir));
mdDir.StreamType = MemoryListStream;
mdDir.Location.Rva = dc.rva;
- dump_memory_info(&dc);
- mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+ dump_memory_info(&dc, &streamSize);
+ mdDir.Location.DataSize = (ULONG32)streamSize; /*dc.rva - mdDir.Location.Rva;*/
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir));
mdDir.StreamType = SystemInfoStream;
mdDir.Location.Rva = dc.rva;
- dump_system_info(&dc);
- mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+ dump_system_info(&dc, &streamSize);
+ mdDir.Location.DataSize = (ULONG32)streamSize; /*dc.rva - mdDir.Location.Rva;*/
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir));
mdDir.StreamType = MiscInfoStream;
mdDir.Location.Rva = dc.rva;
- dump_misc_info(&dc);
- mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+ dump_misc_info(&dc, &streamSize);
+ mdDir.Location.DataSize = (ULONG32)streamSize; /*dc.rva - mdDir.Location.Rva;*/
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir));
@@ -789,8 +858,8 @@
{
mdDir.StreamType = ExceptionStream;
mdDir.Location.Rva = dc.rva;
- dump_exception_info(&dc, ExceptionParam);
- mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+ dump_exception_info(&dc, ExceptionParam, &streamSize);
+ mdDir.Location.DataSize = (ULONG32)streamSize; /*dc.rva - mdDir.Location.Rva;*/
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir));
}
@@ -810,6 +879,14 @@
}
}
+
+
+
+ /* 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.pcs_buffer);
HeapFree(GetProcessHeap(), 0, dc.mem);
HeapFree(GetProcessHeap(), 0, dc.module);