dbghelp: MiniDumpWriteDump called from exception handler.

- MiniDumpWriteDump was unable to provide stack information for the current
  thread, hence did produce unusable minidump when a programs generates the
  minidump from its own exception handler.
- We now support this if the current thread calls MiniDumpWriteDump from an
  exception handler and provides the exception information.
This commit is contained in:
Eric Pouech 2007-02-19 23:09:24 +01:00 committed by Alexandre Julliard
parent 93494f2ac0
commit fa9be99568
1 changed files with 61 additions and 36 deletions

View File

@ -112,15 +112,45 @@ static BOOL fetch_process_info(struct dump_context* dc)
return FALSE; return FALSE;
} }
static void fetch_thread_stack(struct dump_context* dc, void* teb_addr,
const CONTEXT* ctx, MINIDUMP_MEMORY_DESCRIPTOR* mmd)
{
NT_TIB tib;
if (ReadProcessMemory(dc->hProcess, teb_addr, &tib, sizeof(tib), NULL))
{
#ifdef __i386__
/* limiting the stack dumping to the size actually used */
if (ctx->Esp)
mmd->StartOfMemoryRange = (ctx->Esp - 4);
else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
#elif defined(__powerpc__)
if (ctx->Iar)
mmd->StartOfMemoryRange = ctx->Iar - 4;
else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
#elif defined(__x86_64__)
if (ctx->Rsp)
mmd->StartOfMemoryRange = (ctx->Rsp - 8);
else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
#else
#error unsupported CPU
#endif
mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange;
}
}
/****************************************************************** /******************************************************************
* fetch_thread_info * fetch_thread_info
* *
* fetches some information about thread of id 'tid' * fetches some information about thread of id 'tid'
*/ */
static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx, static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
const MINIDUMP_EXCEPTION_INFORMATION* except,
MINIDUMP_THREAD* mdThd, CONTEXT* ctx) MINIDUMP_THREAD* mdThd, CONTEXT* ctx)
{ {
NT_TIB tib;
DWORD tid = dc->spi->ti[thd_idx].dwThreadID; DWORD tid = dc->spi->ti[thd_idx].dwThreadID;
HANDLE hThread; HANDLE hThread;
THREAD_BASIC_INFORMATION tbi; THREAD_BASIC_INFORMATION tbi;
@ -149,40 +179,35 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
&tbi, sizeof(tbi), NULL) == STATUS_SUCCESS) &tbi, sizeof(tbi), NULL) == STATUS_SUCCESS)
{ {
mdThd->Teb = (ULONG_PTR)tbi.TebBaseAddress; mdThd->Teb = (ULONG_PTR)tbi.TebBaseAddress;
if (tbi.ExitStatus == STILL_ACTIVE && tid != GetCurrentThreadId() && if (tbi.ExitStatus == STILL_ACTIVE)
(mdThd->SuspendCount = SuspendThread(hThread)) != (DWORD)-1)
{ {
mdThd->SuspendCount--; if (tid != GetCurrentThreadId() &&
ctx->ContextFlags = CONTEXT_FULL; (mdThd->SuspendCount = SuspendThread(hThread)) != (DWORD)-1)
if (!GetThreadContext(hThread, ctx))
memset(ctx, 0, sizeof(*ctx));
if (ReadProcessMemory(dc->hProcess, tbi.TebBaseAddress,
&tib, sizeof(tib), NULL))
{ {
#ifdef __i386__ mdThd->SuspendCount--;
/* limiting the stack dumping to the size actually used */ ctx->ContextFlags = CONTEXT_FULL;
if (ctx->Esp) if (!GetThreadContext(hThread, ctx))
mdThd->Stack.StartOfMemoryRange = (ctx->Esp - 4); memset(ctx, 0, sizeof(*ctx));
else
mdThd->Stack.StartOfMemoryRange = (ULONG_PTR)tib.StackLimit; fetch_thread_stack(dc, tbi.TebBaseAddress, ctx, &mdThd->Stack);
#elif defined(__powerpc__) ResumeThread(hThread);
if (ctx->Iar) }
mdThd->Stack.StartOfMemoryRange = ctx->Iar - 4; else if (tid == GetCurrentThreadId() && except)
else {
mdThd->Stack.StartOfMemoryRange = (ULONG_PTR)tib.StackLimit; CONTEXT lctx, *pctx;
#elif defined(__x86_64__) if (except->ClientPointers)
if (ctx->Rsp) {
mdThd->Stack.StartOfMemoryRange = (ctx->Rsp - 8); EXCEPTION_POINTERS ep;
else
mdThd->Stack.StartOfMemoryRange = (ULONG_PTR)tib.StackLimit; ReadProcessMemory(dc->hProcess, except->ExceptionPointers,
#else &ep, sizeof(ep), NULL);
#error unsupported CPU ReadProcessMemory(dc->hProcess, ep.ContextRecord,
#endif &ctx, sizeof(ctx), NULL);
mdThd->Stack.Memory.DataSize = (ULONG_PTR)tib.StackBase - pctx = &lctx;
mdThd->Stack.StartOfMemoryRange; }
else pctx = except->ExceptionPointers->ContextRecord;
fetch_thread_stack(dc, tbi.TebBaseAddress, pctx, &mdThd->Stack);
} }
ResumeThread(hThread);
} }
} }
CloseHandle(hThread); CloseHandle(hThread);
@ -347,7 +372,6 @@ static void dump_exception_info(struct dump_context* dc,
ep.ContextRecord, &ctx, sizeof(ctx), NULL); ep.ContextRecord, &ctx, sizeof(ctx), NULL);
prec = &rec; prec = &rec;
pctx = &ctx; pctx = &ctx;
} }
else else
{ {
@ -516,7 +540,8 @@ static void dump_system_info(struct dump_context* dc)
* *
* Dumps into File the information about running threads * Dumps into File the information about running threads
*/ */
static void dump_threads(struct dump_context* dc) static void dump_threads(struct dump_context* dc,
const MINIDUMP_EXCEPTION_INFORMATION* except)
{ {
MINIDUMP_THREAD mdThd; MINIDUMP_THREAD mdThd;
MINIDUMP_THREAD_LIST mdThdList; MINIDUMP_THREAD_LIST mdThdList;
@ -533,7 +558,7 @@ static void dump_threads(struct dump_context* dc)
for (i = 0; i < dc->spi->dwThreadCount; i++) for (i = 0; i < dc->spi->dwThreadCount; i++)
{ {
fetch_thread_info(dc, i, &mdThd, &ctx); fetch_thread_info(dc, i, except, &mdThd, &ctx);
flags_out = ThreadWriteThread | ThreadWriteStack | ThreadWriteContext | flags_out = ThreadWriteThread | ThreadWriteStack | ThreadWriteContext |
ThreadWriteInstructionWindow; ThreadWriteInstructionWindow;
@ -713,7 +738,7 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile,
mdDir.StreamType = ThreadListStream; mdDir.StreamType = ThreadListStream;
mdDir.Location.Rva = dc.rva; mdDir.Location.Rva = dc.rva;
dump_threads(&dc); dump_threads(&dc, ExceptionParam);
mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
&mdDir, sizeof(mdDir)); &mdDir, sizeof(mdDir));