mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
- add support for writing the native call stack
This commit is contained in:
parent
27ecae265d
commit
585058c65e
3 changed files with 125 additions and 10 deletions
|
@ -5,4 +5,4 @@
|
||||||
|
|
||||||
JitFuncPtr JitCompile(VMScriptFunction *func);
|
JitFuncPtr JitCompile(VMScriptFunction *func);
|
||||||
void JitDumpLog(FILE *file, VMScriptFunction *func);
|
void JitDumpLog(FILE *file, VMScriptFunction *func);
|
||||||
FString JitCaptureStackTrace();
|
FString JitCaptureStackTrace(int framesToSkip);
|
||||||
|
|
|
@ -2,8 +2,13 @@
|
||||||
#include "jit.h"
|
#include "jit.h"
|
||||||
#include "jitintern.h"
|
#include "jitintern.h"
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifdef WIN32
|
||||||
|
#include <DbgHelp.h>
|
||||||
|
#else
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct JitFuncInfo
|
struct JitFuncInfo
|
||||||
|
@ -291,9 +296,9 @@ void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler)
|
||||||
JitFrames.Push((uint8_t*)table);
|
JitFrames.Push((uint8_t*)table);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
I_Error("RtlAddFunctionTable failed");
|
I_Error("RtlAddFunctionTable failed");
|
||||||
#endif
|
|
||||||
|
|
||||||
JitDebugInfo.Push({ compiler->GetScriptFunction()->PrintableName, compiler->GetScriptFunction()->SourceFileName, startaddr, endaddr });
|
JitDebugInfo.Push({ compiler->GetScriptFunction()->PrintableName, compiler->GetScriptFunction()->SourceFileName, startaddr, endaddr });
|
||||||
|
#endif
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -840,10 +845,114 @@ static int CaptureStackTrace(int max_frames, void **out_frames)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FString JitGetStackFrameName(void *pc)
|
#ifdef WIN32
|
||||||
|
#pragma comment(lib, "dbghelp.lib")
|
||||||
|
class NativeSymbolResolver
|
||||||
{
|
{
|
||||||
FString s;
|
public:
|
||||||
|
NativeSymbolResolver() { SymInitialize(GetCurrentProcess(), nullptr, TRUE); }
|
||||||
|
~NativeSymbolResolver() { SymCleanup(GetCurrentProcess()); }
|
||||||
|
|
||||||
|
FString GetName(void *frame)
|
||||||
|
{
|
||||||
|
FString s;
|
||||||
|
|
||||||
|
unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + 128];
|
||||||
|
IMAGEHLP_SYMBOL64 *symbol64 = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer);
|
||||||
|
memset(symbol64, 0, sizeof(IMAGEHLP_SYMBOL64) + 128);
|
||||||
|
symbol64->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||||
|
symbol64->MaxNameLength = 128;
|
||||||
|
|
||||||
|
DWORD64 displacement = 0;
|
||||||
|
BOOL result = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, symbol64);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
IMAGEHLP_LINE64 line64;
|
||||||
|
DWORD displacement = 0;
|
||||||
|
memset(&line64, 0, sizeof(IMAGEHLP_LINE64));
|
||||||
|
line64.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, &line64);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
s.Format("Called from %s at %s, line %d\n", symbol64->Name, line64.FileName, (int)line64.LineNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.Format("Called from %s\n", symbol64->Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class NativeSymbolResolver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FString GetName(void *frame)
|
||||||
|
{
|
||||||
|
FString s;
|
||||||
|
char **strings;
|
||||||
|
strings = backtrace_symbols(frames, 1);
|
||||||
|
|
||||||
|
// Decode the strings
|
||||||
|
char *ptr = strings[cnt];
|
||||||
|
char *filename = ptr;
|
||||||
|
const char *function = "";
|
||||||
|
|
||||||
|
// Find function name
|
||||||
|
while (*ptr)
|
||||||
|
{
|
||||||
|
if (*ptr == '(') // Found function name
|
||||||
|
{
|
||||||
|
*(ptr++) = 0;
|
||||||
|
function = ptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find offset
|
||||||
|
if (function[0]) // Only if function was found
|
||||||
|
{
|
||||||
|
while (*ptr)
|
||||||
|
{
|
||||||
|
if (*ptr == '+') // Found function offset
|
||||||
|
{
|
||||||
|
*(ptr++) = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*ptr == ')') // Not found function offset, but found, end of function
|
||||||
|
{
|
||||||
|
*(ptr++) = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int status;
|
||||||
|
char *new_function = abi::__cxa_demangle(function, nullptr, nullptr, &status);
|
||||||
|
if (new_function) // Was correctly decoded
|
||||||
|
{
|
||||||
|
function = new_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Format("Called from %s at %s\n", function, filename);
|
||||||
|
|
||||||
|
if (new_function)
|
||||||
|
{
|
||||||
|
free(new_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(strings);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FString JitGetStackFrameName(NativeSymbolResolver *nativeSymbols, void *pc)
|
||||||
|
{
|
||||||
for (unsigned int i = 0; i < JitDebugInfo.Size(); i++)
|
for (unsigned int i = 0; i < JitDebugInfo.Size(); i++)
|
||||||
{
|
{
|
||||||
const auto &info = JitDebugInfo[i];
|
const auto &info = JitDebugInfo[i];
|
||||||
|
@ -856,25 +965,31 @@ FString JitGetStackFrameName(void *pc)
|
||||||
line = info.lines[j].line;
|
line = info.lines[j].line;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
FString s;
|
||||||
|
|
||||||
if (line == -1)
|
if (line == -1)
|
||||||
s.Format("Called from %s at %s\n", info.name.GetChars(), info.filename.GetChars());
|
s.Format("Called from %s at %s\n", info.name.GetChars(), info.filename.GetChars());
|
||||||
else
|
else
|
||||||
s.Format("Called from %s at %s, line %d\n", info.name.GetChars(), info.filename.GetChars(), line);
|
s.Format("Called from %s at %s, line %d\n", info.name.GetChars(), info.filename.GetChars(), line);
|
||||||
|
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return nativeSymbols->GetName(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
FString JitCaptureStackTrace()
|
FString JitCaptureStackTrace(int framesToSkip)
|
||||||
{
|
{
|
||||||
void *frames[32];
|
void *frames[32];
|
||||||
int numframes = CaptureStackTrace(32, frames);
|
int numframes = CaptureStackTrace(32, frames);
|
||||||
|
|
||||||
|
NativeSymbolResolver nativeSymbols;
|
||||||
|
|
||||||
FString s;
|
FString s;
|
||||||
for (int i = 0; i < numframes; i++)
|
for (int i = framesToSkip + 1; i < numframes; i++)
|
||||||
{
|
{
|
||||||
s += JitGetStackFrameName(frames[i]);
|
s += JitGetStackFrameName(&nativeSymbols, frames[i]);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -660,7 +660,7 @@ CVMAbortException::CVMAbortException(EVMAbortException reason, const char *morei
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm_jit)
|
if (vm_jit)
|
||||||
stacktrace = JitCaptureStackTrace();
|
stacktrace = JitCaptureStackTrace(1);
|
||||||
else
|
else
|
||||||
stacktrace = "";
|
stacktrace = "";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue