From 36061d4ef8a2830bbacddee2af9d35635a5f0e76 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 3 Jan 2017 11:59:55 +0300 Subject: [PATCH] Move code around, prepare for optimizing the stack ostreaming operators --- include/boost/stacktrace/detail/backend.hpp | 87 ----------------- include/boost/stacktrace/detail/backend.ipp | 2 +- .../boost/stacktrace/detail/backend_noop.hpp | 28 +++--- .../boost/stacktrace/detail/backend_posix.hpp | 35 ++++--- .../stacktrace/detail/backend_windows.hpp | 97 ++++++++++--------- include/boost/stacktrace/frame.hpp | 78 +++++++++++++-- include/boost/stacktrace/stacktrace.hpp | 1 - 7 files changed, 153 insertions(+), 175 deletions(-) delete mode 100644 include/boost/stacktrace/detail/backend.hpp diff --git a/include/boost/stacktrace/detail/backend.hpp b/include/boost/stacktrace/detail/backend.hpp deleted file mode 100644 index 962fcdb..0000000 --- a/include/boost/stacktrace/detail/backend.hpp +++ /dev/null @@ -1,87 +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_HPP -#define BOOST_STACKTRACE_DETAIL_BACKEND_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#include - - -// Link or header only -#if !defined(BOOST_STACKTRACE_LINK) && defined(BOOST_STACKTRACE_DYN_LINK) -# define BOOST_STACKTRACE_LINK -#endif - -#if defined(BOOST_STACKTRACE_LINK) && !defined(BOOST_STACKTRACE_DYN_LINK) && defined(BOOST_ALL_DYN_LINK) -# define BOOST_STACKTRACE_DYN_LINK -#endif - -// Backend autodetection -#if !defined(BOOST_STACKTRACE_USE_NOOP) && !defined(BOOST_STACKTRACE_USE_WINDBG) && !defined(BOOST_STACKTRACE_USE_UNWIND) \ - && !defined(BOOST_STACKTRACE_USE_BACKTRACE) && !defined(BOOST_STACKTRACE_USE_HEADER) - -#if defined(__has_include) && (!defined(__GNUC__) || __GNUC__ > 4 || BOOST_CLANG) -# if __has_include("Dbgeng.h") -# define BOOST_STACKTRACE_USE_WINDBG -# else -# define BOOST_STACKTRACE_USE_UNWIND -# endif -#else -# if defined(BOOST_WINDOWS) -# define BOOST_STACKTRACE_USE_WINDBG -# else -# define BOOST_STACKTRACE_USE_UNWIND -# endif -#endif - -#endif - -#ifdef BOOST_STACKTRACE_LINK -# if defined(BOOST_STACKTRACE_DYN_LINK) -# ifdef BOOST_STACKTRACE_INTERNAL_BUILD_LIBS -# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_EXPORT -# else -# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_IMPORT -# endif -# else -# define BOOST_STACKTRACE_FUNCTION -# endif -#else -# define BOOST_STACKTRACE_FUNCTION inline -#endif - -namespace boost { namespace stacktrace { - class frame; -}} - -namespace boost { namespace stacktrace { namespace detail { - -// Class that implements the actual backtracing -class backend { -public: - BOOST_NOINLINE BOOST_STACKTRACE_FUNCTION static std::size_t collect(void** memory, std::size_t size) BOOST_NOEXCEPT; - BOOST_STACKTRACE_FUNCTION static std::string get_name(const void* addr); - 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 static std::string to_string(const void* addr); -}; - -}}} // namespace boost::stacktrace::detail - -/// @cond -#undef BOOST_STACKTRACE_FUNCTION - -#ifndef BOOST_STACKTRACE_LINK -# include -#endif -/// @endcond - -#endif // BOOST_STACKTRACE_DETAIL_BACKEND_HPP diff --git a/include/boost/stacktrace/detail/backend.ipp b/include/boost/stacktrace/detail/backend.ipp index f23935e..98bcce7 100644 --- a/include/boost/stacktrace/detail/backend.ipp +++ b/include/boost/stacktrace/detail/backend.ipp @@ -12,7 +12,7 @@ # pragma once #endif -#include +#include #if defined(BOOST_STACKTRACE_USE_NOOP) # include diff --git a/include/boost/stacktrace/detail/backend_noop.hpp b/include/boost/stacktrace/detail/backend_noop.hpp index 4cfccce..71332a3 100644 --- a/include/boost/stacktrace/detail/backend_noop.hpp +++ b/include/boost/stacktrace/detail/backend_noop.hpp @@ -19,22 +19,24 @@ std::size_t backend::collect(void** /*memory*/, std::size_t /*size*/) BOOST_NOEX return 0; } -std::string backend::get_name(const void* /*addr*/) { - return std::string(); -} - -std::string backend::get_source_file(const void* /*addr*/) { - return std::string(); -} - -std::size_t backend::get_source_line(const void* /*addr*/) { - return 0; -} - std::string backend::to_string(const void* /*addr*/) { return std::string(); } -}}} // namespace boost::stacktrace::detail +} // namespace detail + +std::string frame::name() const { + return std::string(); +} + +std::string frame::source_file() const { + return std::string(); +} + +std::size_t frame::source_line() const { + return 0; +} + +}} // namespace boost::stacktrace #endif // BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP diff --git a/include/boost/stacktrace/detail/backend_posix.hpp b/include/boost/stacktrace/detail/backend_posix.hpp index b0242b6..044b1e6 100644 --- a/include/boost/stacktrace/detail/backend_posix.hpp +++ b/include/boost/stacktrace/detail/backend_posix.hpp @@ -91,7 +91,7 @@ public: } }; -static inline std::string addr2line(const char* flag, const void* addr) { +inline std::string addr2line(const char* flag, const void* addr) { std::string res; Dl_info dli; @@ -135,7 +135,7 @@ static inline std::string addr2line(const char* flag, const void* addr) { return res; } -static inline std::string try_demangle(const char* mangled) { +inline std::string try_demangle(const char* mangled) { std::string res; boost::core::scoped_demangled_name demangled(mangled); @@ -195,16 +195,23 @@ std::size_t backend::collect(void** memory, std::size_t size) BOOST_NOEXCEPT { return frames_count; } -std::string backend::get_name(const void* addr) { +std::string backend::to_string(const void* addr) { + return boost::stacktrace::frame(addr).name() + " at " + boost::stacktrace::detail::addr2line("-Cpe", addr); + //return addr2line("-Cfipe", addr); // Does not seem to work in all cases +} + +} // namespace detail + +std::string frame::name() const { std::string res; Dl_info dli; - if (!!dladdr(addr, &dli) && dli.dli_sname) { - res = try_demangle(dli.dli_sname); + if (!!dladdr(addr_, &dli) && dli.dli_sname) { + res = boost::stacktrace::detail::try_demangle(dli.dli_sname); } else { - res = addr2line("-fe", addr); + res = boost::stacktrace::detail::addr2line("-fe", addr_); res = res.substr(0, res.find_last_of('\n')); - res = try_demangle(res.c_str()); + res = boost::stacktrace::detail::try_demangle(res.c_str()); } if (res == "??") { @@ -214,8 +221,8 @@ std::string backend::get_name(const void* addr) { return res; } -std::string backend::get_source_file(const void* addr) { - std::string res = addr2line("-e", addr); +std::string frame::source_file() const { + std::string res = boost::stacktrace::detail::addr2line("-e", addr_); res = res.substr(0, res.find_last_of(':')); if (res == "??") { res.clear(); @@ -223,8 +230,8 @@ std::string backend::get_source_file(const void* addr) { return res; } -std::size_t backend::get_source_line(const void* addr) { - std::string res = addr2line("-e", addr); +std::size_t frame::source_line() const { + std::string res = boost::stacktrace::detail::addr2line("-e", addr_); const std::size_t last = res.find_last_of(':'); if (last == std::string::npos) { return 0; @@ -239,11 +246,7 @@ std::size_t backend::get_source_line(const void* addr) { return line_num; } -std::string backend::to_string(const void* addr) { - return get_name(addr) + " at " + addr2line("-Cpe", addr); - //return addr2line("-Cfipe", addr); // Does not seem to work in all cases -} -}}} // namespace boost::stacktrace::detail +}} // namespace boost::stacktrace #endif // BOOST_STACKTRACE_DETAIL_BACKEND_POSIX_HPP diff --git a/include/boost/stacktrace/detail/backend_windows.hpp b/include/boost/stacktrace/detail/backend_windows.hpp index 09bb112..81d957a 100644 --- a/include/boost/stacktrace/detail/backend_windows.hpp +++ b/include/boost/stacktrace/detail/backend_windows.hpp @@ -35,6 +35,7 @@ public: } }; + template class com_holder: boost::noncopyable { T* holder_; @@ -63,6 +64,7 @@ public: } }; + inline bool try_init_com(com_holder& idebug, const com_global_initer& com) BOOST_NOEXCEPT { com_holder iclient(com); DebugCreate(__uuidof(IDebugClient), iclient.to_void_ptr_ptr()); @@ -93,8 +95,6 @@ inline bool try_init_com(com_holder& idebug, const com_global_ini } - - std::size_t backend::collect(void** memory, std::size_t size) BOOST_NOEXCEPT { return CaptureStackBackTrace( 0, @@ -104,6 +104,7 @@ std::size_t backend::collect(void** memory, std::size_t size) BOOST_NOEXCEPT { ); } + inline std::string get_name_impl(const com_holder& idebug, const void* addr) { std::string result; const ULONG64 offset = reinterpret_cast(addr); @@ -140,17 +141,6 @@ inline std::string get_name_impl(const com_holder& idebug, const } -std::string backend::get_name(const void* addr) { - com_global_initer com_guard; - com_holder idebug(com_guard); - if (!boost::stacktrace::detail::try_init_com(idebug, com_guard)) { - return std::string(); - } - - return boost::stacktrace::detail::get_name_impl(idebug, addr); -} - - inline std::pair get_source_file_line_impl(const com_holder& idebug, const void* addr) { std::pair result; const ULONG64 offset = reinterpret_cast(addr); @@ -198,40 +188,9 @@ inline std::pair get_source_file_line_impl(const com_h } -std::string backend::get_source_file(const void* addr) { - com_global_initer com_guard; - com_holder idebug(com_guard); - if (!boost::stacktrace::detail::try_init_com(idebug, com_guard)) { - return std::string(); - } - return boost::stacktrace::detail::get_source_file_line_impl(idebug, addr).first; -} - -std::size_t backend::get_source_line(const void* addr) { - ULONG line_num = 0; - - com_global_initer com_guard; - com_holder idebug(com_guard); - if (!boost::stacktrace::detail::try_init_com(idebug, com_guard)) { - return 0; - } - - const bool is_ok = (S_OK == idebug->GetLineByOffset( - reinterpret_cast(addr), - &line_num, - 0, - 0, - 0, - 0 - )); - - return (is_ok ? line_num : 0); -} - - std::string backend::to_string(const void* addr) { - com_global_initer com_guard; - com_holder idebug(com_guard); + boost::stacktrace::detail::com_global_initer com_guard; + boost::stacktrace::detail::com_holder idebug(com_guard); if (!boost::stacktrace::detail::try_init_com(idebug, com_guard)) { return std::string(); } @@ -247,6 +206,50 @@ std::string backend::to_string(const void* addr) { ; } -}}} // namespace boost::stacktrace::detail +} // namespace detail + + +std::string frame::name() const { + boost::stacktrace::detail::com_global_initer com_guard; + boost::stacktrace::detail::com_holder idebug(com_guard); + if (!boost::stacktrace::detail::try_init_com(idebug, com_guard)) { + return std::string(); + } + + return boost::stacktrace::detail::get_name_impl(idebug, addr_); +} + + +std::string frame::source_file() const { + boost::stacktrace::detail::com_global_initer com_guard; + boost::stacktrace::detail::com_holder idebug(com_guard); + if (!boost::stacktrace::detail::try_init_com(idebug, com_guard)) { + return std::string(); + } + return boost::stacktrace::detail::get_source_file_line_impl(idebug, addr_).first; +} + +std::size_t frame::source_line() const { + ULONG line_num = 0; + + boost::stacktrace::detail::com_global_initer com_guard; + boost::stacktrace::detail::com_holder idebug(com_guard); + if (!boost::stacktrace::detail::try_init_com(idebug, com_guard)) { + return 0; + } + + const bool is_ok = (S_OK == idebug->GetLineByOffset( + reinterpret_cast(addr_), + &line_num, + 0, + 0, + 0, + 0 + )); + + return (is_ok ? line_num : 0); +} + +}} // namespace boost::stacktrace #endif // BOOST_STACKTRACE_DETAIL_BACKEND_LINUX_HPP diff --git a/include/boost/stacktrace/frame.hpp b/include/boost/stacktrace/frame.hpp index 19d1d7e..4c3c477 100644 --- a/include/boost/stacktrace/frame.hpp +++ b/include/boost/stacktrace/frame.hpp @@ -16,10 +16,65 @@ #include #include -#include + +// Link or header only +#if !defined(BOOST_STACKTRACE_LINK) && defined(BOOST_STACKTRACE_DYN_LINK) +# define BOOST_STACKTRACE_LINK +#endif + +#if defined(BOOST_STACKTRACE_LINK) && !defined(BOOST_STACKTRACE_DYN_LINK) && defined(BOOST_ALL_DYN_LINK) +# define BOOST_STACKTRACE_DYN_LINK +#endif + +// Backend autodetection +#if !defined(BOOST_STACKTRACE_USE_NOOP) && !defined(BOOST_STACKTRACE_USE_WINDBG) && !defined(BOOST_STACKTRACE_USE_UNWIND) \ + && !defined(BOOST_STACKTRACE_USE_BACKTRACE) && !defined(BOOST_STACKTRACE_USE_HEADER) + +#if defined(__has_include) && (!defined(__GNUC__) || __GNUC__ > 4 || BOOST_CLANG) +# if __has_include("Dbgeng.h") +# define BOOST_STACKTRACE_USE_WINDBG +# else +# define BOOST_STACKTRACE_USE_UNWIND +# endif +#else +# if defined(BOOST_WINDOWS) +# define BOOST_STACKTRACE_USE_WINDBG +# else +# define BOOST_STACKTRACE_USE_UNWIND +# endif +#endif + +#endif + +#ifdef BOOST_STACKTRACE_LINK +# if defined(BOOST_STACKTRACE_DYN_LINK) +# ifdef BOOST_STACKTRACE_INTERNAL_BUILD_LIBS +# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_EXPORT +# else +# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_IMPORT +# endif +# else +# define BOOST_STACKTRACE_FUNCTION +# endif +#else +# define BOOST_STACKTRACE_FUNCTION inline +#endif + + namespace boost { namespace stacktrace { +namespace detail { + +// Class that implements the actual backtracing +class backend { +public: + BOOST_NOINLINE BOOST_STACKTRACE_FUNCTION static std::size_t collect(void** memory, std::size_t size) BOOST_NOEXCEPT; + BOOST_STACKTRACE_FUNCTION static std::string to_string(const void* addr); +}; + +} // namespace detail + /// Non-owning class that references the frame information stored inside the boost::stacktrace::stacktrace class. class frame { /// @cond @@ -71,9 +126,7 @@ public: /// /// @b Async-Handler-Safety: Unsafe. /// @throws std::bad_alloc if not enough memory to construct resulting string. - std::string name() const { - return boost::stacktrace::detail::backend::get_name(address()); - } + BOOST_STACKTRACE_FUNCTION std::string name() const; /// @returns Address of the frame function. /// @@ -88,17 +141,13 @@ public: /// @throws std::bad_alloc if not enough memory to construct resulting string. /// /// @b Async-Handler-Safety: Unsafe. - std::string source_file() const { - return boost::stacktrace::detail::backend::get_source_file(address()); - } + BOOST_STACKTRACE_FUNCTION std::string source_file() const; /// @returns Code line in the source file, were the function of the frame is defined. /// @throws std::bad_alloc if not enough memory to construct string for internal needs. /// /// @b Async-Handler-Safety: Unsafe. - std::size_t source_line() const { - return boost::stacktrace::detail::backend::get_source_line(address()); - } + BOOST_STACKTRACE_FUNCTION std::size_t source_line() const; /// @brief Checks that frame is not references NULL address. /// @returns `true` if `this->address() != 0` @@ -142,4 +191,13 @@ std::basic_ostream& operator<<(std::basic_ostream +#endif +/// @endcond + + #endif // BOOST_STACKTRACE_FRAME_HPP diff --git a/include/boost/stacktrace/stacktrace.hpp b/include/boost/stacktrace/stacktrace.hpp index 70160ae..b60f228 100644 --- a/include/boost/stacktrace/stacktrace.hpp +++ b/include/boost/stacktrace/stacktrace.hpp @@ -20,7 +20,6 @@ #include #include -#include namespace boost { // Forward declaration