Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // interface: demagle.hpp
- #pragma once
- char const *
- get_demangled_name(char const * const symbol) noexcept;
- //interface: backtrace.hpp
- #pragma once
- #include <ostream>
- void
- backtrace(std::ostream & _out) noexcept;
- // implementation: demangle.cpp
- #include "demangle.hpp"
- #include <memory>
- #include <cstdlib>
- #include <cxxabi.h>
- namespace
- {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wglobal-constructors"
- #pragma clang diagnostic ignored "-Wexit-time-destructors"
- std::unique_ptr< char, decltype(std::free) & > demangled_name{nullptr, std::free};
- #pragma clang diagnostic pop
- }
- char const *
- get_demangled_name(char const * const symbol) noexcept
- {
- if (!symbol) {
- return "<null>";
- }
- int status = -4;
- demangled_name.reset(abi::__cxa_demangle(symbol, demangled_name.release(), nullptr, &status));
- return ((status == 0) ? demangled_name.get() : symbol);
- }
- // implementation: backtrace.cpp
- #include "backtrace.hpp"
- #include <iostream>
- #include <iomanip>
- #include <limits>
- #include <ostream>
- #include <cstdint>
- #define UNW_LOCAL_ONLY
- #include <libunwind.h>
- namespace
- {
- void
- print_reg(std::ostream & _out, unw_word_t reg) noexcept
- {
- constexpr std::size_t address_width = std::numeric_limits< std::uintptr_t >::digits / 4;
- _out << "0x" << std::setfill('0') << std::setw(address_width) << reg;
- }
- char symbol[1024];
- }
- void
- backtrace(std::ostream & _out) noexcept
- {
- unw_cursor_t cursor;
- unw_context_t context;
- unw_getcontext(&context);
- unw_init_local(&cursor, &context);
- _out << std::hex << std::uppercase;
- while (0 < unw_step(&cursor)) {
- unw_word_t ip = 0;
- unw_get_reg(&cursor, UNW_REG_IP, &ip);
- if (ip == 0) {
- break;
- }
- unw_word_t sp = 0;
- unw_get_reg(&cursor, UNW_REG_SP, &sp);
- print_reg(_out, ip);
- _out << ": (SP:";
- print_reg(_out, sp);
- _out << ") ";
- unw_word_t offset = 0;
- if (unw_get_proc_name(&cursor, symbol, sizeof(symbol), &offset) == 0) {
- _out << "(" << get_demangled_name(symbol) << " + 0x" << offset << ")\n\n";
- } else {
- _out << "-- error: unable to obtain symbol name for this frame\n\n";
- }
- }
- _out << std::flush;
- }
- // implementation: backtrace_on_terminate.hpp
- #include "demangle.hpp"
- #include "backtrace.hpp"
- #include <iostream>
- #include <type_traits>
- #include <exception>
- #include <memory>
- #include <typeinfo>
- #include <cstdlib>
- #include <cxxabi.h>
- namespace
- {
- [[noreturn]]
- void
- backtrace_on_terminate() noexcept;
- static_assert(std::is_same< std::terminate_handler, decltype(&backtrace_on_terminate) >{});
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wglobal-constructors"
- #pragma clang diagnostic ignored "-Wexit-time-destructors"
- std::unique_ptr< std::remove_pointer_t< std::terminate_handler >, decltype(std::set_terminate) & > terminate_handler{std::set_terminate(backtrace_on_terminate), std::set_terminate};
- #pragma clang diagnostic pop
- [[noreturn]]
- void
- backtrace_on_terminate() noexcept
- {
- std::set_terminate(terminate_handler.release()); // to avoid infinite looping if any
- backtrace(std::clog);
- if (std::exception_ptr ep = std::current_exception()) {
- try {
- std::rethrow_exception(ep);
- } catch (std::exception const & e) {
- std::clog << "backtrace: unhandled exception derived from std::exception: " << e.what() << std::endl;
- } catch (...) {
- if (std::type_info * et = abi::__cxa_current_exception_type()) {
- std::clog << "backtrace: unhandled exception type: " << get_demangled_name(et->name()) << std::endl;
- } else {
- std::clog << "backtrace: unhandled unknown exception" << std::endl;
- }
- }
- }
- std::_Exit(EXIT_FAILURE);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment