diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index d0970a2..0b6c3d2 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -12,7 +12,6 @@ project ; lib dl : : shared ; -lib unwind : : shared ; lib Dbghelp ; actions mp_simple_run_action @@ -29,9 +28,6 @@ rule mp-run-simple ( sources + : args * : input-files * : requirements * : targe alias $(target-name) : $(target-name).output ; } -mp-run-simple has_libunwind.cpp : : : : libunwind ; -explicit libunwind ; - mp-run-simple has_backtrace.cpp : : : : backtrace ; explicit backtrace ; @@ -51,21 +47,6 @@ lib boost_stacktrace_noop boost-install boost_stacktrace_noop ; -lib boost_stacktrace_libunwind - : # sources - ../src/libunwind.cpp - : # requirements - all - unwind - shared:BOOST_STACKTRACE_DYN_LINK=1 - [ check-target-builds ../build//libunwind : : no ] - : # default build - : # usage-requirements - #shared:BOOST_STACKTRACE_DYN_LINK=1 - ; - -boost-install boost_stacktrace_libunwind ; - lib boost_stacktrace_backtrace : # sources ../src/backtrace.cpp diff --git a/build/has_libunwind.cpp b/build/has_libunwind.cpp deleted file mode 100644 index 08550bc..0000000 --- a/build/has_libunwind.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright Antony Polukhin, 2016. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#define UNW_LOCAL_ONLY -#include - -int main() {} diff --git a/include/boost/stacktrace/detail/backend.hpp b/include/boost/stacktrace/detail/backend.hpp index 6ae8fd7..438cd3d 100644 --- a/include/boost/stacktrace/detail/backend.hpp +++ b/include/boost/stacktrace/detail/backend.hpp @@ -29,9 +29,7 @@ && !defined(BOOST_STACKTRACE_USE_BACKTRACE) &&!defined(BOOST_STACKTRACE_USE_HEADER) #if defined(__has_include) && (!defined(__GNUC__) || __GNUC__ > 4 || BOOST_CLANG) -# if __has_include() -# define BOOST_STACKTRACE_USE_LIBUNWIND -# elif __has_include() +# if __has_include() # define BOOST_STACKTRACE_USE_BACKTRACE # elif __has_include("Dbgeng.h") # define BOOST_STACKTRACE_USE_WINDBG @@ -70,10 +68,10 @@ class backend: boost::noncopyable { public: BOOST_STACKTRACE_FUNCTION backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_NOEXCEPT; - BOOST_STACKTRACE_FUNCTION std::string get_name(std::size_t frame_no) const; + BOOST_STACKTRACE_FUNCTION static std::string get_name(const void* addr); BOOST_STACKTRACE_FUNCTION const void* get_address(std::size_t frame_no) const BOOST_NOEXCEPT; - BOOST_STACKTRACE_FUNCTION std::string get_source_file(std::size_t frame_no) const; - BOOST_STACKTRACE_FUNCTION std::size_t get_source_line(std::size_t frame_no) const BOOST_NOEXCEPT; + BOOST_STACKTRACE_FUNCTION static std::string get_source_file(const void* addr); + BOOST_STACKTRACE_FUNCTION static std::size_t get_source_line(const void* addr); BOOST_STACKTRACE_FUNCTION bool operator< (const backend& rhs) const BOOST_NOEXCEPT; BOOST_STACKTRACE_FUNCTION bool operator==(const backend& rhs) const BOOST_NOEXCEPT; diff --git a/include/boost/stacktrace/detail/backend.ipp b/include/boost/stacktrace/detail/backend.ipp index 6f42564..1b7fda2 100644 --- a/include/boost/stacktrace/detail/backend.ipp +++ b/include/boost/stacktrace/detail/backend.ipp @@ -18,8 +18,6 @@ # include #elif defined(BOOST_STACKTRACE_USE_WINDBG) # include -#elif defined(BOOST_STACKTRACE_USE_LIBUNWIND) -# include #elif defined(BOOST_STACKTRACE_USE_BACKTRACE) # include #else diff --git a/include/boost/stacktrace/detail/backend_libunwind.hpp b/include/boost/stacktrace/detail/backend_libunwind.hpp deleted file mode 100644 index 84d2469..0000000 --- a/include/boost/stacktrace/detail/backend_libunwind.hpp +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright Antony Polukhin, 2016. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP -#define BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - -#define UNW_LOCAL_ONLY -#include - -namespace boost { namespace stacktrace { namespace detail { - -struct bt_pair { - std::string name; - const void* addr; -}; - -inline bool operator< (const bt_pair& lhs, const bt_pair& rhs) BOOST_NOEXCEPT { - return lhs.addr < rhs.addr; -} - -inline bool operator== (const bt_pair& lhs, const bt_pair& rhs) BOOST_NOEXCEPT { - return lhs.addr == rhs.addr; -} - -struct backtrace_holder { - std::size_t frames_count; - boost::shared_ptr frames; -}; - -inline std::string get_frame_impl(unw_cursor_t& cursor) { - std::string res; - unw_word_t offp; - char data[256]; - const int ret = unw_get_proc_name(&cursor, data, sizeof(data) / sizeof(char), &offp); - - if (ret == -UNW_ENOMEM) { - res.resize(sizeof(data) * 2); - do { - const int ret2 = unw_get_proc_name(&cursor, &res[0], res.size(), &offp); - if (ret2 == -UNW_ENOMEM) { - res.resize(res.size() * 2); - } else if (ret2 == 0) { - break; - } else { - res = data; - return res; - } - } while(1); - } else if (ret == 0) { - res = data; - } else { - return res; - } - - boost::core::scoped_demangled_name demangled(res.data()); - if (demangled.get()) { - res = demangled.get(); - } else { - res.resize( std::strlen(res.data()) ); // Note: here res is \0 terminated, but size() not equal to strlen - } - - res += " +"; - res += to_hex_array(offp).data(); - - return res; -} - - - -backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_NOEXCEPT - : data_(static_cast(memory)) -{ - new (data_) backtrace_holder(); - data_->frames_count = 0; - hash_code = 0; - - unw_context_t uc; - if (unw_getcontext(&uc) != 0) { - return; - } - - { // Counting frames_count - unw_cursor_t cursor; - if (unw_init_local(&cursor, &uc) != 0) { - return; - } - while (unw_step(&cursor) > 0) { - ++ data_->frames_count; - } - } - - unw_cursor_t cursor; - if (unw_init_local(&cursor, &uc) != 0) { - data_->frames_count = 0; - return; - } - - BOOST_TRY { - data_->frames = boost::make_shared(data_->frames_count); - std::size_t i = 0; - while (unw_step(&cursor) > 0){ - data_->frames[i].name = get_frame_impl(cursor); - unw_proc_info_t inf; - const int res = unw_get_proc_info(&cursor, &inf); - (void)res; - data_->frames[i].addr = reinterpret_cast(inf.start_ip ? inf.start_ip : inf.gp); - boost::hash_combine(hash_code, data_->frames[i].name); - ++ i; - } - } BOOST_CATCH(...) {} - BOOST_CATCH_END -} - -std::string backend::get_name(std::size_t frame) const { - if (frame < data_->frames_count) { - return data_->frames[frame].name; - } else { - return std::string(); - } -} - -const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT { - return data_->frames[frame].addr; -} - -std::string backend::get_source_file(std::size_t /*frame*/) const { - return std::string(); -} - -std::size_t backend::get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT { - return 0; -} - -bool backend::operator< (const backend& rhs) const BOOST_NOEXCEPT { - if (data_->frames_count != rhs.data_->frames_count) { - return data_->frames_count < rhs.data_->frames_count; - } else if (data_->frames.get() == rhs.data_->frames.get()) { - return false; - } - - return std::lexicographical_compare( - data_->frames.get(), data_->frames.get() + data_->frames_count, - rhs.data_->frames.get(), rhs.data_->frames.get() + rhs.data_->frames_count - ); -} - -bool backend::operator==(const backend& rhs) const BOOST_NOEXCEPT { - if (data_->frames_count != rhs.data_->frames_count) { - return false; - } else if (data_->frames.get() == rhs.data_->frames.get()) { - return true; - } - - return std::equal( - data_->frames.get(), data_->frames.get() + data_->frames_count, - rhs.data_->frames.get() - ); -} - -}}} // namespace boost::stacktrace::detail - -#include - -#endif // BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP diff --git a/include/boost/stacktrace/detail/backend_linux.hpp b/include/boost/stacktrace/detail/backend_linux.hpp index d436a63..2611ec9 100644 --- a/include/boost/stacktrace/detail/backend_linux.hpp +++ b/include/boost/stacktrace/detail/backend_linux.hpp @@ -106,7 +106,7 @@ public: } }; -static inline std::string addr2line(const char* flag, void* addr) { +static inline std::string addr2line(const char* flag, const void* addr) { std::string res; Dl_info dli; @@ -179,17 +179,14 @@ backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_N hash_code = boost::hash_range(data_->buffer, data_->buffer + data_->frames_count); } -std::string backend::get_name(std::size_t frame) const { +std::string backend::get_name(const void* addr) { std::string res; - if (frame >= data_->frames_count) { - return res; - } Dl_info dli; - if (!!dladdr(data_->buffer[frame], &dli) && dli.dli_sname) { + if (!!dladdr(addr, &dli) && dli.dli_sname) { res = try_demangle(dli.dli_sname); } else { - res = addr2line("-fe", data_->buffer[frame]); + res = addr2line("-fe", addr); res = res.substr(0, res.find_last_of('\n')); res = try_demangle(res.c_str()); } @@ -201,14 +198,14 @@ const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT { return data_->buffer[frame]; } -std::string backend::get_source_file(std::size_t frame) const { - std::string res = addr2line("-e", data_->buffer[frame]); +std::string backend::get_source_file(const void* addr) { + std::string res = addr2line("-e", addr); res = res.substr(0, res.find_last_of(':')); return res; } -std::size_t backend::get_source_line(std::size_t frame) const BOOST_NOEXCEPT { - std::string res = addr2line("-e", data_->buffer[frame]); +std::size_t backend::get_source_line(const void* addr) { + std::string res = addr2line("-e", addr); const std::size_t last = res.find_last_of(':'); if (last == std::string::npos) { return 0; diff --git a/include/boost/stacktrace/detail/backend_noop.hpp b/include/boost/stacktrace/detail/backend_noop.hpp index 82b2646..e8e002f 100644 --- a/include/boost/stacktrace/detail/backend_noop.hpp +++ b/include/boost/stacktrace/detail/backend_noop.hpp @@ -21,7 +21,7 @@ backend::backend(void* /*memory*/, std::size_t /*size*/, std::size_t& hash_code) hash_code = 0; } -std::string backend::get_name(std::size_t /*frame*/) const { +std::string backend::get_name(const void* /*addr*/) { return std::string(); } @@ -29,11 +29,11 @@ const void* backend::get_address(std::size_t /*frame*/) const BOOST_NOEXCEPT { return data_; // returns 0. Suppressing `private field 'data_' is not used` warning } -std::string backend::get_source_file(std::size_t /*frame*/) const { +std::string backend::get_source_file(const void* /*addr*/) { return std::string(); } -std::size_t backend::get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT { +std::size_t backend::get_source_line(const void* /*addr*/) { return 0; } diff --git a/include/boost/stacktrace/detail/backend_windows.hpp b/include/boost/stacktrace/detail/backend_windows.hpp index e62a21a..08440c7 100644 --- a/include/boost/stacktrace/detail/backend_windows.hpp +++ b/include/boost/stacktrace/detail/backend_windows.hpp @@ -128,17 +128,12 @@ backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_N boost::hash_combine(hash_code, hc); } -std::string backend::get_name(std::size_t frame) const { - std::string result; - if (frame >= data_->frames_count) { - return result; - } - +std::string backend::get_name(const void* addr) { com_holder idebug_; if (!try_init_com(idebug_)) { return result; } - const ULONG64 offset = reinterpret_cast(data_->buffer[frame]); + const ULONG64 offset = reinterpret_cast(addr); char name[256]; name[0] = '\0'; @@ -175,17 +170,12 @@ const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT { return data_->buffer[frame]; } -std::string backend::get_source_file(std::size_t frame) const { - std::string result; - if (frame >= data_->frames_count) { - return result; - } - +std::string backend::get_source_file(const void* addr) { com_holder idebug_; if (!try_init_com(idebug_)) { return result; } - const ULONG64 offset = reinterpret_cast(data_->buffer[frame]); + const ULONG64 offset = reinterpret_cast(addr); char name[256]; name[0] = 0; @@ -221,7 +211,7 @@ std::string backend::get_source_file(std::size_t frame) const { return result; } -std::size_t backend::get_source_line(std::size_t frame) const BOOST_NOEXCEPT { +std::size_t backend::get_source_line(const void* addr) { ULONG line_num = 0; com_holder idebug_; @@ -230,7 +220,7 @@ std::size_t backend::get_source_line(std::size_t frame) const BOOST_NOEXCEPT { } const bool is_ok = (S_OK == idebug_->GetLineByOffset( - reinterpret_cast(data_->buffer[frame]), + reinterpret_cast(addr), &line_num, 0, 0, diff --git a/include/boost/stacktrace/detail/to_hex_array.hpp b/include/boost/stacktrace/detail/to_hex_array.hpp index d56ca45..875a3a0 100644 --- a/include/boost/stacktrace/detail/to_hex_array.hpp +++ b/include/boost/stacktrace/detail/to_hex_array.hpp @@ -61,6 +61,13 @@ inline boost::array to_hex_array(void* addr) BO ); } + +inline boost::array to_hex_array(const void* addr) BOOST_NOEXCEPT { + return to_hex_array( + reinterpret_cast(addr) + ); +} + }}} // namespace boost::stacktrace::detail #endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_TO_HEX_ARRAY_HPP diff --git a/include/boost/stacktrace/frame_view.hpp b/include/boost/stacktrace/frame_view.hpp index 8d89d41..9f5fcf9 100644 --- a/include/boost/stacktrace/frame_view.hpp +++ b/include/boost/stacktrace/frame_view.hpp @@ -58,7 +58,7 @@ public: /// @returns Name of the frame (function name in a human readable form). /// @throws std::bad_alloc if not enough memory to construct resulting string. std::string name() const { - return impl_->get_name(frame_no_); + return boost::stacktrace::detail::backend::get_name(address()); } /// @returns Address of the frame function. @@ -71,13 +71,13 @@ public: /// if this->source_line() == 0. /// @throws std::bad_alloc if not enough memory to construct resulting string. std::string source_file() const { - return impl_->get_source_file(frame_no_); + return boost::stacktrace::detail::backend::get_source_file(address()); } /// @returns Code line in the source file, were the function of the frame is defined. /// @throws Nothing. std::size_t source_line() const BOOST_NOEXCEPT { - return impl_->get_source_line(frame_no_); + return boost::stacktrace::detail::backend::get_source_line(address()); } }; diff --git a/src/libunwind.cpp b/src/libunwind.cpp deleted file mode 100644 index 9f4aa4e..0000000 --- a/src/libunwind.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright Antony Polukhin, 2016. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS -#define BOOST_STACKTRACE_USE_LIBUNWIND -#define BOOST_STACKTRACE_LINK -#include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9e1bd39..dd94e2d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -6,7 +6,6 @@ # lib dl : : shared ; -lib unwind : : shared ; lib Dbghelp ; project @@ -19,18 +18,15 @@ project ; -local UNW_DEPS = unwind [ check-target-builds ../build//libunwind : : no ] ; local BT_DEPS = linux:dl [ check-target-builds ../build//backtrace : : no ] ; local WIND_DEPS = Dbghelp [ check-target-builds ../build//WinDbg : : no ] ; local NOOP_DEPS = ; -local AUTO_DEPS = linux:dl [ check-target-builds ../build//WinDbg : Dbghelp ] [ check-target-builds ../build//libunwind : unwind ] ; +local AUTO_DEPS = linux:dl [ check-target-builds ../build//WinDbg : Dbghelp ] ; -local LINKSHARED_UNW = shared BOOST_STACKTRACE_DYN_LINK /boost/stacktrace//boost_stacktrace_libunwind $(UNW_DEPS) ; local LINKSHARED_BT = shared BOOST_STACKTRACE_DYN_LINK /boost/stacktrace//boost_stacktrace_backtrace $(BT_DEPS) ; local LINKSHARED_WIND = shared BOOST_STACKTRACE_DYN_LINK /boost/stacktrace//boost_stacktrace_windbg $(WIND_DEPS) ; local LINKSHARED_NOOP = shared BOOST_STACKTRACE_DYN_LINK /boost/stacktrace//boost_stacktrace_noop $(NOOP_DEPS) ; -lib test_impl_lib_libunwind : test_impl.cpp : $(LINKSHARED_UNW) ; lib test_impl_lib_backtrace : test_impl.cpp : $(LINKSHARED_BT) ; lib test_impl_lib_windbg : test_impl.cpp : $(LINKSHARED_WIND) ; lib test_impl_lib_noop : test_impl.cpp : $(LINKSHARED_NOOP) ; @@ -38,26 +34,22 @@ lib test_impl_lib_noop : test_impl.cpp : $(LINKSHARED_NOOP) ; test-suite stacktrace_tests : # Header only tests - [ run test.cpp test_impl.cpp : : : BOOST_STACKTRACE_USE_LIBUNWIND $(UNW_DEPS) : libunwind_ho ] [ run test.cpp test_impl.cpp : : : BOOST_STACKTRACE_USE_BACKTRACE $(BT_DEPS) : backtrace_ho ] [ run test.cpp test_impl.cpp : : : BOOST_STACKTRACE_USE_WINDBG $(WIND_DEPS) : windbg_ho ] [ run test_noop.cpp test_impl.cpp : : : BOOST_STACKTRACE_USE_NOOP $(NOOP_DEPS) : noop_ho ] [ run test.cpp test_impl.cpp : : : $(AUTO_DEPS) : autodetect_ho ] # Test with shared linked backends - [ run test.cpp : : : .//test_impl_lib_libunwind $(LINKSHARED_UNW) : libunwind_lib ] [ run test.cpp : : : .//test_impl_lib_backtrace $(LINKSHARED_BT) : backtrace_lib ] [ run test.cpp : : : .//test_impl_lib_windbg $(LINKSHARED_WIND) : windbg_lib ] [ run test_noop.cpp : : : .//test_impl_lib_noop $(LINKSHARED_NOOP) : noop_lib ] # Making sure that the examples work - [ run ../example/getting_started.cpp : : : BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_UNW) : libunwind_getting_started ] [ run ../example/getting_started.cpp : : : BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_BT) : backtrace_getting_started ] [ run ../example/getting_started.cpp : : : BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_WIND) : windbg_getting_started ] [ run ../example/getting_started.cpp : : : BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_NOOP) : noop_getting_started ] [ run ../example/getting_started.cpp : : : BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(AUTO_DEPS) : autodetect_getting_started ] - [ run ../example/throwing_st.cpp : : : $(LINKSHARED_UNW) : libunwind_throwing_st ] [ run ../example/throwing_st.cpp : : : $(LINKSHARED_BT) : backtrace_throwing_st ] [ run ../example/throwing_st.cpp : : : $(LINKSHARED_WIND) : windbg_throwing_st ] [ run ../example/throwing_st.cpp : : : $(LINKSHARED_NOOP) : noop_throwing_st ]