/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Stack.Unix.cpp Date: 2022-1-26 Author: Reece ***/ #include #include "Stack.hpp" #include "Stack.Unix.hpp" #include #include 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 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); } }