__declspec(noinline)
size_t stack_walk(void** buffer, size_t size, CONTEXT* context = 0)
{
CONTEXT here;
if(context == 0)
{
::RtlCaptureContext(&here);
context = &here;
}
UNWIND_HISTORY_TABLE unwindHist;
memset(&unwindHist, 0x00, sizeof(unwindHist));
void** pos = buffer;
for(; (context->Rip != 0) && (size != 0); ++pos, --size)
{
ULONG64 imgBase = 0;
PRUNTIME_FUNCTION func = ::RtlLookupFunctionEntry(context->Rip, &imgBase, &unwindHist);
KNONVOLATILE_CONTEXT_POINTERS nvContext;
memset(&nvContext, 0x00, sizeof(nvContext));
void* handlerData = 0;
ULONG64 establisherFrame = 0;
if(func == 0)
{
*pos = reinterpret_cast<void*>(context->Rip);
context->Rip = static_cast<ULONG64>(*reinterpret_cast<const ULONG64*>(context->Rsp));
context->Rsp += 8;
}
else
{
*pos = reinterpret_cast<void*>(context->Rip);
::RtlVirtualUnwind(0x00,
imgBase,
context->Rip,
func,
context,
&handlerData,
&establisherFrame,
&nvContext);
}
}
return pos - buffer;
}