135 lines
3.1 KiB
C++
135 lines
3.1 KiB
C++
/***
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: Stack.Unix.cpp
|
|
Date: 2022-1-26
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "Stack.hpp"
|
|
#include "Stack.Unix.hpp"
|
|
#include <libunwind.h>
|
|
#include <dlfcn.h>
|
|
|
|
namespace Aurora::Debug
|
|
{
|
|
static void TryComplete(StackTraceEntry &entry)
|
|
{
|
|
|
|
}
|
|
|
|
static StackTrace DumpContext(unw_context_t *uc)
|
|
{
|
|
StackTrace ret;
|
|
|
|
unw_cursor_t cursor;
|
|
unw_word_t ip;
|
|
|
|
::unw_init_local(&cursor, uc);
|
|
|
|
while (::unw_step(&cursor) > 0)
|
|
{
|
|
StackTraceEntry entry;
|
|
|
|
::unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
|
|
|
// module
|
|
{
|
|
unw_word_t off;
|
|
char procName[512];
|
|
|
|
if (unw_get_proc_name(&cursor, procName, AuArraySize(procName), &off) == 0)
|
|
{
|
|
AuString str;
|
|
str = AuString(procName, strlen(procName));
|
|
str += fmt::format("+0x{:x}", off);
|
|
entry.label = str;
|
|
}
|
|
}
|
|
|
|
{
|
|
Dl_info dlinfo;
|
|
AuSInt originalIP {};
|
|
AuUInt moduleAddress {};
|
|
|
|
const char *dllPathName {};
|
|
|
|
if (::dladdr((const void *)ip, &dlinfo))
|
|
{
|
|
dllPathName = dlinfo.dli_fname;
|
|
moduleAddress = (AuUInt)dlinfo.dli_fbase;
|
|
originalIP = (AuUInt)ip - moduleAddress;
|
|
}
|
|
|
|
entry.address = ip;
|
|
entry.relAddress = originalIP;
|
|
|
|
if (dllPathName)
|
|
{
|
|
entry.module = dllPathName;
|
|
}
|
|
}
|
|
|
|
AuTryInsert(ret, entry);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
StackTrace DumpContextPlatform(ucontext_t &uc)
|
|
{
|
|
// VALID:
|
|
// Linux: https://github.com/libunwind/libunwind/blob/3be832395426b72248969247a4a66e3c3623578d/include/libunwind-x86.h#L170
|
|
|
|
// ???
|
|
// MACOS: https://github.com/JuliaLang/libosxunwind/blob/master/include/libunwind.h#L57
|
|
return DumpContext((unw_context_t *)&uc);
|
|
}
|
|
|
|
StackTrace DumpContext(ucontext_t &uc)
|
|
{
|
|
return DumpContextPlatform(uc);
|
|
}
|
|
|
|
StackTrace DumpContext(void *pContext)
|
|
{
|
|
return DumpContext((unw_context_t *)pContext);
|
|
}
|
|
|
|
StackTrace PlatformWalkCallStack()
|
|
{
|
|
#if 0
|
|
StackTrace ret;
|
|
void *ips[1024];
|
|
|
|
int count = ::backtrace(ips, AuArraySize(ips));
|
|
|
|
auto messages = ::backtrace_symbols(ips, count);
|
|
if (!messages)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
StackTraceEntry entry;
|
|
|
|
entry.address = AuUInt64(ips[i]);
|
|
entry.label = AuUInt64(messages[i]);
|
|
|
|
TryComplete(entry);
|
|
|
|
AuTryInsert(ret, entry);
|
|
}
|
|
|
|
free(messages);
|
|
|
|
return ret;
|
|
#endif
|
|
|
|
::unw_context_t uc;
|
|
::unw_getcontext(&uc);
|
|
|
|
return DumpContext(&uc);
|
|
}
|
|
} |