Skip to content

Commit 960f9d0

Browse files
committed
Use native_frame_ptr_t instead of void* and const void*
1 parent 21c2484 commit 960f9d0

10 files changed

Lines changed: 85 additions & 54 deletions

File tree

example/terminate_handler.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,10 @@ int test_inplace() {
220220
}
221221

222222
#if !defined(BOOST_MSVC) && !defined(BOOST_STACKTRACE_USE_WINDBG)
223-
// This is very dependent on compiler and link flags. No sane way to make it work, because
224-
// BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
225-
if (ss1 && ss1[0].name() != ss2[0].name()) {
223+
// This is very dependent on compiler and link flags. No sane way to make it work, because:
224+
// * BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
225+
// * BOOST_FORCEINLINE could be ignored by GCC depending on the std::vector default constructor length.
226+
if (ss1.size() > 1 && ss1[1].name() != ss2[1].name()) {
226227
std::cerr << "Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
227228
return 52;
228229
}
@@ -241,9 +242,10 @@ int test_inplace() {
241242
}
242243

243244
#if !defined(BOOST_MSVC) && !defined(BOOST_STACKTRACE_USE_WINDBG)
244-
// This is very dependent on compiler and link flags. No sane way to make it work, because
245-
// BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
246-
if (ss1 && ss1[0].name() != ss2[0].name()) {
245+
// This is very dependent on compiler and link flags. No sane way to make it work, because:
246+
// * BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
247+
// * BOOST_FORCEINLINE could be ignored by GCC depending on the std::vector default constructor length.
248+
if (ss1.size() > 1 && ss1[1].name() != ss2[1].name()) {
247249
std::cerr << "Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
248250
return 54;
249251
}

include/boost/stacktrace/detail/addr2line_impls.hpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,26 @@
1515
#include <boost/stacktrace/detail/to_hex_array.hpp>
1616
#include <boost/core/demangle.hpp>
1717
#include <boost/lexical_cast.hpp>
18-
1918
#include <cstdio>
2019

2120
#include <sys/types.h>
2221
#include <sys/wait.h>
2322
#include <signal.h>
2423

24+
2525
namespace boost { namespace stacktrace { namespace detail {
2626

27+
28+
#if defined(BOOST_STACKTRACE_ADDR2LINE_LOCATION) && !defined(BOOST_NO_CXX11_CONSTEXPR)
29+
30+
constexpr bool is_abs_path(const char* path) BOOST_NOEXCEPT {
31+
return *path != '\0' && (
32+
*path == ':' || *path == '/' || is_abs_path(path + 1)
33+
);
34+
}
35+
36+
#endif
37+
2738
class addr2line_pipe {
2839
::FILE* p;
2940
::pid_t pid;
@@ -35,8 +46,15 @@ class addr2line_pipe {
3546
{
3647
int pdes[2];
3748
#ifdef BOOST_STACKTRACE_ADDR2LINE_LOCATION
38-
// TODO: static_assert that BOOST_STACKTRACE_ADDR2LINE_LOCATION is an absolute path!
3949
char prog_name[] = BOOST_STACKTRACE_ADDR2LINE_LOCATION ;
50+
51+
#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_STATIC_ASSERT)
52+
static_assert(
53+
boost::stacktrace::detail::is_abs_path( BOOST_STACKTRACE_ADDR2LINE_LOCATION ),
54+
"BOOST_STACKTRACE_ADDR2LINE_LOCATION must be an absolute path"
55+
);
56+
#endif
57+
4058
#else
4159
char prog_name[] = "/usr/bin/addr2line";
4260
#endif

include/boost/stacktrace/detail/frame_msvc.ipp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@
5151

5252
namespace boost { namespace stacktrace { namespace detail {
5353

54-
std::size_t this_thread_frames::collect(void** memory, std::size_t size, std::size_t skip) BOOST_NOEXCEPT {
54+
std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT {
5555
return ::CaptureStackBackTrace(
5656
skip,
57-
static_cast<boost::detail::winapi::ULONG_>(size),
58-
memory,
57+
static_cast<boost::detail::winapi::ULONG_>(max_frames_count),
58+
out_frames,
5959
0
6060
);
6161
}

include/boost/stacktrace/detail/frame_noop.ipp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,22 @@ std::string to_string(const frame* /*frames*/, std::size_t /*count*/) {
2020
return std::string();
2121
}
2222

23-
std::size_t this_thread_frames::collect(void** /*memory*/, std::size_t /*size*/, std::size_t /*skip*/) BOOST_NOEXCEPT {
23+
std::size_t this_thread_frames::collect(native_frame_ptr_t* /*out_frames*/, std::size_t /*max_frames_count*/, std::size_t /*skip*/) BOOST_NOEXCEPT {
2424
return 0;
2525
}
2626

2727
#if defined(BOOST_WINDOWS)
28-
std::size_t dump(void* /*fd*/, void** /*memory*/, std::size_t /*size*/) BOOST_NOEXCEPT {
28+
std::size_t dump(void* /*fd*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT {
2929
return 0;
3030
}
3131
#else
32-
std::size_t dump(int /*fd*/, void** /*memory*/, std::size_t /*size*/) BOOST_NOEXCEPT {
32+
std::size_t dump(int /*fd*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT {
3333
return 0;
3434
}
3535
#endif
3636

3737

38-
std::size_t dump(const char* /*file*/, void** /*memory*/, std::size_t /*size*/) BOOST_NOEXCEPT {
38+
std::size_t dump(const char* /*file*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT {
3939
return 0;
4040
}
4141

include/boost/stacktrace/detail/frame_unwind.ipp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,18 @@ namespace boost { namespace stacktrace { namespace detail {
4040

4141
struct unwind_state {
4242
std::size_t frames_to_skip;
43-
void** current;
44-
void** end;
43+
native_frame_ptr_t* current;
44+
native_frame_ptr_t* end;
4545
};
4646

4747
inline _Unwind_Reason_Code unwind_callback(::_Unwind_Context* context, void* arg) {
48-
unwind_state* state = static_cast<unwind_state*>(arg);
48+
unwind_state* const state = static_cast<unwind_state*>(arg);
4949
if (state->frames_to_skip) {
5050
--state->frames_to_skip;
5151
return ::_Unwind_GetIP(context) ? ::_URC_NO_REASON : ::_URC_END_OF_STACK;
5252
}
5353

54-
*state->current = reinterpret_cast<void*>(
54+
*state->current = reinterpret_cast<native_frame_ptr_t>(
5555
::_Unwind_GetIP(context)
5656
);
5757

@@ -62,17 +62,17 @@ inline _Unwind_Reason_Code unwind_callback(::_Unwind_Context* context, void* arg
6262
return ::_URC_NO_REASON;
6363
}
6464

65-
std::size_t this_thread_frames::collect(void** memory, std::size_t size, std::size_t skip) BOOST_NOEXCEPT {
65+
std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT {
6666
std::size_t frames_count = 0;
67-
if (!size) {
67+
if (!max_frames_count) {
6868
return frames_count;
6969
}
7070

71-
boost::stacktrace::detail::unwind_state state = { skip + 1, memory, memory + size };
71+
boost::stacktrace::detail::unwind_state state = { skip + 1, out_frames, out_frames + max_frames_count };
7272
::_Unwind_Backtrace(&boost::stacktrace::detail::unwind_callback, &state);
73-
frames_count = state.current - memory;
73+
frames_count = state.current - out_frames;
7474

75-
if (frames_count && memory[frames_count - 1] == 0) {
75+
if (frames_count && out_frames[frames_count - 1] == 0) {
7676
-- frames_count;
7777
}
7878

@@ -82,7 +82,7 @@ std::size_t this_thread_frames::collect(void** memory, std::size_t size, std::si
8282
template <class Base>
8383
class to_string_impl_base: private Base {
8484
public:
85-
std::string operator()(const void* addr) {
85+
std::string operator()(boost::stacktrace::detail::native_frame_ptr_t addr) {
8686
Base::res.clear();
8787
Base::prepare_function_name(addr);
8888
if (!Base::res.empty()) {

include/boost/stacktrace/detail/safe_dump_posix.ipp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,25 @@
2020

2121
namespace boost { namespace stacktrace { namespace detail {
2222

23-
std::size_t dump(int fd, void** memory, std::size_t size) BOOST_NOEXCEPT {
23+
std::size_t dump(int fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
2424
// We do not retry, because this function must be typically called from signal handler so it's:
2525
// * to scary to continue in case of EINTR
2626
// * EAGAIN or EWOULDBLOCK may occur only in case of O_NONBLOCK is set for fd,
2727
// so it seems that user does not want to block
28-
if (::write(fd, memory, sizeof(void*) * size) == -1) {
28+
if (::write(fd, frames, sizeof(native_frame_ptr_t) * frames_count) == -1) {
2929
return 0;
3030
}
3131

32-
return size;
32+
return frames_count;
3333
}
3434

35-
std::size_t dump(const char* file, void** memory, std::size_t mem_size) BOOST_NOEXCEPT {
35+
std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
3636
const int fd = ::open(file, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR);
3737
if (fd == -1) {
3838
return 0;
3939
}
4040

41-
const std::size_t size = boost::stacktrace::detail::dump(fd, memory, mem_size);
41+
const std::size_t size = boost::stacktrace::detail::dump(fd, frames, frames_count);
4242
::close(fd);
4343
return size;
4444
}

include/boost/stacktrace/detail/safe_dump_win.ipp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@
2323

2424
namespace boost { namespace stacktrace { namespace detail {
2525

26-
std::size_t dump(void* fd, void** memory, std::size_t mem_size) BOOST_NOEXCEPT {
27-
if (!boost::detail::winapi::WriteFile(fd, memory, static_cast<boost::detail::winapi::DWORD_>(sizeof(void*) * mem_size), 0, 0)) {
26+
std::size_t dump(void* fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
27+
if (!boost::detail::winapi::WriteFile(fd, frames, static_cast<boost::detail::winapi::DWORD_>(sizeof(native_frame_ptr_t) * frames_count), 0, 0)) {
2828
return 0;
2929
}
3030

31-
return mem_size;
31+
return frames_count;
3232
}
3333

34-
std::size_t dump(const char* file, void** memory, std::size_t mem_size) BOOST_NOEXCEPT {
34+
std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
3535
void* const fd = boost::detail::winapi::CreateFileA(
3636
file,
3737
boost::detail::winapi::GENERIC_WRITE_,
@@ -46,7 +46,7 @@ std::size_t dump(const char* file, void** memory, std::size_t mem_size) BOOST_NO
4646
return 0;
4747
}
4848

49-
const std::size_t size = boost::stacktrace::detail::dump(fd, memory, mem_size);
49+
const std::size_t size = boost::stacktrace::detail::dump(fd, frames, frames_count);
5050
boost::detail::winapi::CloseHandle(fd);
5151
return size;
5252
}

include/boost/stacktrace/frame.hpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,33 @@ class frame;
4848
namespace detail {
4949
BOOST_STACKTRACE_FUNCTION std::string to_string(const frame* frames, std::size_t size);
5050

51+
typedef const void* native_frame_ptr_t; // TODO: change to `typedef void(*native_frame_ptr_t)();`
52+
5153
enum helper{ max_frames_dump = 128 };
52-
BOOST_STACKTRACE_FUNCTION std::size_t from_dump(const char* filename, void** frames);
53-
BOOST_STACKTRACE_FUNCTION std::size_t dump(const char* file, void** memory, std::size_t size) BOOST_NOEXCEPT;
54+
BOOST_STACKTRACE_FUNCTION std::size_t from_dump(const char* filename, native_frame_ptr_t* out_frames);
55+
BOOST_STACKTRACE_FUNCTION std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT;
5456
#if defined(BOOST_WINDOWS)
55-
BOOST_STACKTRACE_FUNCTION std::size_t dump(void* fd, void** memory, std::size_t size) BOOST_NOEXCEPT;
57+
BOOST_STACKTRACE_FUNCTION std::size_t dump(void* fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT;
5658
#else
5759
// POSIX
58-
BOOST_STACKTRACE_FUNCTION std::size_t dump(int fd, void** memory, std::size_t size) BOOST_NOEXCEPT;
60+
BOOST_STACKTRACE_FUNCTION std::size_t dump(int fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT;
5961
#endif
6062

6163

6264
struct this_thread_frames { // struct is required to avoid warning about usage of inline+BOOST_NOINLINE
63-
BOOST_NOINLINE BOOST_STACKTRACE_FUNCTION static std::size_t collect(void** memory, std::size_t size, std::size_t skip) BOOST_NOEXCEPT;
65+
BOOST_NOINLINE BOOST_STACKTRACE_FUNCTION static std::size_t collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT;
6466
};
6567

6668
} // namespace detail
6769

6870
/// Non-owning class that references the frame information stored inside the boost::stacktrace::stacktrace class.
6971
class frame {
72+
public:
73+
typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
74+
75+
private:
7076
/// @cond
71-
const void* addr_;
77+
native_frame_ptr_t addr_;
7278
/// @endcond
7379

7480
public:
@@ -108,7 +114,7 @@ class frame {
108114
///
109115
/// @b Async-Handler-Safety: Safe.
110116
/// @throws Nothing.
111-
BOOST_CONSTEXPR explicit frame(const void* addr) BOOST_NOEXCEPT
117+
BOOST_CONSTEXPR explicit frame(native_frame_ptr_t addr) BOOST_NOEXCEPT
112118
: addr_(addr)
113119
{}
114120

@@ -126,7 +132,7 @@ class frame {
126132
///
127133
/// @b Async-Handler-Safety: Safe.
128134
/// @throws Nothing.
129-
BOOST_CONSTEXPR const void* address() const BOOST_NOEXCEPT {
135+
BOOST_CONSTEXPR native_frame_ptr_t address() const BOOST_NOEXCEPT {
130136
return addr_;
131137
}
132138

include/boost/stacktrace/safe_dump_to.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,19 @@ namespace boost { namespace stacktrace {
2525
namespace detail {
2626
struct suppress_noinline_warnings {
2727
BOOST_NOINLINE static std::size_t safe_dump_to_impl(void* memory, std::size_t size, std::size_t skip) BOOST_NOEXCEPT {
28-
void** mem = static_cast<void**>(memory);
29-
const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(mem, size / sizeof(void*) - 1, skip + 1);
28+
typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
29+
30+
native_frame_ptr_t* mem = static_cast<native_frame_ptr_t*>(memory);
31+
const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(mem, size / sizeof(native_frame_ptr_t) - 1, skip + 1);
3032
mem[frames_count] = 0;
3133
return frames_count + 1;
3234
}
3335

3436
template <class T>
3537
BOOST_NOINLINE static std::size_t safe_dump_to_impl(T file, std::size_t skip, std::size_t max_depth) BOOST_NOEXCEPT {
36-
void* buffer[boost::stacktrace::detail::max_frames_dump + 1];
38+
typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
39+
40+
native_frame_ptr_t buffer[boost::stacktrace::detail::max_frames_dump + 1];
3741
if (max_depth > boost::stacktrace::detail::max_frames_dump) {
3842
max_depth = boost::stacktrace::detail::max_frames_dump;
3943
}

include/boost/stacktrace/stacktrace.hpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ namespace boost { namespace stacktrace {
3535
template <class Allocator>
3636
class basic_stacktrace {
3737
std::vector<frame, Allocator> impl_;
38+
typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
3839

3940
/// @cond
40-
void fill(void** begin, std::size_t size) {
41+
void fill(native_frame_ptr_t* begin, std::size_t size) {
4142
if (!size) {
4243
return;
4344
}
@@ -54,7 +55,7 @@ class basic_stacktrace {
5455
}
5556

5657
static std::size_t frames_count_from_buffer_size(std::size_t buffer_size) BOOST_NOEXCEPT {
57-
const std::size_t ret = (buffer_size > sizeof(void*) ? buffer_size / sizeof(void*) : 0);
58+
const std::size_t ret = (buffer_size > sizeof(native_frame_ptr_t) ? buffer_size / sizeof(native_frame_ptr_t) : 0);
5859
return (ret > 1024 ? 1024 : ret); // Dealing with suspiciously big sizes
5960
}
6061

@@ -66,7 +67,7 @@ class basic_stacktrace {
6667

6768
try {
6869
{ // Fast path without additional allocations
69-
void* buffer[buffer_size];
70+
native_frame_ptr_t buffer[buffer_size];
7071
const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(buffer, buffer_size, frames_to_skip + 1);
7172
if (buffer_size > frames_count || frames_count >= max_depth) {
7273
const std::size_t size = (max_depth < frames_count ? max_depth : frames_count);
@@ -76,8 +77,8 @@ class basic_stacktrace {
7677
}
7778

7879
// Failed to fit in `buffer_size`. Allocating memory:
79-
typedef typename Allocator::template rebind<void*>::other allocator_void_t;
80-
std::vector<void*, allocator_void_t> buf(buffer_size * 2, 0, impl_.get_allocator());
80+
typedef typename Allocator::template rebind<native_frame_ptr_t>::other allocator_void_t;
81+
std::vector<native_frame_ptr_t, allocator_void_t> buf(buffer_size * 2, 0, impl_.get_allocator());
8182
do {
8283
const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(buf.data(), buf.size(), frames_to_skip + 1);
8384
if (buf.size() > frames_count || frames_count >= max_depth) {
@@ -284,7 +285,7 @@ class basic_stacktrace {
284285
return ret;
285286
}
286287

287-
void* ptr = 0;
288+
native_frame_ptr_t ptr = 0;
288289
ret.impl_.reserve(frames_count);
289290
while (in.read(reinterpret_cast<Char*>(&ptr), sizeof(ptr))) {
290291
if (!ptr) {
@@ -302,13 +303,13 @@ class basic_stacktrace {
302303
/// @b Complexity: O(size) in worst case
303304
static basic_stacktrace from_dump(const void* begin, std::size_t size, const allocator_type& a = allocator_type()) {
304305
basic_stacktrace ret(0, 0, a);
305-
const void* const* first = static_cast<const void* const*>(begin);
306+
const native_frame_ptr_t* first = static_cast<const native_frame_ptr_t*>(begin);
306307
const std::size_t frames_count = frames_count_from_buffer_size(size);
307308
if (!frames_count) {
308309
return ret;
309310
}
310311

311-
const void* const* const last = first + frames_count;
312+
const native_frame_ptr_t* const last = first + frames_count;
312313
ret.impl_.reserve(frames_count);
313314
for (; first != last; ++first) {
314315
if (!*first) {

0 commit comments

Comments
 (0)