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