mirror of
https://github.com/boostorg/stacktrace.git
synced 2026-01-22 05:42:25 +00:00
Big refactoring to allow in the future to setup stacktrace depth
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
// sym_from_addr.hpp --------------------------------------------------------------//
|
||||
|
||||
// Copyright 2016 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
|
||||
#ifndef BOOST_DETAIL_WINAPI_SYM_FROM_ADDR_HPP
|
||||
#define BOOST_DETAIL_WINAPI_SYM_FROM_ADDR_HPP
|
||||
|
||||
#include <boost/detail/winapi/basic_types.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_USE_WINDOWS_H )
|
||||
extern "C" {
|
||||
struct _SYMBOL_INFO;
|
||||
|
||||
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI SymFromAddr(
|
||||
/*HANDLE*/ boost::detail::winapi::HANDLE_ hProcess,
|
||||
/*DWORD64*/ boost::detail::winapi::ULONGLONG_ Address,
|
||||
/*PDWORD64*/ boost::detail::winapi::ULONGLONG_* Displacement,
|
||||
/*PSYMBOL_INFO*/ _SYMBOL_INFO* Symbol);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
namespace winapi {
|
||||
|
||||
typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _SYMBOL_INFO {
|
||||
ULONG_ SizeOfStruct;
|
||||
ULONG_ TypeIndex;
|
||||
ULONGLONG_ Reserved[2];
|
||||
ULONG_ Index;
|
||||
ULONG_ Size;
|
||||
ULONGLONG_ ModBase;
|
||||
ULONG_ Flags;
|
||||
ULONGLONG_ Value;
|
||||
ULONGLONG_ Address;
|
||||
ULONG_ Register;
|
||||
ULONG_ Scope;
|
||||
ULONG_ Tag;
|
||||
ULONG_ NameLen;
|
||||
ULONG_ MaxNameLen;
|
||||
CHAR_ Name[1];
|
||||
} SYMBOL_INFO_, *PSYMBOL_INFO_;
|
||||
|
||||
using ::SymFromAddr;
|
||||
|
||||
BOOST_FORCEINLINE BOOL_ SymFromAddr(HANDLE_ hProcess, ULONGLONG_ Address, ULONGLONG_* Displacement, PSYMBOL_INFO_ Symbol)
|
||||
{
|
||||
return ::SymFromAddr(hProcess, Address, Displacement, reinterpret_cast< ::_SYMBOL_INFO* >(Symbol));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_DETAIL_WINAPI_SYM_FROM_ADDR_HPP
|
||||
@@ -21,64 +21,7 @@
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
/// @cond
|
||||
|
||||
// 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_LIBUNWIND) \
|
||||
&& !defined(BOOST_STACKTRACE_USE_BACKTRACE) &&!defined(BOOST_STACKTRACE_USE_HEADER)
|
||||
|
||||
#if defined(__has_include) && (!defined(__GNUC__) || __GNUC__ > 4 || BOOST_CLANG)
|
||||
# if __has_include(<libunwind.h>)
|
||||
# define BOOST_STACKTRACE_USE_LIBUNWIND
|
||||
# elif __has_include(<execinfo.h>)
|
||||
# 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
|
||||
# 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
|
||||
# if defined(BOOST_STACKTRACE_USE_NOOP)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_noop.hpp>
|
||||
# elif defined(BOOST_STACKTRACE_USE_WINDBG)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_windows.hpp>
|
||||
# elif defined(BOOST_STACKTRACE_USE_LIBUNWIND)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_libunwind.hpp>
|
||||
# elif defined(BOOST_STACKTRACE_USE_BACKTRACE)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_linux.hpp>
|
||||
# else
|
||||
# error No suitable backtrace backend found
|
||||
# endif
|
||||
#endif
|
||||
/// @endcond
|
||||
#include <boost/stacktrace/detail/backend.hpp>
|
||||
|
||||
namespace boost { namespace stacktrace {
|
||||
|
||||
@@ -90,12 +33,12 @@ namespace detail { class iterator; }
|
||||
/// Non-owning class that references the frame information stored inside the boost::stacktrace::stacktrace class.
|
||||
class frame_view {
|
||||
/// @cond
|
||||
const stacktrace* impl_;
|
||||
const boost::stacktrace::detail::backend* impl_;
|
||||
std::size_t frame_no_;
|
||||
|
||||
frame_view(); // = delete
|
||||
|
||||
frame_view(const stacktrace* impl, std::size_t frame_no) BOOST_NOEXCEPT
|
||||
frame_view(const boost::stacktrace::detail::backend* impl, std::size_t frame_no) BOOST_NOEXCEPT
|
||||
: impl_(impl)
|
||||
, frame_no_(frame_no)
|
||||
{}
|
||||
@@ -156,7 +99,7 @@ namespace detail {
|
||||
|
||||
frame_view f_;
|
||||
|
||||
iterator(const stacktrace* impl, std::size_t frame_no) BOOST_NOEXCEPT
|
||||
iterator(const boost::stacktrace::detail::backend* impl, std::size_t frame_no) BOOST_NOEXCEPT
|
||||
: f_(impl, frame_no)
|
||||
{}
|
||||
|
||||
@@ -195,21 +138,11 @@ namespace detail {
|
||||
/// Class that on construction copies minimal information about call stack into its internals and provides access to that information.
|
||||
class stacktrace {
|
||||
/// @cond
|
||||
#ifdef BOOST_STACKTRACE_LINK
|
||||
BOOST_STATIC_CONSTEXPR std::size_t max_implementation_size = sizeof(void*) * 110u;
|
||||
boost::aligned_storage<max_implementation_size>::type impl_;
|
||||
#else
|
||||
boost::stacktrace::detail::backtrace_holder impl_;
|
||||
#endif
|
||||
std::size_t hash_code_;
|
||||
boost::stacktrace::detail::backend back_;
|
||||
|
||||
BOOST_STACKTRACE_FUNCTION std::string get_name(std::size_t frame_no) const;
|
||||
BOOST_STACKTRACE_FUNCTION const void* get_address(std::size_t frame_no) const BOOST_NOEXCEPT;
|
||||
BOOST_STACKTRACE_FUNCTION std::string get_source_file(std::size_t frame_no) const;
|
||||
BOOST_STACKTRACE_FUNCTION std::size_t get_source_line(std::size_t frame_no) const BOOST_NOEXCEPT;
|
||||
/// @endcond
|
||||
|
||||
friend class frame_view;
|
||||
public:
|
||||
typedef frame_view reference;
|
||||
|
||||
@@ -222,21 +155,35 @@ public:
|
||||
/// @brief Stores the current function call sequence inside the class.
|
||||
///
|
||||
/// @b Complexity: O(N) where N is call seaquence length, O(1) for noop backend.
|
||||
BOOST_STACKTRACE_FUNCTION stacktrace() BOOST_NOEXCEPT;
|
||||
stacktrace() BOOST_NOEXCEPT
|
||||
: impl_()
|
||||
, hash_code_()
|
||||
, back_(&impl_, sizeof(impl_), hash_code_)
|
||||
{}
|
||||
|
||||
/// @b Complexity: O(1)
|
||||
BOOST_STACKTRACE_FUNCTION stacktrace(const stacktrace& bt) BOOST_NOEXCEPT;
|
||||
stacktrace(const stacktrace& st) BOOST_NOEXCEPT
|
||||
: impl_()
|
||||
, hash_code_(st.hash_code_)
|
||||
, back_(st.back_, &impl_)
|
||||
{}
|
||||
|
||||
/// @b Complexity: O(1)
|
||||
BOOST_STACKTRACE_FUNCTION stacktrace& operator=(const stacktrace& bt) BOOST_NOEXCEPT;
|
||||
stacktrace& operator=(const stacktrace& st) BOOST_NOEXCEPT {
|
||||
back_.~backend();
|
||||
new (&back_) boost::stacktrace::detail::backend(st.back_, &impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @b Complexity: O(N) for libunwind, O(1) for other backends.
|
||||
BOOST_STACKTRACE_FUNCTION ~stacktrace() BOOST_NOEXCEPT;
|
||||
~stacktrace() BOOST_NOEXCEPT {}
|
||||
|
||||
/// @returns Number of function names stored inside the class.
|
||||
///
|
||||
/// @b Complexity: O(1)
|
||||
BOOST_STACKTRACE_FUNCTION std::size_t size() const BOOST_NOEXCEPT;
|
||||
std::size_t size() const BOOST_NOEXCEPT {
|
||||
return back_.size();
|
||||
}
|
||||
|
||||
/// @param frame_no Zero based index of frame to return. 0
|
||||
/// is the function index where stacktrace was constructed and
|
||||
@@ -250,22 +197,22 @@ public:
|
||||
|
||||
|
||||
/// @b Complexity: O(1)
|
||||
const_iterator begin() const BOOST_NOEXCEPT { return const_iterator(this, 0); }
|
||||
const_iterator begin() const BOOST_NOEXCEPT { return const_iterator(&back_, 0); }
|
||||
/// @b Complexity: O(1)
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT { return const_iterator(this, 0); }
|
||||
const_iterator cbegin() const BOOST_NOEXCEPT { return const_iterator(&back_, 0); }
|
||||
/// @b Complexity: O(1)
|
||||
const_iterator end() const BOOST_NOEXCEPT { return const_iterator(this, size()); }
|
||||
const_iterator end() const BOOST_NOEXCEPT { return const_iterator(&back_, size()); }
|
||||
/// @b Complexity: O(1)
|
||||
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(this, size()); }
|
||||
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(&back_, size()); }
|
||||
|
||||
/// @b Complexity: O(1)
|
||||
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, 0) ); }
|
||||
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(&back_, 0) ); }
|
||||
/// @b Complexity: O(1)
|
||||
const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, 0) ); }
|
||||
const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(&back_, 0) ); }
|
||||
/// @b Complexity: O(1)
|
||||
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, size()) ); }
|
||||
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(&back_, size()) ); }
|
||||
/// @b Complexity: O(1)
|
||||
const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, size()) ); }
|
||||
const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(&back_, size()) ); }
|
||||
|
||||
|
||||
/// @brief Allows to check that stack trace capturing was successful.
|
||||
@@ -277,12 +224,16 @@ public:
|
||||
/// @brief Compares stacktraces for less, order is platform dependant.
|
||||
///
|
||||
/// @b Complexity: Amortized O(1); worst case O(size())
|
||||
BOOST_STACKTRACE_FUNCTION bool operator< (const stacktrace& rhs) const BOOST_NOEXCEPT;
|
||||
bool operator< (const stacktrace& rhs) const BOOST_NOEXCEPT {
|
||||
return hash_code_ < rhs.hash_code_ || (hash_code_ == rhs.hash_code_ && back_ < rhs.back_);
|
||||
}
|
||||
|
||||
/// @brief Compares stacktraces for equality.
|
||||
///
|
||||
/// @b Complexity: Amortized O(1); worst case O(size())
|
||||
BOOST_STACKTRACE_FUNCTION bool operator==(const stacktrace& rhs) const BOOST_NOEXCEPT;
|
||||
bool operator==(const stacktrace& rhs) const BOOST_NOEXCEPT {
|
||||
return hash_code_ == rhs.hash_code_ && back_ == rhs.back_;
|
||||
}
|
||||
|
||||
/// @brief Returns hashed code of the stacktrace.
|
||||
///
|
||||
@@ -371,12 +322,4 @@ 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/stacktrace.ipp>
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
#endif // BOOST_STACKTRACE_STACKTRACE_HPP
|
||||
|
||||
103
include/boost/stacktrace/detail/backend.hpp
Normal file
103
include/boost/stacktrace/detail/backend.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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 <boost/core/noncopyable.hpp>
|
||||
#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_LIBUNWIND) \
|
||||
&& !defined(BOOST_STACKTRACE_USE_BACKTRACE) &&!defined(BOOST_STACKTRACE_USE_HEADER)
|
||||
|
||||
#if defined(__has_include) && (!defined(__GNUC__) || __GNUC__ > 4 || BOOST_CLANG)
|
||||
# if __has_include(<libunwind.h>)
|
||||
# define BOOST_STACKTRACE_USE_LIBUNWIND
|
||||
# elif __has_include(<execinfo.h>)
|
||||
# define BOOST_STACKTRACE_USE_BACKTRACE
|
||||
# elif __has_include("Dbgeng.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
|
||||
# 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 BOOST_FORCEINLINE
|
||||
#endif
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
struct backtrace_holder;
|
||||
|
||||
// Class that implements the actual backtracing
|
||||
class backend: boost::noncopyable {
|
||||
void* data_;
|
||||
|
||||
inline boost::stacktrace::detail::backtrace_holder& impl() BOOST_NOEXCEPT {
|
||||
return *reinterpret_cast<boost::stacktrace::detail::backtrace_holder*>(data_);
|
||||
}
|
||||
|
||||
inline const boost::stacktrace::detail::backtrace_holder& impl() const BOOST_NOEXCEPT {
|
||||
return *reinterpret_cast<const boost::stacktrace::detail::backtrace_holder*>(data_);
|
||||
}
|
||||
|
||||
public:
|
||||
BOOST_STACKTRACE_FUNCTION backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_NOEXCEPT;
|
||||
BOOST_STACKTRACE_FUNCTION std::string get_name(std::size_t frame_no) const;
|
||||
BOOST_STACKTRACE_FUNCTION const void* get_address(std::size_t frame_no) const BOOST_NOEXCEPT;
|
||||
BOOST_STACKTRACE_FUNCTION std::string get_source_file(std::size_t frame_no) const;
|
||||
BOOST_STACKTRACE_FUNCTION std::size_t get_source_line(std::size_t frame_no) const BOOST_NOEXCEPT;
|
||||
BOOST_STACKTRACE_FUNCTION bool operator< (const backend& rhs) const BOOST_NOEXCEPT;
|
||||
BOOST_STACKTRACE_FUNCTION bool operator==(const backend& rhs) const BOOST_NOEXCEPT;
|
||||
|
||||
BOOST_STACKTRACE_FUNCTION backend(const backend& b, void* memory) BOOST_NOEXCEPT;
|
||||
BOOST_STACKTRACE_FUNCTION ~backend() BOOST_NOEXCEPT;
|
||||
BOOST_STACKTRACE_FUNCTION std::size_t size() const BOOST_NOEXCEPT;
|
||||
};
|
||||
|
||||
}}} // 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
|
||||
29
include/boost/stacktrace/detail/backend.ipp
Normal file
29
include/boost/stacktrace/detail/backend.ipp
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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_IPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKEND_IPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/backend.hpp>
|
||||
|
||||
#if defined(BOOST_STACKTRACE_USE_NOOP)
|
||||
# include <boost/stacktrace/detail/backend_noop.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_WINDBG)
|
||||
# include <boost/stacktrace/detail/backend_windows.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_LIBUNWIND)
|
||||
# include <boost/stacktrace/detail/backend_libunwind.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_BACKTRACE)
|
||||
# include <boost/stacktrace/detail/backend_linux.hpp>
|
||||
#else
|
||||
# error No suitable backtrace backend found
|
||||
#endif
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_IPP
|
||||
35
include/boost/stacktrace/detail/backend_common.ipp
Normal file
35
include/boost/stacktrace/detail/backend_common.ipp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_COMMON_IPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKEND_COMMON_IPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
backend::backend(const backend& b, void* memory) BOOST_NOEXCEPT
|
||||
: data_(memory)
|
||||
{
|
||||
new(data_) backtrace_holder(
|
||||
b.impl()
|
||||
);
|
||||
}
|
||||
|
||||
backend::~backend() BOOST_NOEXCEPT {
|
||||
reinterpret_cast<backtrace_holder*>(data_)->~backtrace_holder();
|
||||
}
|
||||
|
||||
std::size_t backend::size() const BOOST_NOEXCEPT {
|
||||
return impl().frames_count;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_COMMON_IPP
|
||||
180
include/boost/stacktrace/detail/backend_libunwind.hpp
Normal file
180
include/boost/stacktrace/detail/backend_libunwind.hpp
Normal file
@@ -0,0 +1,180 @@
|
||||
// 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_LIBUNWIND_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <cstring>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
struct bt_pair {
|
||||
std::string name;
|
||||
const void* addr;
|
||||
};
|
||||
|
||||
inline bool operator< (const bt_pair& lhs, const bt_pair& rhs) BOOST_NOEXCEPT {
|
||||
return lhs.addr < rhs.addr;
|
||||
}
|
||||
|
||||
inline bool operator== (const bt_pair& lhs, const bt_pair& rhs) BOOST_NOEXCEPT {
|
||||
return lhs.addr == rhs.addr;
|
||||
}
|
||||
|
||||
struct backtrace_holder {
|
||||
std::size_t frames_count;
|
||||
boost::shared_ptr<bt_pair[]> frames;
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
res += " +";
|
||||
res += to_hex_array(offp).data();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_NOEXCEPT
|
||||
: data_(memory)
|
||||
{
|
||||
new (data_) backtrace_holder();
|
||||
impl().frames_count = 0;
|
||||
hash_code = 0;
|
||||
|
||||
unw_context_t uc;
|
||||
if (unw_getcontext(&uc) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
{ // Counting frames_count
|
||||
unw_cursor_t cursor;
|
||||
if (unw_init_local(&cursor, &uc) != 0) {
|
||||
return;
|
||||
}
|
||||
while (unw_step(&cursor) > 0) {
|
||||
++ impl().frames_count;
|
||||
}
|
||||
}
|
||||
|
||||
unw_cursor_t cursor;
|
||||
if (unw_init_local(&cursor, &uc) != 0) {
|
||||
impl().frames_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_TRY {
|
||||
impl().frames = boost::make_shared<boost::stacktrace::detail::bt_pair[]>(impl().frames_count);
|
||||
std::size_t i = 0;
|
||||
while (unw_step(&cursor) > 0){
|
||||
impl().frames[i].name = get_frame_impl(cursor);
|
||||
unw_proc_info_t inf;
|
||||
const int res = unw_get_proc_info(&cursor, &inf);
|
||||
(void)res;
|
||||
impl().frames[i].addr = reinterpret_cast<void*>(inf.start_ip ? inf.start_ip : inf.gp);
|
||||
boost::hash_combine(hash_code, impl().frames[i].name);
|
||||
++ i;
|
||||
}
|
||||
} BOOST_CATCH(...) {}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
std::string backend::get_name(std::size_t frame) const {
|
||||
if (frame < impl().frames_count) {
|
||||
return impl().frames[frame].name;
|
||||
} else {
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return impl().frames[frame].addr;
|
||||
}
|
||||
|
||||
std::string backend::get_source_file(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::size_t backend::get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool backend::operator< (const backend& rhs) const BOOST_NOEXCEPT {
|
||||
if (impl().frames_count != rhs.impl().frames_count) {
|
||||
return impl().frames_count < rhs.impl().frames_count;
|
||||
} else if (impl().frames.get() == rhs.impl().frames.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::lexicographical_compare(
|
||||
impl().frames.get(), impl().frames.get() + impl().frames_count,
|
||||
rhs.impl().frames.get(), rhs.impl().frames.get() + rhs.impl().frames_count
|
||||
);
|
||||
}
|
||||
|
||||
bool backend::operator==(const backend& rhs) const BOOST_NOEXCEPT {
|
||||
if (impl().frames_count != rhs.impl().frames_count) {
|
||||
return false;
|
||||
} else if (impl().frames.get() == rhs.impl().frames.get()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::equal(
|
||||
impl().frames.get(), impl().frames.get() + impl().frames_count,
|
||||
rhs.impl().frames.get()
|
||||
);
|
||||
}
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#include <boost/stacktrace/detail/backend_common.ipp>
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP
|
||||
117
include/boost/stacktrace/detail/backend_linux.hpp
Normal file
117
include/boost/stacktrace/detail/backend_linux.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// 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_LINUX_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKEND_LINUX_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
struct backtrace_holder {
|
||||
std::size_t frames_count;
|
||||
void* buffer[1];
|
||||
|
||||
backtrace_holder() BOOST_NOEXCEPT {}
|
||||
|
||||
backtrace_holder(const backtrace_holder& d) BOOST_NOEXCEPT
|
||||
: frames_count(d.frames_count)
|
||||
{
|
||||
std::copy(d.buffer, d.buffer + frames_count, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_NOEXCEPT
|
||||
: data_(memory)
|
||||
{
|
||||
new (data_) backtrace_holder();
|
||||
impl().frames_count = 0;
|
||||
hash_code = 0;
|
||||
|
||||
impl().frames_count = ::backtrace(impl().buffer, 1 + (size - sizeof(backtrace_holder)) / sizeof(void*));
|
||||
if (impl().buffer[impl().frames_count - 1] == 0) {
|
||||
-- impl().frames_count;
|
||||
}
|
||||
|
||||
hash_code = boost::hash_range(impl().buffer, impl().buffer + impl().frames_count);
|
||||
}
|
||||
|
||||
std::string backend::get_name(std::size_t frame) const {
|
||||
std::string res;
|
||||
if (frame >= impl().frames_count) {
|
||||
return res;
|
||||
}
|
||||
|
||||
Dl_info dli;
|
||||
if (!!dladdr(impl().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(impl().buffer[frame]).data();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return impl().buffer[frame];
|
||||
}
|
||||
|
||||
std::string backend::get_source_file(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::size_t backend::get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool backend::operator< (const backend& rhs) const BOOST_NOEXCEPT {
|
||||
if (impl().frames_count != rhs.impl().frames_count) {
|
||||
return impl().frames_count < rhs.impl().frames_count;
|
||||
} else if (this == &rhs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::lexicographical_compare(
|
||||
impl().buffer, impl().buffer + impl().frames_count,
|
||||
rhs.impl().buffer, rhs.impl().buffer + rhs.impl().frames_count
|
||||
);
|
||||
}
|
||||
|
||||
bool backend::operator==(const backend& rhs) const BOOST_NOEXCEPT {
|
||||
if (impl().frames_count != rhs.impl().frames_count) {
|
||||
return false;
|
||||
} else if (this == &rhs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::equal(
|
||||
impl().buffer, impl().buffer + impl().frames_count,
|
||||
rhs.impl().buffer
|
||||
);
|
||||
}
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#include <boost/stacktrace/detail/backend_common.ipp>
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_LINUX_HPP
|
||||
57
include/boost/stacktrace/detail/backend_noop.hpp
Normal file
57
include/boost/stacktrace/detail/backend_noop.hpp
Normal file
@@ -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_BACKEND_NOOP_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKEND_NOOP_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_NOEXCEPT
|
||||
: data_(memory)
|
||||
{}
|
||||
|
||||
std::string backend::get_name(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const void* backend::get_address(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string backend::get_source_file(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::size_t backend::get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool backend::operator< (const backend& /*rhs*/) const BOOST_NOEXCEPT {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool backend::operator==(const backend& /*rhs*/) const BOOST_NOEXCEPT {
|
||||
return true;
|
||||
}
|
||||
|
||||
backend::backend(const backend& b, void* memory) BOOST_NOEXCEPT
|
||||
: data_(memory)
|
||||
{}
|
||||
|
||||
backend::~backend() BOOST_NOEXCEPT {}
|
||||
|
||||
std::size_t backend::size() const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP
|
||||
267
include/boost/stacktrace/detail/backend_windows.hpp
Normal file
267
include/boost/stacktrace/detail/backend_windows.hpp
Normal file
@@ -0,0 +1,267 @@
|
||||
// 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_WINDOWS_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKEND_WINDOWS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <windows.h>
|
||||
#include "Dbgeng.h"
|
||||
|
||||
#include <boost/detail/winapi/get_current_process.hpp>
|
||||
|
||||
#pragma comment(lib, "ole32.lib")
|
||||
#pragma comment(lib, "Dbgeng.lib")
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
template <class T>
|
||||
class com_holder: boost::noncopyable {
|
||||
T* holder_;
|
||||
|
||||
public:
|
||||
com_holder() BOOST_NOEXCEPT
|
||||
: holder_(0)
|
||||
{}
|
||||
|
||||
T* operator->() const BOOST_NOEXCEPT {
|
||||
return holder_;
|
||||
}
|
||||
|
||||
void** to_void_ptr_ptr() BOOST_NOEXCEPT {
|
||||
return reinterpret_cast<void**>(&holder_);
|
||||
}
|
||||
|
||||
bool is_inited() const BOOST_NOEXCEPT {
|
||||
return !!holder_;
|
||||
}
|
||||
|
||||
void reset() const BOOST_NOEXCEPT {
|
||||
if (holder_) {
|
||||
holder_->Release();
|
||||
}
|
||||
}
|
||||
|
||||
~com_holder() BOOST_NOEXCEPT {
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
inline bool try_init_com(com_holder<IDebugSymbols>& idebug_) BOOST_NOEXCEPT {
|
||||
if (idebug_.is_inited()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
|
||||
com_holder<IDebugClient> iclient;
|
||||
DebugCreate(__uuidof(IDebugClient), iclient.to_void_ptr_ptr());
|
||||
|
||||
com_holder<IDebugControl> icontrol;
|
||||
iclient->QueryInterface(__uuidof(IDebugControl), icontrol.to_void_ptr_ptr());
|
||||
|
||||
const bool res1 = (S_OK == iclient->AttachProcess(
|
||||
0,
|
||||
GetCurrentProcessId(),
|
||||
DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND)
|
||||
);
|
||||
if (!res1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool res2 = (S_OK == icontrol->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE));
|
||||
if (!res2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool res = (S_OK == iclient->QueryInterface(__uuidof(IDebugSymbols), idebug_.to_void_ptr_ptr()));
|
||||
if (!res) {
|
||||
idebug_.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct backtrace_holder {
|
||||
std::size_t frames_count;
|
||||
void* buffer[1];
|
||||
|
||||
backtrace_holder() BOOST_NOEXCEPT {}
|
||||
|
||||
backtrace_holder(const backtrace_holder& d) BOOST_NOEXCEPT
|
||||
: frames_count(d.frames_count)
|
||||
{
|
||||
std::copy(d.buffer, d.buffer + frames_count, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_NOEXCEPT
|
||||
: data_(memory)
|
||||
{
|
||||
new (data_) backtrace_holder();
|
||||
impl().frames_count = 0;
|
||||
hash_code = 0;
|
||||
boost::detail::winapi::ULONG_ hc = 0;
|
||||
impl().frames_count = CaptureStackBackTrace(0, 1 + (size - sizeof(backtrace_holder)) / sizeof(void*), impl().buffer, &hc);
|
||||
boost::hash_combine(hash_code, hc);
|
||||
}
|
||||
|
||||
std::string backend::get_name(std::size_t frame) const {
|
||||
std::string result;
|
||||
if (frame >= impl().frames_count) {
|
||||
return result;
|
||||
}
|
||||
|
||||
com_holder<IDebugSymbols> idebug_;
|
||||
if (!try_init_com(idebug_)) {
|
||||
return result;
|
||||
}
|
||||
const ULONG64 offset = reinterpret_cast<ULONG64>(impl().buffer[frame]);
|
||||
|
||||
char name[256];
|
||||
name[0] = '\0';
|
||||
ULONG size = 0;
|
||||
bool res = (S_OK == idebug_->GetNameByOffset(
|
||||
offset,
|
||||
name,
|
||||
sizeof(name),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
|
||||
if (!res && size != 0) {
|
||||
result.resize(size);
|
||||
res = (S_OK == idebug_->GetNameByOffset(
|
||||
offset,
|
||||
&result[0],
|
||||
static_cast<ULONG>(result.size()),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
} else if (res) {
|
||||
result = name;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
result.clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return impl().buffer[frame];
|
||||
}
|
||||
|
||||
std::string backend::get_source_file(std::size_t frame) const {
|
||||
std::string result;
|
||||
if (frame >= impl().frames_count) {
|
||||
return result;
|
||||
}
|
||||
|
||||
com_holder<IDebugSymbols> idebug_;
|
||||
if (!try_init_com(idebug_)) {
|
||||
return result;
|
||||
}
|
||||
const ULONG64 offset = reinterpret_cast<ULONG64>(impl().buffer[frame]);
|
||||
|
||||
char name[256];
|
||||
name[0] = 0;
|
||||
ULONG size = 0;
|
||||
bool res = (S_OK == idebug_->GetLineByOffset(
|
||||
offset,
|
||||
0,
|
||||
name,
|
||||
sizeof(name),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
|
||||
if (!res && size != 0) {
|
||||
result.resize(size);
|
||||
res = (S_OK == idebug_->GetLineByOffset(
|
||||
offset,
|
||||
0,
|
||||
&result[0],
|
||||
static_cast<ULONG>(result.size()),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
} else if (res) {
|
||||
result = name;
|
||||
}
|
||||
|
||||
|
||||
if (!res) {
|
||||
result.clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::size_t backend::get_source_line(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
ULONG line_num = 0;
|
||||
|
||||
com_holder<IDebugSymbols> idebug_;
|
||||
if (!try_init_com(idebug_)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const bool is_ok = (S_OK == idebug_->GetLineByOffset(
|
||||
reinterpret_cast<ULONG64>(impl().buffer[frame]),
|
||||
&line_num,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
));
|
||||
|
||||
return (is_ok ? line_num : 0);
|
||||
}
|
||||
|
||||
bool backend::operator< (const backend& rhs) const BOOST_NOEXCEPT {
|
||||
if (impl().frames_count != rhs.impl().frames_count) {
|
||||
return impl().frames_count < rhs.impl().frames_count;
|
||||
} else if (this == &rhs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::lexicographical_compare(
|
||||
impl().buffer, impl().buffer + impl().frames_count,
|
||||
rhs.impl().buffer, rhs.impl().buffer + rhs.impl().frames_count
|
||||
);
|
||||
}
|
||||
|
||||
bool backend::operator==(const backend& rhs) const BOOST_NOEXCEPT {
|
||||
if (impl().frames_count != rhs.impl().frames_count) {
|
||||
return false;
|
||||
} else if (this == &rhs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::equal(
|
||||
impl().buffer, impl().buffer + impl().frames_count,
|
||||
rhs.impl().buffer
|
||||
);
|
||||
}
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#include <boost/stacktrace/detail/backend_common.ipp>
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_LINUX_HPP
|
||||
@@ -1,135 +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_BACKTRACE_HOLDER_LIBUNWIND_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LIBUNWIND_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <cstring>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
struct bt_pair {
|
||||
std::string name;
|
||||
const void* addr;
|
||||
};
|
||||
|
||||
inline bool operator< (const bt_pair& lhs, const bt_pair& rhs) BOOST_NOEXCEPT {
|
||||
return lhs.addr < rhs.addr;
|
||||
}
|
||||
|
||||
inline bool operator== (const bt_pair& lhs, const bt_pair& rhs) BOOST_NOEXCEPT {
|
||||
return lhs.addr == rhs.addr;
|
||||
}
|
||||
|
||||
struct backtrace_holder {
|
||||
std::size_t frames_count;
|
||||
boost::shared_ptr<bt_pair[]> frames;
|
||||
|
||||
inline std::size_t size() const BOOST_NOEXCEPT {
|
||||
return frames_count;
|
||||
}
|
||||
|
||||
inline const void* get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return frames[frame].addr;
|
||||
}
|
||||
|
||||
inline std::string get_source_file(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
inline std::size_t get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::string get_frame(std::size_t frame) const {
|
||||
if (frame < frames_count) {
|
||||
return frames[frame].name;
|
||||
} 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
|
||||
}
|
||||
|
||||
res += " +";
|
||||
res += to_hex_array(offp).data();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return frames_count < rhs.frames_count;
|
||||
} else if (frames.get() == rhs.frames.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::lexicographical_compare(
|
||||
frames.get(), frames.get() + frames_count,
|
||||
rhs.frames.get(), rhs.frames.get() + rhs.frames_count
|
||||
);
|
||||
}
|
||||
|
||||
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return false;
|
||||
} else if (frames.get() == rhs.frames.get()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::equal(
|
||||
frames.get(), frames.get() + frames_count,
|
||||
rhs.frames.get()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LIBUNWIND_HPP
|
||||
@@ -1,96 +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_BACKTRACE_HOLDER_LINUX_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LINUX_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
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 const void* get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return buffer[frame];
|
||||
}
|
||||
|
||||
inline std::string get_source_file(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
inline std::size_t get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) && 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;
|
||||
}
|
||||
|
||||
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return frames_count < rhs.frames_count;
|
||||
} else if (this == &rhs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::lexicographical_compare(
|
||||
buffer, buffer + frames_count,
|
||||
rhs.buffer, rhs.buffer + rhs.frames_count
|
||||
);
|
||||
}
|
||||
|
||||
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return false;
|
||||
} else if (this == &rhs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::equal(
|
||||
buffer, buffer + frames_count,
|
||||
rhs.buffer
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LINUX_HPP
|
||||
@@ -1,50 +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_BACKTRACE_HOLDER_NOOP_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_NOOP_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#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 const void* get_address(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::string get_source_file(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
inline std::size_t get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::string get_frame(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
inline bool operator< (const backtrace_holder& /*rhs*/) const BOOST_NOEXCEPT {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool operator==(const backtrace_holder& /*rhs*/) const BOOST_NOEXCEPT {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_NOOP_HPP
|
||||
@@ -1,130 +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_BACKTRACE_HOLDER_WIN_DBGHELP_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WIN_DBGHELP_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <windows.h>
|
||||
#include "DbgHelp.h"
|
||||
#include <WinBase.h>
|
||||
|
||||
#include <boost/detail/winapi/get_current_process.hpp>
|
||||
#include <boost/detail/winapi/sym_from_addr.hpp>
|
||||
|
||||
#if !defined(BOOST_ALL_NO_LIB)
|
||||
# define BOOST_LIB_NAME Dbghelp
|
||||
# ifdef BOOST_STACKTRACE_DYN_LINK
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
# include <boost/config/auto_link.hpp>
|
||||
#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 const void* get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return buffer[frame];
|
||||
}
|
||||
|
||||
inline std::string get_source_file(std::size_t /*frame*/) const {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
inline std::size_t get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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<boost::detail::winapi::ULONGLONG_>(buffer[frame]), 0, &s.symbol
|
||||
);
|
||||
if (sym_res) {
|
||||
res = s.symbol.Name;
|
||||
} else {
|
||||
res = "?? at ";
|
||||
res += to_hex_array(buffer[frame]).data();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return frames_count < rhs.frames_count;
|
||||
} else if (this == &rhs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::lexicographical_compare(
|
||||
buffer, buffer + frames_count,
|
||||
rhs.buffer, rhs.buffer + rhs.frames_count
|
||||
);
|
||||
}
|
||||
|
||||
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return false;
|
||||
} else if (this == &rhs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::equal(
|
||||
buffer, buffer + frames_count,
|
||||
rhs.buffer
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WIN_DBGHELP_HPP
|
||||
@@ -1,250 +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_BACKTRACE_HOLDER_WINDOWS_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WINDOWS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <windows.h>
|
||||
#include "Dbgeng.h"
|
||||
|
||||
#include <boost/detail/winapi/get_current_process.hpp>
|
||||
|
||||
#pragma comment(lib, "ole32.lib")
|
||||
#pragma comment(lib, "Dbgeng.lib")
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
template <class T>
|
||||
class com_holder: boost::noncopyable {
|
||||
T* holder_;
|
||||
|
||||
public:
|
||||
com_holder() BOOST_NOEXCEPT
|
||||
: holder_(0)
|
||||
{}
|
||||
|
||||
T* operator->() const BOOST_NOEXCEPT {
|
||||
return holder_;
|
||||
}
|
||||
|
||||
void** to_void_ptr_ptr() BOOST_NOEXCEPT {
|
||||
return reinterpret_cast<void**>(&holder_);
|
||||
}
|
||||
|
||||
bool is_inited() const BOOST_NOEXCEPT {
|
||||
return !!holder_;
|
||||
}
|
||||
|
||||
void reset() const BOOST_NOEXCEPT {
|
||||
if (holder_) {
|
||||
holder_->Release();
|
||||
}
|
||||
}
|
||||
|
||||
~com_holder() BOOST_NOEXCEPT {
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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 const void* get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return buffer[frame];
|
||||
}
|
||||
|
||||
inline std::string get_source_file(std::size_t frame) const {
|
||||
std::string result;
|
||||
if (frame >= frames_count) {
|
||||
return result;
|
||||
}
|
||||
|
||||
com_holder<IDebugSymbols> idebug_;
|
||||
if (!try_init_com(idebug_)) {
|
||||
return result;
|
||||
}
|
||||
const ULONG64 offset = reinterpret_cast<ULONG64>(buffer[frame]);
|
||||
|
||||
char name[256];
|
||||
name[0] = 0;
|
||||
ULONG size = 0;
|
||||
bool res = (S_OK == idebug_->GetLineByOffset(
|
||||
offset,
|
||||
0,
|
||||
name,
|
||||
sizeof(name),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
|
||||
if (!res && size != 0) {
|
||||
result.resize(size);
|
||||
res = (S_OK == idebug_->GetLineByOffset(
|
||||
offset,
|
||||
0,
|
||||
&result[0],
|
||||
static_cast<ULONG>(result.size()),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
} else if (res) {
|
||||
result = name;
|
||||
}
|
||||
|
||||
|
||||
if (!res) {
|
||||
result.clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::size_t get_source_line(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
ULONG line_num = 0;
|
||||
|
||||
com_holder<IDebugSymbols> idebug_;
|
||||
if (!try_init_com(idebug_)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const bool is_ok = (S_OK == idebug_->GetLineByOffset(
|
||||
reinterpret_cast<ULONG64>(buffer[frame]),
|
||||
&line_num,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
));
|
||||
|
||||
return (is_ok ? line_num : 0);
|
||||
}
|
||||
|
||||
static bool try_init_com(com_holder<IDebugSymbols>& idebug_) BOOST_NOEXCEPT {
|
||||
if (idebug_.is_inited()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
|
||||
com_holder<IDebugClient> iclient;
|
||||
DebugCreate(__uuidof(IDebugClient), iclient.to_void_ptr_ptr());
|
||||
|
||||
com_holder<IDebugControl> icontrol;
|
||||
iclient->QueryInterface(__uuidof(IDebugControl), icontrol.to_void_ptr_ptr());
|
||||
|
||||
const bool res1 = (S_OK == iclient->AttachProcess(
|
||||
0,
|
||||
GetCurrentProcessId(),
|
||||
DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND)
|
||||
);
|
||||
if (!res1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool res2 = (S_OK == icontrol->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE));
|
||||
if (!res2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool res = (S_OK == iclient->QueryInterface(__uuidof(IDebugSymbols), idebug_.to_void_ptr_ptr()));
|
||||
if (!res) {
|
||||
idebug_.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::string get_frame(std::size_t frame) const {
|
||||
std::string result;
|
||||
if (frame >= frames_count) {
|
||||
return result;
|
||||
}
|
||||
|
||||
com_holder<IDebugSymbols> idebug_;
|
||||
if (!try_init_com(idebug_)) {
|
||||
return result;
|
||||
}
|
||||
const ULONG64 offset = reinterpret_cast<ULONG64>(buffer[frame]);
|
||||
|
||||
char name[256];
|
||||
name[0] = '\0';
|
||||
ULONG size = 0;
|
||||
bool res = (S_OK == idebug_->GetNameByOffset(
|
||||
offset,
|
||||
name,
|
||||
sizeof(name),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
|
||||
if (!res && size != 0) {
|
||||
result.resize(size);
|
||||
res = (S_OK == idebug_->GetNameByOffset(
|
||||
offset,
|
||||
&result[0],
|
||||
static_cast<ULONG>(result.size()),
|
||||
&size,
|
||||
0
|
||||
));
|
||||
} else if (res) {
|
||||
result = name;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
result.clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return frames_count < rhs.frames_count;
|
||||
} else if (this == &rhs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::lexicographical_compare(
|
||||
buffer, buffer + frames_count,
|
||||
rhs.buffer, rhs.buffer + rhs.frames_count
|
||||
);
|
||||
}
|
||||
|
||||
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
|
||||
if (frames_count != rhs.frames_count) {
|
||||
return false;
|
||||
} else if (this == &rhs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return std::equal(
|
||||
buffer, buffer + frames_count,
|
||||
rhs.buffer
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WINDOWS_HPP
|
||||
@@ -1,41 +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_STACKTRACE_HELPERS_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_STACKTRACE_HELPERS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
struct backtrace_holder;
|
||||
|
||||
template <class T>
|
||||
inline boost::stacktrace::detail::backtrace_holder& to_bt(T& data) BOOST_NOEXCEPT {
|
||||
return *reinterpret_cast<boost::stacktrace::detail::backtrace_holder*>(&data);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const boost::stacktrace::detail::backtrace_holder& to_bt(const T& data) BOOST_NOEXCEPT {
|
||||
return *reinterpret_cast<const boost::stacktrace::detail::backtrace_holder*>(&data);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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;
|
||||
}
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_HELPERS_HPP
|
||||
@@ -1,80 +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_STACKTRACE_IPP
|
||||
#define BOOST_STACKTRACE_DETAIL_STACKTRACE_IPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
|
||||
#if defined(BOOST_STACKTRACE_USE_NOOP)
|
||||
# include <boost/stacktrace/detail/stacktrace_noop.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_WINDBG)
|
||||
# include <boost/stacktrace/detail/stacktrace_windows.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_LIBUNWIND)
|
||||
# include <boost/stacktrace/detail/stacktrace_libunwind.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_BACKTRACE)
|
||||
# include <boost/stacktrace/detail/stacktrace_linux.hpp>
|
||||
#else
|
||||
# error No suitable backtrace backend found
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
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
|
||||
: impl_(bt.impl_)
|
||||
, hash_code_(bt.hash_code_)
|
||||
{}
|
||||
|
||||
stacktrace& stacktrace::operator=(const stacktrace& bt) BOOST_NOEXCEPT {
|
||||
impl_ = bt.impl_;
|
||||
hash_code_ = bt.hash_code_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
stacktrace::~stacktrace() BOOST_NOEXCEPT {}
|
||||
|
||||
std::size_t stacktrace::size() const BOOST_NOEXCEPT {
|
||||
return impl_.size();
|
||||
}
|
||||
|
||||
std::string stacktrace::get_name(std::size_t frame) const {
|
||||
return impl_.get_frame(frame);
|
||||
}
|
||||
|
||||
const void* stacktrace::get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return impl_.get_address(frame);
|
||||
}
|
||||
|
||||
std::string stacktrace::get_source_file(std::size_t frame) const {
|
||||
return impl_.get_source_file(frame);
|
||||
}
|
||||
|
||||
std::size_t stacktrace::get_source_line(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return impl_.get_source_line(frame);
|
||||
}
|
||||
|
||||
bool stacktrace::operator< (const stacktrace& rhs) const BOOST_NOEXCEPT {
|
||||
return hash_code_ < rhs.hash_code_ || (hash_code_ == rhs.hash_code_ && impl_ < rhs.impl_);
|
||||
}
|
||||
|
||||
bool stacktrace::operator==(const stacktrace& rhs) const BOOST_NOEXCEPT {
|
||||
return hash_code_ == rhs.hash_code_ && impl_ == rhs.impl_;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_IPP
|
||||
@@ -1,68 +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_STACKTRACE_LIBUNWIND_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_STACKTRACE_LIBUNWIND_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <boost/stacktrace/detail/backtrace_holder_libunwind.hpp>
|
||||
#include <boost/stacktrace/detail/helpers.hpp>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
namespace boost { namespace stacktrace {
|
||||
|
||||
stacktrace::stacktrace() BOOST_NOEXCEPT
|
||||
: hash_code_(0)
|
||||
{
|
||||
boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_);
|
||||
bt.frames_count = 0;
|
||||
|
||||
unw_context_t uc;
|
||||
if (unw_getcontext(&uc) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
{ // Counting frames_count
|
||||
unw_cursor_t cursor;
|
||||
if (unw_init_local(&cursor, &uc) != 0) {
|
||||
return;
|
||||
}
|
||||
while (unw_step(&cursor) > 0) {
|
||||
++ bt.frames_count;
|
||||
}
|
||||
}
|
||||
|
||||
unw_cursor_t cursor;
|
||||
if (unw_init_local(&cursor, &uc) != 0) {
|
||||
bt.frames_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_TRY {
|
||||
bt.frames = boost::make_shared<boost::stacktrace::detail::bt_pair[]>(bt.frames_count);
|
||||
std::size_t i = 0;
|
||||
while (unw_step(&cursor) > 0){
|
||||
bt.frames[i].name = boost::stacktrace::detail::backtrace_holder::get_frame_impl(cursor);
|
||||
unw_proc_info_t inf;
|
||||
const int res = unw_get_proc_info(&cursor, &inf);
|
||||
(void)res;
|
||||
bt.frames[i].addr = reinterpret_cast<void*>(inf.start_ip ? inf.start_ip : inf.gp);
|
||||
boost::hash_combine(hash_code_, bt.frames[i].name);
|
||||
++ i;
|
||||
}
|
||||
} BOOST_CATCH(...) {}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
}} // namespace boost::stacktrace
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_LIBUNWIND_HPP
|
||||
@@ -1,37 +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_STACKTRACE_LINUX_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_STACKTRACE_LINUX_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <boost/stacktrace/detail/backtrace_holder_linux.hpp>
|
||||
#include <boost/stacktrace/detail/helpers.hpp>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
namespace boost { namespace stacktrace {
|
||||
|
||||
stacktrace::stacktrace() BOOST_NOEXCEPT
|
||||
: hash_code_(0)
|
||||
{
|
||||
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 - 1] == 0) {
|
||||
-- bt.frames_count;
|
||||
}
|
||||
|
||||
hash_code_ = boost::hash_range(bt.buffer, bt.buffer + bt.frames_count);
|
||||
}
|
||||
|
||||
}} // namespace boost::stacktrace
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_LINUX_HPP
|
||||
@@ -1,29 +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_STACKTRACE_NOOP_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_STACKTRACE_NOOP_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <boost/stacktrace/detail/backtrace_holder_noop.hpp>
|
||||
#include <boost/stacktrace/detail/helpers.hpp>
|
||||
|
||||
namespace boost { namespace stacktrace {
|
||||
|
||||
stacktrace::stacktrace() BOOST_NOEXCEPT
|
||||
: hash_code_(0)
|
||||
{
|
||||
boost::stacktrace::detail::construct_bt_and_return(impl_);
|
||||
}
|
||||
|
||||
}} // namespace boost::stacktrace
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_NOOP_HPP
|
||||
@@ -1,34 +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_STACKTRACE_WINDOWS_HPP
|
||||
#define BOOST_STACKTRACE_DETAIL_STACKTRACE_WINDOWS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <boost/stacktrace/detail/backtrace_holder_windows.hpp>
|
||||
#include <boost/stacktrace/detail/helpers.hpp>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
namespace boost { namespace stacktrace {
|
||||
|
||||
stacktrace::stacktrace() BOOST_NOEXCEPT
|
||||
: hash_code_(0)
|
||||
{
|
||||
boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_);
|
||||
boost::detail::winapi::ULONG_ hc = 0;
|
||||
bt.frames_count = CaptureStackBackTrace(0, boost::stacktrace::detail::backtrace_holder::max_size, bt.buffer, &hc);
|
||||
boost::hash_combine(hash_code_, hc);
|
||||
}
|
||||
|
||||
}} // namespace boost::stacktrace
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_WINDOWS_HPP
|
||||
@@ -7,4 +7,4 @@
|
||||
#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
|
||||
#define BOOST_STACKTRACE_USE_BACKTRACE
|
||||
#define BOOST_STACKTRACE_LINK
|
||||
#include "stacktrace_src.ipp"
|
||||
#include <boost/stacktrace/detail/backend.ipp>
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
|
||||
#define BOOST_STACKTRACE_USE_LIBUNWIND
|
||||
#define BOOST_STACKTRACE_LINK
|
||||
#include "stacktrace_src.ipp"
|
||||
#include <boost/stacktrace/detail/backend.ipp>
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
|
||||
#define BOOST_STACKTRACE_USE_NOOP
|
||||
#define BOOST_STACKTRACE_LINK
|
||||
#include "stacktrace_src.ipp"
|
||||
#include <boost/stacktrace/detail/backend.ipp>
|
||||
|
||||
@@ -1,99 +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_SRC_STACKTRACE_IPP
|
||||
#define BOOST_STACKTRACE_SRC_STACKTRACE_IPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
|
||||
#if defined(BOOST_STACKTRACE_USE_HEADER)
|
||||
# include BOOST_STACKTRACE_USE_HEADER
|
||||
#elif defined(BOOST_STACKTRACE_USE_NOOP)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_noop.hpp>
|
||||
# include <boost/stacktrace/detail/stacktrace_noop.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_WINDBG)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_windows.hpp>
|
||||
# include <boost/stacktrace/detail/stacktrace_windows.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_LIBUNWIND)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_libunwind.hpp>
|
||||
# include <boost/stacktrace/detail/stacktrace_libunwind.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_BACKTRACE)
|
||||
# include <boost/stacktrace/detail/backtrace_holder_linux.hpp>
|
||||
# include <boost/stacktrace/detail/stacktrace_linux.hpp>
|
||||
#else
|
||||
# error No suitable backtrace backend found
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/helpers.hpp>
|
||||
|
||||
|
||||
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
|
||||
: hash_code_(bt.hash_code_)
|
||||
{
|
||||
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_);
|
||||
hash_code_ = bt.hash_code_;
|
||||
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::get_name(std::size_t frame) const {
|
||||
return boost::stacktrace::detail::to_bt(impl_).get_frame(frame);
|
||||
}
|
||||
|
||||
const void* stacktrace::get_address(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return boost::stacktrace::detail::to_bt(impl_).get_address(frame);
|
||||
}
|
||||
|
||||
std::string stacktrace::get_source_file(std::size_t frame) const {
|
||||
return boost::stacktrace::detail::to_bt(impl_).get_source_file(frame);
|
||||
}
|
||||
|
||||
std::size_t stacktrace::get_source_line(std::size_t frame) const BOOST_NOEXCEPT {
|
||||
return boost::stacktrace::detail::to_bt(impl_).get_source_line(frame);
|
||||
}
|
||||
|
||||
bool stacktrace::operator< (const stacktrace& rhs) const BOOST_NOEXCEPT {
|
||||
return hash_code_ < rhs.hash_code_
|
||||
|| (hash_code_ == rhs.hash_code_ && boost::stacktrace::detail::to_bt(impl_) < boost::stacktrace::detail::to_bt(rhs.impl_))
|
||||
;
|
||||
}
|
||||
|
||||
bool stacktrace::operator==(const stacktrace& rhs) const BOOST_NOEXCEPT {
|
||||
return hash_code_ == rhs.hash_code_
|
||||
&& boost::stacktrace::detail::to_bt(impl_) == boost::stacktrace::detail::to_bt(rhs.impl_)
|
||||
;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_STACKTRACE_SRC_STACKTRACE_IPP
|
||||
@@ -7,4 +7,4 @@
|
||||
#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
|
||||
#define BOOST_STACKTRACE_USE_WINDBG
|
||||
#define BOOST_STACKTRACE_LINK
|
||||
#include "stacktrace_src.ipp"
|
||||
#include <boost/stacktrace/detail/backend.ipp>
|
||||
|
||||
Reference in New Issue
Block a user