From e1c1a4910b13252ecb82ef3df89feccea90edf61 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 11 Oct 2016 23:22:38 +0300 Subject: [PATCH] Minor improvements and refactoring --- include/boost/stacktrace.hpp | 39 +++++++++ .../detail/backtrace_holder_libunwind.hpp | 83 ++++++++++++++++++ .../detail/backtrace_holder_linux.hpp | 57 ++++++++++++ .../detail/backtrace_holder_noop.hpp | 30 +++++++ .../detail/backtrace_holder_windows.hpp | 86 +++++++++++++++++++ .../{stacktrace_helpers.hpp => helpers.hpp} | 9 ++ .../boost/stacktrace/detail/stacktrace.ipp | 47 ++-------- .../detail/stacktrace_libunwind.hpp | 74 +--------------- .../stacktrace/detail/stacktrace_linux.hpp | 48 +---------- .../stacktrace/detail/stacktrace_noop.hpp | 19 +--- .../stacktrace/detail/stacktrace_windows.hpp | 77 +---------------- src/backtrace.cpp | 2 +- src/libunwind.cpp | 2 +- src/noop.cpp | 2 +- src/stacktrace_src.ipp | 73 ++++++++++++++++ src/windbg.cpp | 2 +- 16 files changed, 401 insertions(+), 249 deletions(-) create mode 100644 include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp create mode 100644 include/boost/stacktrace/detail/backtrace_holder_linux.hpp create mode 100644 include/boost/stacktrace/detail/backtrace_holder_noop.hpp create mode 100644 include/boost/stacktrace/detail/backtrace_holder_windows.hpp rename include/boost/stacktrace/detail/{stacktrace_helpers.hpp => helpers.hpp} (82%) create mode 100644 src/stacktrace_src.ipp diff --git a/include/boost/stacktrace.hpp b/include/boost/stacktrace.hpp index 142596b..e27859e 100644 --- a/include/boost/stacktrace.hpp +++ b/include/boost/stacktrace.hpp @@ -18,6 +18,8 @@ #include /// @cond + +// Link or header only #if !defined(BOOST_STACKTRACE_LINK) && defined(BOOST_STACKTRACE_DYN_LINK) # define BOOST_STACKTRACE_LINK #endif @@ -26,6 +28,28 @@ # define BOOST_STACKTRACE_DYN_LINK #endif +// Backend autodetection +#if !defined(BOOST_STACKTRACE_USE_NOOP) && !defined(BOOST_STACKTRACE_USE_WINDBG) && !defined(BOOST_STACKTRACE_USE_LIBUNWIND) \ + && !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() +# define BOOST_STACKTRACE_USE_BACKTRACE +# elif __has_include("DbgHelp.h") +# define BOOST_STACKTRACE_USE_WINDBG +# endif +#else +# if defined(BOOST_WINDOWS) +# define BOOST_STACKTRACE_USE_WINDBG +# else +# define BOOST_STACKTRACE_USE_BACKTRACE +# endif +#endif + +#endif + #ifdef BOOST_STACKTRACE_LINK # if defined(BOOST_STACKTRACE_DYN_LINK) # ifdef BOOST_STACKTRACE_INTERNAL_BUILD_LIBS @@ -38,14 +62,29 @@ # endif #else # define BOOST_STACKTRACE_FUNCTION inline +# if defined(BOOST_STACKTRACE_USE_NOOP) +# include +# elif defined(BOOST_STACKTRACE_USE_WINDBG) +# include +# elif defined(BOOST_STACKTRACE_USE_LIBUNWIND) +# include +# elif defined(BOOST_STACKTRACE_USE_BACKTRACE) +# include +# else +# error No suitable backtrace backend found +# endif #endif /// @endcond namespace boost { namespace stacktrace { class stacktrace { +#ifdef BOOST_STACKTRACE_LINK BOOST_STATIC_CONSTEXPR std::size_t max_implementation_size = sizeof(void*) * 110u; boost::aligned_storage::type impl_; +#else + boost::stacktrace::detail::backtrace_holder impl_; +#endif public: /// @brief Stores the current function call sequence inside the class. diff --git a/include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp b/include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp new file mode 100644 index 0000000..621cc86 --- /dev/null +++ b/include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp @@ -0,0 +1,83 @@ +// 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_BACKTRACE_HOLDER_LIBUNWIND_HPP +#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LIBUNWIND_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include +#include +#include + +#define UNW_LOCAL_ONLY +#include + +namespace boost { namespace stacktrace { namespace detail { + +struct backtrace_holder { + std::size_t frames_count; + boost::shared_ptr frames; + + BOOST_FORCEINLINE backtrace_holder() BOOST_NOEXCEPT + : frames_count(0) + {} + + inline std::size_t size() const BOOST_NOEXCEPT { + return frames_count; + } + + inline std::string get_frame(std::size_t frame) const { + if (frame < frames_count) { + return frames[frame]; + } else { + return std::string(); + } + } + + static 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 + } + + return res; + } +}; + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LIBUNWIND_HPP diff --git a/include/boost/stacktrace/detail/backtrace_holder_linux.hpp b/include/boost/stacktrace/detail/backtrace_holder_linux.hpp new file mode 100644 index 0000000..d7397e6 --- /dev/null +++ b/include/boost/stacktrace/detail/backtrace_holder_linux.hpp @@ -0,0 +1,57 @@ +// 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_BACKTRACE_HOLDER_LINUX_HPP +#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LINUX_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +#include +#include + +namespace boost { namespace stacktrace { namespace detail { + +struct backtrace_holder { + std::size_t frames_count; + BOOST_STATIC_CONSTEXPR std::size_t max_size = 100u; + void* buffer[max_size]; + + inline std::size_t size() const BOOST_NOEXCEPT { + return frames_count; + } + + inline std::string get_frame(std::size_t frame) const { + std::string res; + if (frame >= frames_count) { + return res; + } + + Dl_info dli; + if (!dladdr(buffer[frame], &dli)) { + return res; + } + + if (dli.dli_sname) { + boost::core::scoped_demangled_name demangled(dli.dli_sname); + if (demangled.get()) { + res = demangled.get(); + } else { + res = dli.dli_sname; + } + } + + return res; + } +}; + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LINUX_HPP diff --git a/include/boost/stacktrace/detail/backtrace_holder_noop.hpp b/include/boost/stacktrace/detail/backtrace_holder_noop.hpp new file mode 100644 index 0000000..39be629 --- /dev/null +++ b/include/boost/stacktrace/detail/backtrace_holder_noop.hpp @@ -0,0 +1,30 @@ +// 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_BACKTRACE_HOLDER_NOOP_HPP +#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_NOOP_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + + +namespace boost { namespace stacktrace { namespace detail { + +struct backtrace_holder { + inline std::size_t size() const BOOST_NOEXCEPT { + return 0u; + } + + inline std::string get_frame(std::size_t /*frame*/) const { + return std::string(); + } +}; + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_NOOP_HPP diff --git a/include/boost/stacktrace/detail/backtrace_holder_windows.hpp b/include/boost/stacktrace/detail/backtrace_holder_windows.hpp new file mode 100644 index 0000000..82043b8 --- /dev/null +++ b/include/boost/stacktrace/detail/backtrace_holder_windows.hpp @@ -0,0 +1,86 @@ +// 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_BACKTRACE_HOLDER_WINDOWS_HPP +#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WINDOWS_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include "DbgHelp.h" +#include + +#include +#include + +#if !defined(BOOST_ALL_NO_LIB) +# define BOOST_LIB_NAME Dbghelp +# ifdef BOOST_STACKTRACE_DYN_LINK +# define BOOST_DYN_LINK +# endif +# include +#endif + +namespace boost { namespace stacktrace { namespace detail { + +struct symbol_info_with_stack { + BOOST_STATIC_CONSTEXPR std::size_t max_name_length = MAX_SYM_NAME * sizeof(char); + boost::detail::winapi::SYMBOL_INFO_ symbol; + char name_part[max_name_length]; +}; + +struct symbol_initialization_structure { + boost::detail::winapi::HANDLE_ process; + + inline symbol_initialization_structure() BOOST_NOEXCEPT + : process(boost::detail::winapi::GetCurrentProcess()) + { + SymInitialize(process, 0, true); + } + + inline ~symbol_initialization_structure() BOOST_NOEXCEPT { + SymCleanup(process); + } +}; + +struct backtrace_holder { + BOOST_STATIC_CONSTEXPR std::size_t max_size = 100u; + + std::size_t frames_count; + void* buffer[max_size]; + + inline std::size_t size() const BOOST_NOEXCEPT { + return frames_count; + } + + inline std::string get_frame(std::size_t frame) const { + std::string res; + + static symbol_initialization_structure symproc; + + if (frame >= frames_count) { + return res; + } + + symbol_info_with_stack s; + s.symbol.MaxNameLen = symbol_info_with_stack::max_name_length; + s.symbol.SizeOfStruct = sizeof(boost::detail::winapi::SYMBOL_INFO_); + const bool sym_res = !!boost::detail::winapi::SymFromAddr( + symproc.process, reinterpret_cast(buffer[frame]), 0, &s.symbol + ); + if (sym_res) { + res = s.symbol.Name; + } + return res; + } +}; + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WINDOWS_HPP diff --git a/include/boost/stacktrace/detail/stacktrace_helpers.hpp b/include/boost/stacktrace/detail/helpers.hpp similarity index 82% rename from include/boost/stacktrace/detail/stacktrace_helpers.hpp rename to include/boost/stacktrace/detail/helpers.hpp index fe2bea4..d797e8f 100644 --- a/include/boost/stacktrace/detail/stacktrace_helpers.hpp +++ b/include/boost/stacktrace/detail/helpers.hpp @@ -29,6 +29,15 @@ inline const boost::stacktrace::detail::backtrace_holder& to_bt(const T& data) B return *reinterpret_cast(&data); } +template +inline boost::stacktrace::detail::backtrace_holder& construct_bt_and_return(T& data) BOOST_NOEXCEPT { + new (&data) boost::stacktrace::detail::backtrace_holder(); + return boost::stacktrace::detail::to_bt(data); +} + +inline boost::stacktrace::detail::backtrace_holder& construct_bt_and_return(backtrace_holder& data) BOOST_NOEXCEPT { + return data; +} /* BOOST_STATIC_CONSTEXPR char to_hex_array[] = "0123456789ABCDEF"; diff --git a/include/boost/stacktrace/detail/stacktrace.ipp b/include/boost/stacktrace/detail/stacktrace.ipp index 209113a..0338747 100644 --- a/include/boost/stacktrace/detail/stacktrace.ipp +++ b/include/boost/stacktrace/detail/stacktrace.ipp @@ -13,35 +13,9 @@ #endif #include -#include #include -// Autodetection -#if !defined(BOOST_STACKTRACE_USE_NOOP) && !defined(BOOST_STACKTRACE_USE_WINDBG) && !defined(BOOST_STACKTRACE_USE_LIBUNWIND) \ - && !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() -# define BOOST_STACKTRACE_USE_BACKTRACE -# elif __has_include("DbgHelp.h") -# define BOOST_STACKTRACE_USE_WINDBG -# endif -#else -# if defined(BOOST_WINDOWS) -# define BOOST_STACKTRACE_USE_WINDBG -# else -# define BOOST_STACKTRACE_USE_BACKTRACE -# endif -#endif - -#endif - - -#if defined(BOOST_STACKTRACE_USE_HEADER) -# include BOOST_STACKTRACE_USE_HEADER -#elif defined(BOOST_STACKTRACE_USE_NOOP) +#if defined(BOOST_STACKTRACE_USE_NOOP) # include #elif defined(BOOST_STACKTRACE_USE_WINDBG) # include @@ -61,28 +35,23 @@ namespace boost { namespace stacktrace { // requered to avoid `boost::stacktrace::detail::backtrace_holder` apearing in // stack traces. -stacktrace::stacktrace(const stacktrace& bt) BOOST_NOEXCEPT { - new (&impl_) boost::stacktrace::detail::backtrace_holder( - boost::stacktrace::detail::to_bt(bt.impl_) - ); -} +stacktrace::stacktrace(const stacktrace& bt) BOOST_NOEXCEPT + : impl_(bt.impl_) +{} stacktrace& stacktrace::operator=(const stacktrace& bt) BOOST_NOEXCEPT { - boost::stacktrace::detail::to_bt(impl_) = boost::stacktrace::detail::to_bt(bt.impl_); + impl_ = bt.impl_; return *this; } -stacktrace::~stacktrace() BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG(sizeof(impl_) >= sizeof(boost::stacktrace::detail::backtrace_holder), "Too small storage for holding backtrace"); - boost::stacktrace::detail::to_bt(impl_).~backtrace_holder(); -} +stacktrace::~stacktrace() BOOST_NOEXCEPT {} std::size_t stacktrace::size() const BOOST_NOEXCEPT { - return boost::stacktrace::detail::to_bt(impl_).size(); + return impl_.size(); } std::string stacktrace::operator[](std::size_t frame) const { - return boost::stacktrace::detail::to_bt(impl_).get_frame(frame); + return impl_.get_frame(frame); } diff --git a/include/boost/stacktrace/detail/stacktrace_libunwind.hpp b/include/boost/stacktrace/detail/stacktrace_libunwind.hpp index d97ad23..8ccbb71 100644 --- a/include/boost/stacktrace/detail/stacktrace_libunwind.hpp +++ b/include/boost/stacktrace/detail/stacktrace_libunwind.hpp @@ -13,81 +13,13 @@ #endif #include -#include -#include -#include -#include -#include - -#define UNW_LOCAL_ONLY -#include - -namespace boost { namespace stacktrace { namespace detail { - -struct backtrace_holder { - std::size_t frames_count; - boost::shared_ptr frames; - - BOOST_FORCEINLINE backtrace_holder() BOOST_NOEXCEPT - : frames_count(0) - {} - - inline std::size_t size() const BOOST_NOEXCEPT { - return frames_count; - } - - inline std::string get_frame(std::size_t frame) const { - if (frame < frames_count) { - return frames[frame]; - } else { - return std::string(); - } - } - - static 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 - } - - return res; - } -}; - -}}} // namespace boost::stacktrace::detail - +#include +#include namespace boost { namespace stacktrace { stacktrace::stacktrace() BOOST_NOEXCEPT { - new (&impl_) boost::stacktrace::detail::backtrace_holder(); - boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::to_bt(impl_); + boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_); unw_context_t uc; if (unw_getcontext(&uc) != 0) { diff --git a/include/boost/stacktrace/detail/stacktrace_linux.hpp b/include/boost/stacktrace/detail/stacktrace_linux.hpp index 73a6fcc..24399fe 100644 --- a/include/boost/stacktrace/detail/stacktrace_linux.hpp +++ b/include/boost/stacktrace/detail/stacktrace_linux.hpp @@ -13,55 +13,13 @@ #endif #include -#include -#include - -#include -#include - -namespace boost { namespace stacktrace { namespace detail { - -struct backtrace_holder { - std::size_t frames_count; - BOOST_STATIC_CONSTEXPR std::size_t max_size = 100u; - void* buffer[max_size]; - - inline std::size_t size() const BOOST_NOEXCEPT { - return frames_count; - } - - inline std::string get_frame(std::size_t frame) const { - std::string res; - if (frame >= frames_count) { - return res; - } - - Dl_info dli; - if (!dladdr(buffer[frame], &dli)) { - return res; - } - - if (dli.dli_sname) { - boost::core::scoped_demangled_name demangled(dli.dli_sname); - if (demangled.get()) { - res = demangled.get(); - } else { - res = dli.dli_sname; - } - } - - return res; - } -}; - -}}} // namespace boost::stacktrace::detail - +#include +#include namespace boost { namespace stacktrace { stacktrace::stacktrace() BOOST_NOEXCEPT { - new (&impl_) boost::stacktrace::detail::backtrace_holder(); - boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::to_bt(impl_); + boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_); bt.frames_count = ::backtrace(bt.buffer, boost::stacktrace::detail::backtrace_holder::max_size); } diff --git a/include/boost/stacktrace/detail/stacktrace_noop.hpp b/include/boost/stacktrace/detail/stacktrace_noop.hpp index 56a8270..ebff503 100644 --- a/include/boost/stacktrace/detail/stacktrace_noop.hpp +++ b/include/boost/stacktrace/detail/stacktrace_noop.hpp @@ -12,27 +12,14 @@ # pragma once #endif - #include - -namespace boost { namespace stacktrace { namespace detail { - -struct backtrace_holder { - inline std::size_t size() const BOOST_NOEXCEPT { - return 0u; - } - - inline std::string get_frame(std::size_t /*frame*/) const { - return std::string(); - } -}; - -}}} // namespace boost::stacktrace::detail +#include +#include namespace boost { namespace stacktrace { stacktrace::stacktrace() BOOST_NOEXCEPT { - new (&impl_) boost::stacktrace::detail::backtrace_holder(); + boost::stacktrace::detail::construct_bt_and_return(impl_); } }} // namespace boost::stacktrace diff --git a/include/boost/stacktrace/detail/stacktrace_windows.hpp b/include/boost/stacktrace/detail/stacktrace_windows.hpp index a6eca3e..f23d8f1 100644 --- a/include/boost/stacktrace/detail/stacktrace_windows.hpp +++ b/include/boost/stacktrace/detail/stacktrace_windows.hpp @@ -13,84 +13,13 @@ #endif #include -#include - -#include -#include "DbgHelp.h" -#include - -#include -#include - -#if !defined(BOOST_ALL_NO_LIB) -# define BOOST_LIB_NAME Dbghelp -# ifdef BOOST_STACKTRACE_DYN_LINK -# define BOOST_DYN_LINK -# endif -# include -#endif - -namespace boost { namespace stacktrace { namespace detail { - -struct symbol_info_with_stack { - BOOST_STATIC_CONSTEXPR std::size_t max_name_length = MAX_SYM_NAME * sizeof(char); - boost::detail::winapi::SYMBOL_INFO_ symbol; - char name_part[max_name_length]; -}; - -struct symbol_initialization_structure { - boost::detail::winapi::HANDLE_ process; - - inline symbol_initialization_structure() BOOST_NOEXCEPT - : process(boost::detail::winapi::GetCurrentProcess()) - { - SymInitialize(process, 0, true); - } - - inline ~symbol_initialization_structure() BOOST_NOEXCEPT { - SymCleanup(process); - } -}; - -struct backtrace_holder { - BOOST_STATIC_CONSTEXPR std::size_t max_size = 100u; - - std::size_t frames_count; - void* buffer[max_size]; - - inline std::size_t size() const BOOST_NOEXCEPT { - return frames_count; - } - - inline std::string get_frame(std::size_t frame) const { - std::string res; - - static symbol_initialization_structure symproc; - - if (frame >= frames_count) { - return res; - } - - symbol_info_with_stack s; - s.symbol.MaxNameLen = symbol_info_with_stack::max_name_length; - s.symbol.SizeOfStruct = sizeof(boost::detail::winapi::SYMBOL_INFO_); - const bool sym_res = !!boost::detail::winapi::SymFromAddr( - symproc.process, reinterpret_cast(buffer[frame]), 0, &s.symbol - ); - if (sym_res) { - res = s.symbol.Name; - } - return res; - } -}; - -}}} // namespace boost::stacktrace::detail +#include +#include namespace boost { namespace stacktrace { stacktrace::stacktrace() BOOST_NOEXCEPT { - new (&impl_) boost::stacktrace::detail::backtrace_holder(); - boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::to_bt(impl_); + boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_); bt.frames_count = CaptureStackBackTrace(0, boost::stacktrace::detail::backtrace_holder::max_size, bt.buffer, 0); } diff --git a/src/backtrace.cpp b/src/backtrace.cpp index 0b80a61..17a791a 100644 --- a/src/backtrace.cpp +++ b/src/backtrace.cpp @@ -7,4 +7,4 @@ #define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS #define BOOST_STACKTRACE_USE_BACKTRACE #define BOOST_STACKTRACE_LINK -#include +#include "stacktrace_src.ipp" diff --git a/src/libunwind.cpp b/src/libunwind.cpp index 6d0d118..6da4753 100644 --- a/src/libunwind.cpp +++ b/src/libunwind.cpp @@ -7,4 +7,4 @@ #define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS #define BOOST_STACKTRACE_USE_LIBUNWIND #define BOOST_STACKTRACE_LINK -#include +#include "stacktrace_src.ipp" diff --git a/src/noop.cpp b/src/noop.cpp index 42a432b..6344e95 100644 --- a/src/noop.cpp +++ b/src/noop.cpp @@ -7,4 +7,4 @@ #define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS #define BOOST_STACKTRACE_USE_NOOP #define BOOST_STACKTRACE_LINK -#include +#include "stacktrace_src.ipp" diff --git a/src/stacktrace_src.ipp b/src/stacktrace_src.ipp new file mode 100644 index 0000000..6f463b2 --- /dev/null +++ b/src/stacktrace_src.ipp @@ -0,0 +1,73 @@ +// 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_SRC_STACKTRACE_IPP +#define BOOST_STACKTRACE_SRC_STACKTRACE_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include + + +#if defined(BOOST_STACKTRACE_USE_HEADER) +# include BOOST_STACKTRACE_USE_HEADER +#elif defined(BOOST_STACKTRACE_USE_NOOP) +# include +# include +#elif defined(BOOST_STACKTRACE_USE_WINDBG) +# include +# include +#elif defined(BOOST_STACKTRACE_USE_LIBUNWIND) +# include +# include +#elif defined(BOOST_STACKTRACE_USE_BACKTRACE) +# include +# include +#else +# error No suitable backtrace backend found +#endif + +#include + + +namespace boost { namespace stacktrace { + +// stacktrace::stacktrace() is defined in each backend separately. This is +// requered to avoid `boost::stacktrace::detail::backtrace_holder` apearing in +// stack traces. + +stacktrace::stacktrace(const stacktrace& bt) BOOST_NOEXCEPT { + new (&impl_) boost::stacktrace::detail::backtrace_holder( + boost::stacktrace::detail::to_bt(bt.impl_) + ); +} + +stacktrace& stacktrace::operator=(const stacktrace& bt) BOOST_NOEXCEPT { + boost::stacktrace::detail::to_bt(impl_) = boost::stacktrace::detail::to_bt(bt.impl_); + return *this; +} + +stacktrace::~stacktrace() BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT_MSG(sizeof(impl_) >= sizeof(boost::stacktrace::detail::backtrace_holder), "Too small storage for holding backtrace"); + boost::stacktrace::detail::to_bt(impl_).~backtrace_holder(); +} + +std::size_t stacktrace::size() const BOOST_NOEXCEPT { + return boost::stacktrace::detail::to_bt(impl_).size(); +} + +std::string stacktrace::operator[](std::size_t frame) const { + return boost::stacktrace::detail::to_bt(impl_).get_frame(frame); +} + + +}} + +#endif // BOOST_STACKTRACE_SRC_STACKTRACE_IPP diff --git a/src/windbg.cpp b/src/windbg.cpp index e165cae..8b69466 100644 --- a/src/windbg.cpp +++ b/src/windbg.cpp @@ -7,4 +7,4 @@ #define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS #define BOOST_STACKTRACE_USE_WINDBG #define BOOST_STACKTRACE_LINK -#include +#include "stacktrace_src.ipp"