AuroraRuntime/Source/Debug/Stack.Win32.cpp

142 lines
4.1 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Stack.Win32.cpp
Date: 2022-1-26
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "Stack.hpp"
#include "Stack.Win32.hpp"
#include <Dbghelp.h>
#include <Source/Process/AuProcessMap.hpp>
#include <Source/Process/AuProcessMap.Win32.hpp>
namespace Aurora::Debug
{
static AuUInt GetImageBase(HMODULE mod)
{
if (!mod)
{
return 0;
}
if (mod == INVALID_HANDLE_VALUE)
{
return 0;
}
auto cache = Process::GetFromModuleCache(reinterpret_cast<AuUInt>(mod));
if (!cache.moduleMeta)
{
return 0;
}
return cache.moduleMeta->origVa;
}
void ParseStack(CONTEXT *ctx, StackTrace &backTrace)
{
char buffer[sizeof(SYMBOL_INFO) + (MAX_SYM_NAME + 1) * sizeof(char)] = { 0 };
AuString backTraceBuffer;
HMODULE hModule;
DWORD64 displacement = 0;
HANDLE process = GetCurrentProcess();
STACKFRAME64 stack = { 0 };
CONTEXT cpy = *ctx;
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
#if defined(AURORA_ARCH_X64)
stack.AddrPC.Offset = ctx->Rip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = ctx->Rsp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = ctx->Rbp;
stack.AddrFrame.Mode = AddrModeFlat;
#elif defined(AURORA_ARCH_X86)
stack.AddrPC.Offset = ctx->Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = ctx->Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = ctx->Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
#endif
for (ULONG frame = 0; ; frame++)
{
StackTraceEntry frameCurrent;
bool bResult {};
if (pSymGetModuleBase64 && pStackWalk64)
{
bResult = pStackWalk64
(
#if defined(AURORA_ARCH_X64)
IMAGE_FILE_MACHINE_AMD64,
#else
IMAGE_FILE_MACHINE_I386,
#endif
INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE,
&stack,
&cpy,
NULL,
pSymFunctionTableAccess64,
pSymGetModuleBase64,
NULL
);
}
if (!bResult)
{
break;
}
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
frameCurrent.address = stack.AddrPC.Offset;
frameCurrent.relAddress = frameCurrent.address;
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)(stack.AddrPC.Offset), &hModule))
{
if (hModule != NULL)
{
frameCurrent.module = Process::ModuleToPath(hModule);
frameCurrent.relAddress = frameCurrent.relAddress - reinterpret_cast<AuUInt>(hModule) + GetImageBase(hModule);
}
}
#if defined(DEBUG) || defined(STAGING)
IMAGEHLP_LINE64 line;
DWORD disp;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (pSymGetLineFromAddr64)
{
if (pSymGetLineFromAddr64(process, stack.AddrPC.Offset, &disp, &line))
{
frameCurrent.file = AuMakeTuple(line.FileName, line.LineNumber, 0);
}
}
#endif
backTrace.push_back(frameCurrent);
}
}
StackTrace PlatformWalkCallStack()
{
StackTrace ret;
CONTEXT ctx {};
ctx.ContextFlags = CONTEXT_ALL;
if (!GetThreadContext(GetCurrentThread(), &ctx))
{
return {};
}
ParseStack(&ctx, ret);
return ret;
}
}