Move code around, prepare for optimizing the stack ostreaming operators

This commit is contained in:
Antony Polukhin
2017-01-03 11:59:55 +03:00
parent 7149a04002
commit 36061d4ef8
7 changed files with 153 additions and 175 deletions

View File

@@ -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 <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#include <string>
// 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 <boost/stacktrace/detail/backend.ipp>
#endif
/// @endcond
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_HPP

View File

@@ -12,7 +12,7 @@
# pragma once
#endif
#include <boost/stacktrace/detail/backend.hpp>
#include <boost/stacktrace/frame.hpp>
#if defined(BOOST_STACKTRACE_USE_NOOP)
# include <boost/stacktrace/detail/backend_noop.hpp>

View File

@@ -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

View File

@@ -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

View File

@@ -35,6 +35,7 @@ public:
}
};
template <class T>
class com_holder: boost::noncopyable {
T* holder_;
@@ -63,6 +64,7 @@ public:
}
};
inline bool try_init_com(com_holder<IDebugSymbols>& idebug, const com_global_initer& com) BOOST_NOEXCEPT {
com_holder<IDebugClient> iclient(com);
DebugCreate(__uuidof(IDebugClient), iclient.to_void_ptr_ptr());
@@ -93,8 +95,6 @@ inline bool try_init_com(com_holder<IDebugSymbols>& 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<IDebugSymbols>& idebug, const void* addr) {
std::string result;
const ULONG64 offset = reinterpret_cast<ULONG64>(addr);
@@ -140,17 +141,6 @@ inline std::string get_name_impl(const com_holder<IDebugSymbols>& idebug, const
}
std::string backend::get_name(const void* addr) {
com_global_initer com_guard;
com_holder<IDebugSymbols> 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<std::string, std::size_t> get_source_file_line_impl(const com_holder<IDebugSymbols>& idebug, const void* addr) {
std::pair<std::string, std::size_t> result;
const ULONG64 offset = reinterpret_cast<ULONG64>(addr);
@@ -198,40 +188,9 @@ inline std::pair<std::string, std::size_t> get_source_file_line_impl(const com_h
}
std::string backend::get_source_file(const void* addr) {
com_global_initer com_guard;
com_holder<IDebugSymbols> 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<IDebugSymbols> 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<ULONG64>(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<IDebugSymbols> idebug(com_guard);
boost::stacktrace::detail::com_global_initer com_guard;
boost::stacktrace::detail::com_holder<IDebugSymbols> 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<IDebugSymbols> 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<IDebugSymbols> 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<IDebugSymbols> 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<ULONG64>(addr_),
&line_num,
0,
0,
0,
0
));
return (is_ok ? line_num : 0);
}
}} // namespace boost::stacktrace
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_LINUX_HPP

View File

@@ -16,10 +16,65 @@
#include <string>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/stacktrace/detail/backend.hpp>
// 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<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT
}} // namespace boost::stacktrace
/// @cond
#undef BOOST_STACKTRACE_FUNCTION
#ifndef BOOST_STACKTRACE_LINK
# include <boost/stacktrace/detail/backend.ipp>
#endif
/// @endcond
#endif // BOOST_STACKTRACE_FRAME_HPP

View File

@@ -20,7 +20,6 @@
#include <boost/stacktrace/stacktrace_fwd.hpp>
#include <boost/stacktrace/frame.hpp>
#include <boost/stacktrace/detail/backend.hpp>
namespace boost {
// Forward declaration