From 8a805fc8290a7ea9df361ec7d835b0e0ef4f9370 Mon Sep 17 00:00:00 2001 From: Jeremy Rifkin <51220084+jeremy-rifkin@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:53:04 -0500 Subject: [PATCH] Some more implementation --- include/cpptrace/from_current.hpp | 95 ++++++++++++++++++------------- src/cpptrace.cpp | 55 ++++++++++++++++-- 2 files changed, 108 insertions(+), 42 deletions(-) diff --git a/include/cpptrace/from_current.hpp b/include/cpptrace/from_current.hpp index 3b1a6ff..17b1fcd 100644 --- a/include/cpptrace/from_current.hpp +++ b/include/cpptrace/from_current.hpp @@ -1,51 +1,70 @@ +#ifndef CPPTRACE_FROM_CURRENT_HPP +#define CPPTRACE_FROM_CURRENT_HPP + #include -#include -#include -#include -#include - #ifdef _MSC_VER - +#include #else + #define CPPTRACE_LIBSTDCPP 0 + #define CPPTRACE_LIBCPP 0 + #if defined(__GLIBCXX__) || defined(__GLIBCPP__) + #undef CPPTRACE_LIBSTDCPP + #undef CPPTRACE_LIBCPP + #define CPPTRACE_LIBSTDCPP 1 + #elif defined(_LIBCPP_VERSION) + #undef CPPTRACE_LIBSTDCPP + #undef CPPTRACE_LIBCPP + #define CPPTRACE_LIBCPP 1 + #else + #error "Cpptrace from_current: Unsupported C++ standard library" + #endif +#endif + +#include + +// #if defined(__clang__) +// // pass +// #elif defined(__GNUC__) || defined(__GNUG__) +// // pass +// #elif defined(_MSC_VER) +// // pass +// #else +// #error "Cpptrace from_current: Unsupported C++ compiler" +// #endif namespace cpptrace { const raw_trace& raw_trace_from_current_exception(); const stacktrace& from_current_exception(); - class unwind_interceptor { - public: - virtual ~unwind_interceptor(); - }; + namespace detail { + #ifdef _MSC_VER + CPPTRACE_FORCE_NO_INLINE int exception_filter(); + #else + class unwind_interceptor { + public: + virtual ~unwind_interceptor(); + }; + #endif + } } -/* - -CPPTRACE_TRY { - foo(); -} CPPTRACE_CATCH(std::runtime_error& e) { - fmt::println("Exception occurred: {}", e.get().what()); - fmt::println("{}", cpptrace::from_current_exception()); -} - -try { - try { - foo(); - } catch(const ::cpptrace::unwind_interceptor&) {} -} catch(std::runtime_error& e) { - fmt::println("Exception occurred: {}", e.get().what()); - fmt::println("{}", cpptrace::from_current_exception()); -} - -*/ - -#define CPPTRACE_TRY \ - try { \ - try - -#define CPPTRACE_CATCH(param) \ - catch(cpptrace::unwind_interceptor&) { puts("shouldn't be here"); } \ - } catch(param) - +#ifdef _MSC_VER + #define CPPTRACE_TRY \ + try { \ + [&]() { \ + __try + #define CPPTRACE_CATCH(param) \ + __except(::cpptrace::detail::exception_filter()) { puts("shouldn't be here"); } \ + }(); \ + } catch(param) +#else + #define CPPTRACE_TRY \ + try { \ + try + #define CPPTRACE_CATCH(param) \ + catch(::cpptrace::detail::unwind_interceptor&) { puts("shouldn't be here"); } \ + } catch(param) +#endif #endif diff --git a/src/cpptrace.cpp b/src/cpptrace.cpp index 272ceea..4423a89 100644 --- a/src/cpptrace.cpp +++ b/src/cpptrace.cpp @@ -12,6 +12,11 @@ #include #include +#ifndef _MSC_VER +#include +#include +#endif + #include "symbols/symbols.hpp" #include "unwind/unwind.hpp" #include "demangle/demangle.hpp" @@ -697,10 +702,11 @@ namespace cpptrace { } } - unwind_interceptor::~unwind_interceptor() = default; - namespace detail { - inline thread_local lazy_trace_holder current; + + thread_local lazy_trace_holder current; + + #ifndef _MSC_VER CPPTRACE_FORCE_NO_INLINE bool foobar(const std::type_info* this_ptr, const std::type_info* t, void**, unsigned) { std::cout<<"--------UNGABUNGA!!-------- "<name()<<" "<name()< new_vtable; void clobber_type_info(const std::type_info& info) { void* type_info_pointer = const_cast(reinterpret_cast(&info)); void* type_info_vtable_pointer = *reinterpret_cast(type_info_pointer); - type_info_vtable_pointer = reinterpret_cast(reinterpret_cast(type_info_vtable_pointer) - 2); // adjust offset + // adjust offset, some info lies before the vtable pointer + // for libstdc++ this looks like + // 0x7ffff7f89d18 <_ZTVN10__cxxabiv117__class_type_infoE>: 0x0000000000000000 0x00007ffff7f89d00 + // [offset ][typeinfo pointer ] + // 0x7ffff7f89d28 <_ZTVN10__cxxabiv117__class_type_infoE+16>: 0x00007ffff7dd65a0 0x00007ffff7dd65c0 + // [base destructor ][deleting dtor ] + // 0x7ffff7f89d38 <_ZTVN10__cxxabiv117__class_type_infoE+32>: 0x00007ffff7dd8f10 0x00007ffff7dd8f10 + // [__is_pointer_p ][__is_function_p ] + // 0x7ffff7f89d48 <_ZTVN10__cxxabiv117__class_type_infoE+48>: 0x00007ffff7dd6640 0x00007ffff7dd6500 + // [__do_catch ][__do_upcast ] + // 0x7ffff7f89d58 <_ZTVN10__cxxabiv117__class_type_infoE+64>: 0x00007ffff7dd65e0 0x00007ffff7dd66d0 + // [__do_upcast ][__do_dyncast ] + // 0x7ffff7f89d68 <_ZTVN10__cxxabiv117__class_type_infoE+80>: 0x00007ffff7dd6580 0x00007ffff7f8abe8 + // [__do_find_public_src][other ] + // In libc++ the layout is + // [offset ][typeinfo pointer ] + // [base destructor ][deleting dtor ] + // [noop1 ][noop2 ] + // [can_catch ][search_above_dst ] + // [search_below_dst ][has_unambiguous_public_base] + // Relevant documentation/implementation: + // https://itanium-cxx-abi.github.io/cxx-abi/abi.html + // libstdc++ + // https://github.com/gcc-mirror/gcc/blob/b13e34699c7d27e561fcfe1b66ced1e50e69976f/libstdc%252B%252B-v3/libsupc%252B%252B/typeinfo + // https://github.com/gcc-mirror/gcc/blob/b13e34699c7d27e561fcfe1b66ced1e50e69976f/libstdc%252B%252B-v3/libsupc%252B%252B/class_type_info.cc + // libc++ + // https://github.com/llvm/llvm-project/blob/648f4d0658ab00cf1e95330c8811aaea9481a274/libcxx/include/typeinfo + // https://github.com/llvm/llvm-project/blob/648f4d0658ab00cf1e95330c8811aaea9481a274/libcxxabi/src/private_typeinfo.h + // + type_info_vtable_pointer = reinterpret_cast(reinterpret_cast(type_info_vtable_pointer) - 2); memcpy(new_vtable.data(), type_info_vtable_pointer, 11 * sizeof(void*)); new_vtable[6] = reinterpret_cast(foobar); @@ -745,6 +782,16 @@ namespace cpptrace { clobber_type_info(typeid(cpptrace::unwind_interceptor)); return 0; }(); + + #else + + CPPTRACE_FORCE_NO_INLINE int exception_filter() { + std::cout<<"--------UNGABUNGA WINDOWS!!-------- "<