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:
parent
93494f2ac0
commit
fa9be99568
|
@ -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));
|
||||||
|
|
Loading…
Reference in New Issue