diff --git a/include/boost/stacktrace.hpp b/include/boost/stacktrace.hpp index d01cc29..82c3920 100644 --- a/include/boost/stacktrace.hpp +++ b/include/boost/stacktrace.hpp @@ -150,13 +150,8 @@ std::basic_ostream& operator<<(std::basic_ostream #include #include +#include +#include #define UNW_LOCAL_ONLY #include @@ -74,6 +76,9 @@ struct backtrace_holder { 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; } diff --git a/include/boost/stacktrace/detail/backtrace_holder_linux.hpp b/include/boost/stacktrace/detail/backtrace_holder_linux.hpp index ab0bf04..1e80ed9 100644 --- a/include/boost/stacktrace/detail/backtrace_holder_linux.hpp +++ b/include/boost/stacktrace/detail/backtrace_holder_linux.hpp @@ -13,6 +13,8 @@ #endif #include +#include +#include #include #include @@ -34,18 +36,18 @@ struct backtrace_holder { return res; } - Dl_info dli; - if (!dladdr(buffer[frame], &dli)) { - return res; - } - if (dli.dli_sname) { + Dl_info dli; + if (!!dladdr(buffer[frame], &dli) && dli.dli_sname) { boost::core::scoped_demangled_name demangled(dli.dli_sname); if (demangled.get()) { res = demangled.get(); } else { res = dli.dli_sname; } + } else { + res = "?? at "; + res += to_hex_array(buffer[frame]).data(); } return res; diff --git a/include/boost/stacktrace/detail/backtrace_holder_windows.hpp b/include/boost/stacktrace/detail/backtrace_holder_windows.hpp index 3c1655a..393da38 100644 --- a/include/boost/stacktrace/detail/backtrace_holder_windows.hpp +++ b/include/boost/stacktrace/detail/backtrace_holder_windows.hpp @@ -12,6 +12,9 @@ # pragma once #endif +#include +#include + #include #include "DbgHelp.h" #include @@ -76,6 +79,9 @@ struct backtrace_holder { ); if (sym_res) { res = s.symbol.Name; + } else { + res = "?? at "; + res += to_hex_array(buffer[frame]).data(); } return res; } diff --git a/include/boost/stacktrace/detail/helpers.hpp b/include/boost/stacktrace/detail/helpers.hpp index d797e8f..64b8a49 100644 --- a/include/boost/stacktrace/detail/helpers.hpp +++ b/include/boost/stacktrace/detail/helpers.hpp @@ -12,9 +12,6 @@ # pragma once #endif -#include -#include - namespace boost { namespace stacktrace { namespace detail { struct backtrace_holder; @@ -39,33 +36,6 @@ inline boost::stacktrace::detail::backtrace_holder& construct_bt_and_return(back return data; } -/* -BOOST_STATIC_CONSTEXPR char to_hex_array[] = "0123456789ABCDEF"; - -template -inline boost::array to_hex(T addr) BOOST_NOEXCEPT { - boost::array ret = {"0x"}; - ret.back() = '\0'; - BOOST_STATIC_ASSERT_MSG(!boost::is_pointer::value, ""); - - const std::size_t s = ( - (addr >> (sizeof(addr) / 2 * 8)) ? sizeof(addr) : sizeof(addr) / 2 - ); - - char* out = ret.data() + s * 2 + 1; - - for (std::size_t i = 0; i < s; ++i) { - const unsigned char tmp_addr = (addr & 0xFFu); - *out = to_hex_array[tmp_addr & 0xF]; - -- out; - *out = to_hex_array[tmp_addr >> 4]; - -- out; - addr >>= 8; - } - - return ret; -}*/ - }}} // namespace boost::stacktrace::detail #endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_HELPERS_HPP diff --git a/include/boost/stacktrace/detail/stacktrace_linux.hpp b/include/boost/stacktrace/detail/stacktrace_linux.hpp index 24399fe..9a5693b 100644 --- a/include/boost/stacktrace/detail/stacktrace_linux.hpp +++ b/include/boost/stacktrace/detail/stacktrace_linux.hpp @@ -21,6 +21,9 @@ namespace boost { namespace stacktrace { stacktrace::stacktrace() BOOST_NOEXCEPT { 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); + if (bt.buffer[bt.frames_count] == 0) { + -- bt.frames_count; + } } }} // namespace boost::stacktrace diff --git a/include/boost/stacktrace/detail/to_hex_array.hpp b/include/boost/stacktrace/detail/to_hex_array.hpp new file mode 100644 index 0000000..d56ca45 --- /dev/null +++ b/include/boost/stacktrace/detail/to_hex_array.hpp @@ -0,0 +1,66 @@ +// 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_STACKTRACE_TO_HEX_ARRAY_HPP +#define BOOST_STACKTRACE_DETAIL_STACKTRACE_TO_HEX_ARRAY_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include +#include + +namespace boost { namespace stacktrace { namespace detail { + +BOOST_STATIC_CONSTEXPR char to_hex_array_bytes[] = "0123456789ABCDEF"; + +template +inline bool can_be_safely_trimmed_by(T addr, std::size_t part) BOOST_NOEXCEPT { + return !(addr >> (sizeof(T) / part * 8)); +} + +template +inline boost::array to_hex_array(T addr) BOOST_NOEXCEPT { + boost::array ret = {"0x"}; + ret.back() = '\0'; + BOOST_STATIC_ASSERT_MSG(!boost::is_pointer::value, ""); + + const std::size_t s = ( + can_be_safely_trimmed_by(addr, 2) + ? (can_be_safely_trimmed_by(addr, 4) + ? (can_be_safely_trimmed_by(addr, 8) + ? sizeof(addr) / 8 + : sizeof(addr) / 4) + : sizeof(addr) / 2) + : sizeof(addr) + ); + + char* out = ret.data() + s * 2 + 1; + + for (std::size_t i = 0; i < s; ++i) { + const unsigned char tmp_addr = (addr & 0xFFu); + *out = to_hex_array_bytes[tmp_addr & 0xF]; + -- out; + *out = to_hex_array_bytes[tmp_addr >> 4]; + -- out; + addr >>= 8; + } + + return ret; +} + +inline boost::array to_hex_array(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/test/test.cpp b/test/test.cpp index e601893..b01f52d 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -33,7 +33,8 @@ void test_deeply_nested_namespaces() { BOOST_TEST(ss.str().find("get_backtrace_from_nested_namespaces") != std::string::npos); #endif - // TODO: BOOST_TEST(return_from_nested_namespaces() != return_from_nested_namespaces()); + stacktrace ns1 = return_from_nested_namespaces(); + BOOST_TEST(ns1 != return_from_nested_namespaces()); // Different addresses in test_deeply_nested_namespaces() function } void test_nested() {