diff --git a/.gitmodules b/.gitmodules index c8edf6a..c122359 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "fmt"] path = fmt url = https://github.com/fmtlib/fmt +[submodule "libbacktrace"] + path = libbacktrace + url = https://github.com/status-im/libbacktrace.git diff --git a/CMakeLists.txt b/CMakeLists.txt index c8a7410..53d9a7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,13 +15,38 @@ add_library(logvisor lib/logvisor.cpp include/logvisor/logvisor.hpp) -target_link_libraries(logvisor PUBLIC fmt) -if(NX) - target_link_libraries(logvisor PUBLIC debug nxd optimized nx) +if(APPLE OR UNIX) + include(ExternalProject) + find_package(Git REQUIRED) + find_program(MAKE_EXE NAMES gmake make) + ExternalProject_Add( + project_libbacktrace + PREFIX ${PROJECT_BINARY_DIR}/libbacktrace + GIT_REPOSITORY https://github.com/status-im/libbacktrace.git + GIT_TAG 2e878a38dd7144c84b665019b1085ea38ebe56d1 + CONFIGURE_COMMAND ${PROJECT_BINARY_DIR}/libbacktrace/src/project_libbacktrace/configure --enable-host-shared --prefix=${PROJECT_BINARY_DIR}/libbacktrace/install --enable-shared=no --enable-static=yes + BUILD_COMMAND ${MAKE_EXE} + INSTALL_COMMAND ${MAKE_EXE} install + BUILD_IN_SOURCE 1 + ) + add_library(libbacktrace STATIC IMPORTED GLOBAL) + set_target_properties(libbacktrace PROPERTIES IMPORTED_LOCATION "${PROJECT_BINARY_DIR}/libbacktrace/install/lib/libbacktrace.a") + set_target_properties(libbacktrace PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_BINARY_DIR}/libbacktrace/install/include") + # Hack for INTERFACE_INCLUDE_DIRECTORIES propagation + # https://gitlab.kitware.com/cmake/cmake/-/issues/15052 + file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/libbacktrace/install/include") + add_dependencies(libbacktrace project_libbacktrace) + set(BACKTRACE_LIBS libbacktrace) else() - target_link_libraries(logvisor PUBLIC ${CMAKE_DL_LIBS}) + set(BACKTRACE_LIBS "") endif() +target_link_libraries(logvisor PUBLIC fmt) +if(NX) + target_link_libraries(logvisor PUBLIC debug nxd optimized nx) +else() + target_link_libraries(logvisor PRIVATE ${CMAKE_DL_LIBS} ${BACKTRACE_LIBS}) +endif() target_include_directories(logvisor PUBLIC $) install(DIRECTORY include/logvisor DESTINATION include) diff --git a/lib/logvisor.cpp b/lib/logvisor.cpp index 42cfe90..bf2d3e7 100644 --- a/lib/logvisor.cpp +++ b/lib/logvisor.cpp @@ -178,57 +178,26 @@ void KillProcessTree() { void KillProcessTree() {} -#include -[[noreturn]] void logvisorAbort() { - void* array[128]; - size_t size = backtrace(array, 128); +#include - constexpr size_t exeBufSize = 1024 + 1; - char exeNameBuffer[exeBufSize] = {}; +void backtrace_error(void* data, const char* msg, int errnum) { + std::fprintf(stderr, "Error retrieving stack trace: %d %s\n", errnum, msg); +} -#if __linux__ - readlink("/proc/self/exe", exeNameBuffer, exeBufSize); -#endif - -#if __APPLE__ - std::string cmdLineStr = fmt::format(FMT_STRING("atos -p {}"), getpid()); -#else - std::string cmdLineStr = fmt::format(FMT_STRING("2>/dev/null addr2line -C -f -e \"{}\""), exeNameBuffer); -#endif - - for (size_t i = 0; i < size; i++) { -#if __linux__ - Dl_info dlip; - if (dladdr(array[i], &dlip)) - cmdLineStr += fmt::format(FMT_STRING(" 0x{:016X}"), (uintptr_t)((uint8_t*)array[i] - (uint8_t*)dlip.dli_fbase)); - else - cmdLineStr += fmt::format(FMT_STRING(" 0x{:016X}"), (uintptr_t)array[i]); -#else - cmdLineStr += fmt::format(FMT_STRING(" 0x{:016X}"), (uintptr_t)array[i]); -#endif +int backtrace_callback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function) { + int status = -255; + char* demangledName = abi::__cxa_demangle(function, nullptr, nullptr, &status); + std::fprintf(stderr, "0x%lX %s\n\t%s:%d\n", pc, status == 0 ? demangledName : function, filename, lineno); + if (demangledName != nullptr) { + std::free(demangledName); } + return 0; +} - FILE* fp = popen(cmdLineStr.c_str(), "r"); - if (fp) { - char readBuf[256]; - size_t readSz; - while ((readSz = fread(readBuf, 1, 256, fp))) - std::fwrite(readBuf, 1, readSz, stderr); - pclose(fp); - } else { - for (size_t i = 0; i < size; i++) { - std::fputs("- ", stderr); - Dl_info dlip; - if (dladdr(array[i], &dlip)) { - int status; - char* demangledName = abi::__cxa_demangle(dlip.dli_sname, nullptr, nullptr, &status); - std::fprintf(stderr, "%p(%s+%p)\n", dlip.dli_saddr, demangledName ? demangledName : dlip.dli_sname, - (void*)((uint8_t*)array[i] - (uint8_t*)dlip.dli_fbase)); - std::free(demangledName); - } else { - std::fprintf(stderr, "%p\n", array[i]); - } - } +[[noreturn]] void logvisorAbort() { + backtrace_state* state = backtrace_create_state(nullptr, 0, backtrace_error, nullptr); + if (state != nullptr) { + backtrace_full(state, 0, backtrace_callback, backtrace_error, nullptr); } std::fflush(stderr);