Skip to content

Commit e1c1a49

Browse files
committed
Minor improvements and refactoring
1 parent 73206b9 commit e1c1a49

16 files changed

Lines changed: 401 additions & 249 deletions

include/boost/stacktrace.hpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <string>
1919

2020
/// @cond
21+
22+
// Link or header only
2123
#if !defined(BOOST_STACKTRACE_LINK) && defined(BOOST_STACKTRACE_DYN_LINK)
2224
# define BOOST_STACKTRACE_LINK
2325
#endif
@@ -26,6 +28,28 @@
2628
# define BOOST_STACKTRACE_DYN_LINK
2729
#endif
2830

31+
// Backend autodetection
32+
#if !defined(BOOST_STACKTRACE_USE_NOOP) && !defined(BOOST_STACKTRACE_USE_WINDBG) && !defined(BOOST_STACKTRACE_USE_LIBUNWIND) \
33+
&& !defined(BOOST_STACKTRACE_USE_BACKTRACE) &&!defined(BOOST_STACKTRACE_USE_HEADER)
34+
35+
#if defined(__has_include) && (!defined(__GNUC__) || __GNUC__ > 4 || BOOST_CLANG)
36+
# if __has_include(<libunwind.h>)
37+
# define BOOST_STACKTRACE_USE_LIBUNWIND
38+
# elif __has_include(<execinfo.h>)
39+
# define BOOST_STACKTRACE_USE_BACKTRACE
40+
# elif __has_include("DbgHelp.h")
41+
# define BOOST_STACKTRACE_USE_WINDBG
42+
# endif
43+
#else
44+
# if defined(BOOST_WINDOWS)
45+
# define BOOST_STACKTRACE_USE_WINDBG
46+
# else
47+
# define BOOST_STACKTRACE_USE_BACKTRACE
48+
# endif
49+
#endif
50+
51+
#endif
52+
2953
#ifdef BOOST_STACKTRACE_LINK
3054
# if defined(BOOST_STACKTRACE_DYN_LINK)
3155
# ifdef BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
@@ -38,14 +62,29 @@
3862
# endif
3963
#else
4064
# define BOOST_STACKTRACE_FUNCTION inline
65+
# if defined(BOOST_STACKTRACE_USE_NOOP)
66+
# include <boost/stacktrace/detail/backtrace_holder_noop.hpp>
67+
# elif defined(BOOST_STACKTRACE_USE_WINDBG)
68+
# include <boost/stacktrace/detail/backtrace_holder_windows.hpp>
69+
# elif defined(BOOST_STACKTRACE_USE_LIBUNWIND)
70+
# include <boost/stacktrace/detail/backtrace_holder_libunwind.hpp>
71+
# elif defined(BOOST_STACKTRACE_USE_BACKTRACE)
72+
# include <boost/stacktrace/detail/backtrace_holder_linux.hpp>
73+
# else
74+
# error No suitable backtrace backend found
75+
# endif
4176
#endif
4277
/// @endcond
4378

4479
namespace boost { namespace stacktrace {
4580

4681
class stacktrace {
82+
#ifdef BOOST_STACKTRACE_LINK
4783
BOOST_STATIC_CONSTEXPR std::size_t max_implementation_size = sizeof(void*) * 110u;
4884
boost::aligned_storage<max_implementation_size>::type impl_;
85+
#else
86+
boost::stacktrace::detail::backtrace_holder impl_;
87+
#endif
4988

5089
public:
5190
/// @brief Stores the current function call sequence inside the class.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright Antony Polukhin, 2016.
2+
//
3+
// Distributed under the Boost Software License, Version 1.0. (See
4+
// accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
7+
#ifndef BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LIBUNWIND_HPP
8+
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LIBUNWIND_HPP
9+
10+
#include <boost/config.hpp>
11+
#ifdef BOOST_HAS_PRAGMA_ONCE
12+
# pragma once
13+
#endif
14+
15+
#include <boost/core/demangle.hpp>
16+
#include <cstring>
17+
#include <boost/core/no_exceptions_support.hpp>
18+
#include <boost/make_shared.hpp>
19+
20+
#define UNW_LOCAL_ONLY
21+
#include <libunwind.h>
22+
23+
namespace boost { namespace stacktrace { namespace detail {
24+
25+
struct backtrace_holder {
26+
std::size_t frames_count;
27+
boost::shared_ptr<std::string[]> frames;
28+
29+
BOOST_FORCEINLINE backtrace_holder() BOOST_NOEXCEPT
30+
: frames_count(0)
31+
{}
32+
33+
inline std::size_t size() const BOOST_NOEXCEPT {
34+
return frames_count;
35+
}
36+
37+
inline std::string get_frame(std::size_t frame) const {
38+
if (frame < frames_count) {
39+
return frames[frame];
40+
} else {
41+
return std::string();
42+
}
43+
}
44+
45+
static inline std::string get_frame_impl(unw_cursor_t& cursor) {
46+
std::string res;
47+
unw_word_t offp;
48+
char data[256];
49+
const int ret = unw_get_proc_name (&cursor, data, sizeof(data) / sizeof(char), &offp);
50+
51+
if (ret == -UNW_ENOMEM) {
52+
res.resize(sizeof(data) * 2);
53+
do {
54+
const int ret2 = unw_get_proc_name(&cursor, &res[0], res.size(), &offp);
55+
if (ret2 == -UNW_ENOMEM) {
56+
res.resize(res.size() * 2);
57+
} else if (ret2 == 0) {
58+
break;
59+
} else {
60+
res = data;
61+
return res;
62+
}
63+
} while(1);
64+
} else if (ret == 0) {
65+
res = data;
66+
} else {
67+
return res;
68+
}
69+
70+
boost::core::scoped_demangled_name demangled(res.data());
71+
if (demangled.get()) {
72+
res = demangled.get();
73+
} else {
74+
res.resize( std::strlen(res.data()) ); // Note: here res is \0 terminated, but size() not equal to strlen
75+
}
76+
77+
return res;
78+
}
79+
};
80+
81+
}}} // namespace boost::stacktrace::detail
82+
83+
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LIBUNWIND_HPP
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright Antony Polukhin, 2016.
2+
//
3+
// Distributed under the Boost Software License, Version 1.0. (See
4+
// accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
7+
#ifndef BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LINUX_HPP
8+
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LINUX_HPP
9+
10+
#include <boost/config.hpp>
11+
#ifdef BOOST_HAS_PRAGMA_ONCE
12+
# pragma once
13+
#endif
14+
15+
#include <boost/core/demangle.hpp>
16+
17+
#include <dlfcn.h>
18+
#include <execinfo.h>
19+
20+
namespace boost { namespace stacktrace { namespace detail {
21+
22+
struct backtrace_holder {
23+
std::size_t frames_count;
24+
BOOST_STATIC_CONSTEXPR std::size_t max_size = 100u;
25+
void* buffer[max_size];
26+
27+
inline std::size_t size() const BOOST_NOEXCEPT {
28+
return frames_count;
29+
}
30+
31+
inline std::string get_frame(std::size_t frame) const {
32+
std::string res;
33+
if (frame >= frames_count) {
34+
return res;
35+
}
36+
37+
Dl_info dli;
38+
if (!dladdr(buffer[frame], &dli)) {
39+
return res;
40+
}
41+
42+
if (dli.dli_sname) {
43+
boost::core::scoped_demangled_name demangled(dli.dli_sname);
44+
if (demangled.get()) {
45+
res = demangled.get();
46+
} else {
47+
res = dli.dli_sname;
48+
}
49+
}
50+
51+
return res;
52+
}
53+
};
54+
55+
}}} // namespace boost::stacktrace::detail
56+
57+
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_LINUX_HPP
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright Antony Polukhin, 2016.
2+
//
3+
// Distributed under the Boost Software License, Version 1.0. (See
4+
// accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
7+
#ifndef BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_NOOP_HPP
8+
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_NOOP_HPP
9+
10+
#include <boost/config.hpp>
11+
#ifdef BOOST_HAS_PRAGMA_ONCE
12+
# pragma once
13+
#endif
14+
15+
16+
namespace boost { namespace stacktrace { namespace detail {
17+
18+
struct backtrace_holder {
19+
inline std::size_t size() const BOOST_NOEXCEPT {
20+
return 0u;
21+
}
22+
23+
inline std::string get_frame(std::size_t /*frame*/) const {
24+
return std::string();
25+
}
26+
};
27+
28+
}}} // namespace boost::stacktrace::detail
29+
30+
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_NOOP_HPP
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright Antony Polukhin, 2016.
2+
//
3+
// Distributed under the Boost Software License, Version 1.0. (See
4+
// accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
7+
#ifndef BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WINDOWS_HPP
8+
#define BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WINDOWS_HPP
9+
10+
#include <boost/config.hpp>
11+
#ifdef BOOST_HAS_PRAGMA_ONCE
12+
# pragma once
13+
#endif
14+
15+
#include <windows.h>
16+
#include "DbgHelp.h"
17+
#include <WinBase.h>
18+
19+
#include <boost/detail/winapi/get_current_process.hpp>
20+
#include <boost/detail/winapi/sym_from_addr.hpp>
21+
22+
#if !defined(BOOST_ALL_NO_LIB)
23+
# define BOOST_LIB_NAME Dbghelp
24+
# ifdef BOOST_STACKTRACE_DYN_LINK
25+
# define BOOST_DYN_LINK
26+
# endif
27+
# include <boost/config/auto_link.hpp>
28+
#endif
29+
30+
namespace boost { namespace stacktrace { namespace detail {
31+
32+
struct symbol_info_with_stack {
33+
BOOST_STATIC_CONSTEXPR std::size_t max_name_length = MAX_SYM_NAME * sizeof(char);
34+
boost::detail::winapi::SYMBOL_INFO_ symbol;
35+
char name_part[max_name_length];
36+
};
37+
38+
struct symbol_initialization_structure {
39+
boost::detail::winapi::HANDLE_ process;
40+
41+
inline symbol_initialization_structure() BOOST_NOEXCEPT
42+
: process(boost::detail::winapi::GetCurrentProcess())
43+
{
44+
SymInitialize(process, 0, true);
45+
}
46+
47+
inline ~symbol_initialization_structure() BOOST_NOEXCEPT {
48+
SymCleanup(process);
49+
}
50+
};
51+
52+
struct backtrace_holder {
53+
BOOST_STATIC_CONSTEXPR std::size_t max_size = 100u;
54+
55+
std::size_t frames_count;
56+
void* buffer[max_size];
57+
58+
inline std::size_t size() const BOOST_NOEXCEPT {
59+
return frames_count;
60+
}
61+
62+
inline std::string get_frame(std::size_t frame) const {
63+
std::string res;
64+
65+
static symbol_initialization_structure symproc;
66+
67+
if (frame >= frames_count) {
68+
return res;
69+
}
70+
71+
symbol_info_with_stack s;
72+
s.symbol.MaxNameLen = symbol_info_with_stack::max_name_length;
73+
s.symbol.SizeOfStruct = sizeof(boost::detail::winapi::SYMBOL_INFO_);
74+
const bool sym_res = !!boost::detail::winapi::SymFromAddr(
75+
symproc.process, reinterpret_cast<boost::detail::winapi::ULONGLONG_>(buffer[frame]), 0, &s.symbol
76+
);
77+
if (sym_res) {
78+
res = s.symbol.Name;
79+
}
80+
return res;
81+
}
82+
};
83+
84+
}}} // namespace boost::stacktrace::detail
85+
86+
#endif // BOOST_STACKTRACE_DETAIL_BACKTRACE_HOLDER_WINDOWS_HPP

include/boost/stacktrace/detail/stacktrace_helpers.hpp renamed to include/boost/stacktrace/detail/helpers.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ inline const boost::stacktrace::detail::backtrace_holder& to_bt(const T& data) B
2929
return *reinterpret_cast<const boost::stacktrace::detail::backtrace_holder*>(&data);
3030
}
3131

32+
template <class T>
33+
inline boost::stacktrace::detail::backtrace_holder& construct_bt_and_return(T& data) BOOST_NOEXCEPT {
34+
new (&data) boost::stacktrace::detail::backtrace_holder();
35+
return boost::stacktrace::detail::to_bt(data);
36+
}
37+
38+
inline boost::stacktrace::detail::backtrace_holder& construct_bt_and_return(backtrace_holder& data) BOOST_NOEXCEPT {
39+
return data;
40+
}
3241

3342
/*
3443
BOOST_STATIC_CONSTEXPR char to_hex_array[] = "0123456789ABCDEF";

0 commit comments

Comments
 (0)