diff --git a/aurora-main/cmake/AuroraDawnProvider.cmake b/aurora-main/cmake/AuroraDawnProvider.cmake index 35214a0..6503cf6 100644 --- a/aurora-main/cmake/AuroraDawnProvider.cmake +++ b/aurora-main/cmake/AuroraDawnProvider.cmake @@ -185,7 +185,11 @@ elseif (_aurora_dawn_provider STREQUAL "package") endif () endif () endif () - message(STATUS "aurora: Fetching prebuilt Dawn package from ${AURORA_DAWN_PACKAGE_URL}") + if (FETCHCONTENT_SOURCE_DIR_DAWN_PREBUILT) + message(STATUS "aurora: Using the local Dawn package ${FETCHCONTENT_SOURCE_DIR_DAWN_PREBUILT}") + else () + message(STATUS "aurora: Fetching prebuilt Dawn package from ${AURORA_DAWN_PACKAGE_URL}") + endif () set(_dawn_prebuilt_hash_argument "") if (AURORA_DAWN_PACKAGE_URL_HASH) diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index 5a61273..abc2e9b 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -49,6 +49,14 @@ #include #endif #include +#if defined(__GLIBC__) +// The host side of a native crash on desktop Linux: the faulting thread, its pc and lr, and a +// backtrace, each as module + offset for addr2line against the unstripped executable. +#include +#include +#include +#include +#endif #endif #include "abi_bridge.h" @@ -766,6 +774,23 @@ void SetRuntimeExitCodeImpl(int code) { namespace { +#if defined(__GLIBC__) +// One host code address as module + offset (what `addr2line -f -C -e ` takes), +// with the nearest exported symbol when there is one. +void LogHostAddress(const char* label, int index, const void* address) { + Dl_info info{}; + if (address != nullptr && dladdr(address, &info) != 0 && info.dli_fname != nullptr) { + const char* slash = std::strrchr(info.dli_fname, '/'); + const char* module = slash != nullptr ? slash + 1 : info.dli_fname; + const auto offset = reinterpret_cast(address) - reinterpret_cast(info.dli_fbase); + RT_LOGF(RT_TAG_RUNTIME, "%s%d %p %s+0x%zx%s%s\n", label, index, address, module, static_cast(offset), + info.dli_sname != nullptr ? " " : "", info.dli_sname != nullptr ? info.dli_sname : ""); + } else { + RT_LOGF(RT_TAG_RUNTIME, "%s%d %p\n", label, index, address); + } +} +#endif + void DumpHostStackTrace() { #if defined(_WIN32) static std::atomic_flag s_inProgress = ATOMIC_FLAG_INIT; @@ -776,6 +801,19 @@ void DumpHostStackTrace() { std::fputs(trace.c_str(), stderr); std::fflush(stderr); s_inProgress.clear(); +#elif defined(__GLIBC__) + static std::atomic_flag s_inProgress = ATOMIC_FLAG_INIT; + if (s_inProgress.test_and_set()) { + return; + } + std::array frames{}; + const int count = backtrace(frames.data(), static_cast(frames.size())); + RT_LOGF(RT_TAG_RUNTIME, "Host stack trace (%d frames):\n", count); + for (int i = 0; i < count; ++i) { + LogHostAddress(" #", i, frames[static_cast(i)]); + } + std::fflush(stderr); + s_inProgress.clear(); #else RT_LOGF(RT_TAG_RUNTIME, "Host stack trace unavailable on this platform\n"); std::fflush(stderr); @@ -1231,6 +1269,22 @@ void PosixMemoryFaultHandler(int sig, siginfo_t* info, void* ucontextVoid) { popupDetails << ".\n\nThe process transcript and crash log contain the full CPU and stack " "diagnostics."; ShowRuntimeFatalPopup("a native crash occurred", popupDetails.str()); +#if defined(__GLIBC__) + { + char threadName[32] = "?"; + pthread_getname_np(pthread_self(), threadName, sizeof(threadName)); + RT_LOGF(RT_TAG_RUNTIME, "Faulting host thread: '%s' (tid %ld)\n", threadName, static_cast(gettid())); + if (ucontextVoid != nullptr) { + const auto* uc = static_cast(ucontextVoid); +#if defined(__aarch64__) + LogHostAddress("Faulting pc #", 0, reinterpret_cast(uc->uc_mcontext.pc)); + LogHostAddress("Faulting lr #", 0, reinterpret_cast(uc->uc_mcontext.regs[30])); +#elif defined(__x86_64__) + LogHostAddress("Faulting pc #", 0, reinterpret_cast(uc->uc_mcontext.gregs[REG_RIP])); +#endif + } + } +#endif DumpHostStackTrace(); WriteFatalLogImpl(sig == SIGBUS ? "sigbus" : "sigsegv");