mirror of
https://github.com/boostorg/stacktrace.git
synced 2026-01-23 18:12:11 +00:00
Move code around, prepare for optimizing the stack ostreaming operators
This commit is contained in:
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user