Removed libunwind backend and forced all the backends to return source info from void pointer

This commit is contained in:
Antony Polukhin
2016-11-25 21:50:43 +03:00
parent 58f49c9208
commit b35614a7a5
12 changed files with 32 additions and 270 deletions

View File

@@ -12,7 +12,6 @@ project
;
lib dl : : <link>shared ;
lib unwind : : <link>shared ;
lib Dbghelp ;
actions mp_simple_run_action
@@ -29,9 +28,6 @@ rule mp-run-simple ( sources + : args * : input-files * : requirements * : targe
alias $(target-name) : $(target-name).output ;
}
mp-run-simple has_libunwind.cpp : : : : libunwind ;
explicit libunwind ;
mp-run-simple has_backtrace.cpp : : : : backtrace ;
explicit backtrace ;
@@ -51,21 +47,6 @@ lib boost_stacktrace_noop
boost-install boost_stacktrace_noop ;
lib boost_stacktrace_libunwind
: # sources
../src/libunwind.cpp
: # requirements
<warnings>all
<library>unwind
<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
[ check-target-builds ../build//libunwind : : <build>no ]
: # default build
: # usage-requirements
#<link>shared:<define>BOOST_STACKTRACE_DYN_LINK=1
;
boost-install boost_stacktrace_libunwind ;
lib boost_stacktrace_backtrace
: # sources
../src/backtrace.cpp

View File

@@ -1,11 +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)
#define UNW_LOCAL_ONLY
#include <libunwind.h>
int main() {}

View File

@@ -29,9 +29,7 @@
&& !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>)
# if __has_include(<execinfo.h>)
# define BOOST_STACKTRACE_USE_BACKTRACE
# elif __has_include("Dbgeng.h")
# define BOOST_STACKTRACE_USE_WINDBG
@@ -70,10 +68,10 @@ class backend: boost::noncopyable {
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 static std::string get_name(const void* addr);
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 static std::string get_source_file(const void* addr);
BOOST_STACKTRACE_FUNCTION static std::size_t get_source_line(const void* addr);
BOOST_STACKTRACE_FUNCTION bool operator< (const backend& rhs) const BOOST_NOEXCEPT;
BOOST_STACKTRACE_FUNCTION bool operator==(const backend& rhs) const BOOST_NOEXCEPT;

View File

@@ -18,8 +18,6 @@
# 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

View File

@@ -1,180 +0,0 @@
// Copyright Antony Polukhin, 2016.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STACKTRACE_DETAIL_BACKEND_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_(static_cast<backtrace_holder*>(memory))
{
new (data_) backtrace_holder();
data_->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) {
++ data_->frames_count;
}
}
unw_cursor_t cursor;
if (unw_init_local(&cursor, &uc) != 0) {
data_->frames_count = 0;
return;
}
BOOST_TRY {
data_->frames = boost::make_shared<boost::stacktrace::detail::bt_pair[]>(data_->frames_count);
std::size_t i = 0;
while (unw_step(&cursor) > 0){
data_->frames[i].name = get_frame_impl(cursor);
unw_proc_info_t inf;
const int res = unw_get_proc_info(&cursor, &inf);
(void)res;
data_->frames[i].addr = reinterpret_cast<void*>(inf.start_ip ? inf.start_ip : inf.gp);
boost::hash_combine(hash_code, data_->frames[i].name);
++ i;
}
} BOOST_CATCH(...) {}
BOOST_CATCH_END
}
std::string backend::get_name(std::size_t frame) const {
if (frame < data_->frames_count) {
return data_->frames[frame].name;
} else {
return std::string();
}
}
const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT {
return data_->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 (data_->frames_count != rhs.data_->frames_count) {
return data_->frames_count < rhs.data_->frames_count;
} else if (data_->frames.get() == rhs.data_->frames.get()) {
return false;
}
return std::lexicographical_compare(
data_->frames.get(), data_->frames.get() + data_->frames_count,
rhs.data_->frames.get(), rhs.data_->frames.get() + rhs.data_->frames_count
);
}
bool backend::operator==(const backend& rhs) const BOOST_NOEXCEPT {
if (data_->frames_count != rhs.data_->frames_count) {
return false;
} else if (data_->frames.get() == rhs.data_->frames.get()) {
return true;
}
return std::equal(
data_->frames.get(), data_->frames.get() + data_->frames_count,
rhs.data_->frames.get()
);
}
}}} // namespace boost::stacktrace::detail
#include <boost/stacktrace/detail/backend_common.ipp>
#endif // BOOST_STACKTRACE_DETAIL_BACKEND_LIBUNWIND_HPP

View File

@@ -106,7 +106,7 @@ public:
}
};
static inline std::string addr2line(const char* flag, void* addr) {
static inline std::string addr2line(const char* flag, const void* addr) {
std::string res;
Dl_info dli;
@@ -179,17 +179,14 @@ backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_N
hash_code = boost::hash_range(data_->buffer, data_->buffer + data_->frames_count);
}
std::string backend::get_name(std::size_t frame) const {
std::string backend::get_name(const void* addr) {
std::string res;
if (frame >= data_->frames_count) {
return res;
}
Dl_info dli;
if (!!dladdr(data_->buffer[frame], &dli) && dli.dli_sname) {
if (!!dladdr(addr, &dli) && dli.dli_sname) {
res = try_demangle(dli.dli_sname);
} else {
res = addr2line("-fe", data_->buffer[frame]);
res = addr2line("-fe", addr);
res = res.substr(0, res.find_last_of('\n'));
res = try_demangle(res.c_str());
}
@@ -201,14 +198,14 @@ const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT {
return data_->buffer[frame];
}
std::string backend::get_source_file(std::size_t frame) const {
std::string res = addr2line("-e", data_->buffer[frame]);
std::string backend::get_source_file(const void* addr) {
std::string res = addr2line("-e", addr);
res = res.substr(0, res.find_last_of(':'));
return res;
}
std::size_t backend::get_source_line(std::size_t frame) const BOOST_NOEXCEPT {
std::string res = addr2line("-e", data_->buffer[frame]);
std::size_t backend::get_source_line(const void* addr) {
std::string res = addr2line("-e", addr);
const std::size_t last = res.find_last_of(':');
if (last == std::string::npos) {
return 0;

View File

@@ -21,7 +21,7 @@ backend::backend(void* /*memory*/, std::size_t /*size*/, std::size_t& hash_code)
hash_code = 0;
}
std::string backend::get_name(std::size_t /*frame*/) const {
std::string backend::get_name(const void* /*addr*/) {
return std::string();
}
@@ -29,11 +29,11 @@ const void* backend::get_address(std::size_t /*frame*/) const BOOST_NOEXCEPT {
return data_; // returns 0. Suppressing `private field 'data_' is not used` warning
}
std::string backend::get_source_file(std::size_t /*frame*/) const {
std::string backend::get_source_file(const void* /*addr*/) {
return std::string();
}
std::size_t backend::get_source_line(std::size_t /*frame*/) const BOOST_NOEXCEPT {
std::size_t backend::get_source_line(const void* /*addr*/) {
return 0;
}

View File

@@ -128,17 +128,12 @@ backend::backend(void* memory, std::size_t size, std::size_t& hash_code) BOOST_N
boost::hash_combine(hash_code, hc);
}
std::string backend::get_name(std::size_t frame) const {
std::string result;
if (frame >= data_->frames_count) {
return result;
}
std::string backend::get_name(const void* addr) {
com_holder<IDebugSymbols> idebug_;
if (!try_init_com(idebug_)) {
return result;
}
const ULONG64 offset = reinterpret_cast<ULONG64>(data_->buffer[frame]);
const ULONG64 offset = reinterpret_cast<ULONG64>(addr);
char name[256];
name[0] = '\0';
@@ -175,17 +170,12 @@ const void* backend::get_address(std::size_t frame) const BOOST_NOEXCEPT {
return data_->buffer[frame];
}
std::string backend::get_source_file(std::size_t frame) const {
std::string result;
if (frame >= data_->frames_count) {
return result;
}
std::string backend::get_source_file(const void* addr) {
com_holder<IDebugSymbols> idebug_;
if (!try_init_com(idebug_)) {
return result;
}
const ULONG64 offset = reinterpret_cast<ULONG64>(data_->buffer[frame]);
const ULONG64 offset = reinterpret_cast<ULONG64>(addr);
char name[256];
name[0] = 0;
@@ -221,7 +211,7 @@ std::string backend::get_source_file(std::size_t frame) const {
return result;
}
std::size_t backend::get_source_line(std::size_t frame) const BOOST_NOEXCEPT {
std::size_t backend::get_source_line(const void* addr) {
ULONG line_num = 0;
com_holder<IDebugSymbols> idebug_;
@@ -230,7 +220,7 @@ std::size_t backend::get_source_line(std::size_t frame) const BOOST_NOEXCEPT {
}
const bool is_ok = (S_OK == idebug_->GetLineByOffset(
reinterpret_cast<ULONG64>(data_->buffer[frame]),
reinterpret_cast<ULONG64>(addr),
&line_num,
0,
0,

View File

@@ -61,6 +61,13 @@ inline boost::array<char, 2 + sizeof(void*) * 2 + 1> to_hex_array(void* addr) BO
);
}
inline boost::array<char, 2 + sizeof(void*) * 2 + 1> to_hex_array(const void* addr) BOOST_NOEXCEPT {
return to_hex_array(
reinterpret_cast<std::size_t>(addr)
);
}
}}} // namespace boost::stacktrace::detail
#endif // BOOST_STACKTRACE_DETAIL_STACKTRACE_TO_HEX_ARRAY_HPP

View File

@@ -58,7 +58,7 @@ public:
/// @returns Name of the frame (function name in a human readable form).
/// @throws std::bad_alloc if not enough memory to construct resulting string.
std::string name() const {
return impl_->get_name(frame_no_);
return boost::stacktrace::detail::backend::get_name(address());
}
/// @returns Address of the frame function.
@@ -71,13 +71,13 @@ public:
/// if this->source_line() == 0.
/// @throws std::bad_alloc if not enough memory to construct resulting string.
std::string source_file() const {
return impl_->get_source_file(frame_no_);
return boost::stacktrace::detail::backend::get_source_file(address());
}
/// @returns Code line in the source file, were the function of the frame is defined.
/// @throws Nothing.
std::size_t source_line() const BOOST_NOEXCEPT {
return impl_->get_source_line(frame_no_);
return boost::stacktrace::detail::backend::get_source_line(address());
}
};

View File

@@ -1,10 +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)
#define BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
#define BOOST_STACKTRACE_USE_LIBUNWIND
#define BOOST_STACKTRACE_LINK
#include <boost/stacktrace/detail/backend.ipp>

View File

@@ -6,7 +6,6 @@
#
lib dl : : <link>shared ;
lib unwind : : <link>shared ;
lib Dbghelp ;
project
@@ -19,18 +18,15 @@ project
;
local UNW_DEPS = <library>unwind [ check-target-builds ../build//libunwind : : <build>no ] ;
local BT_DEPS = <target-os>linux:<library>dl [ check-target-builds ../build//backtrace : : <build>no ] ;
local WIND_DEPS = <library>Dbghelp [ check-target-builds ../build//WinDbg : : <build>no ] ;
local NOOP_DEPS = ;
local AUTO_DEPS = <target-os>linux:<library>dl [ check-target-builds ../build//WinDbg : <library>Dbghelp ] [ check-target-builds ../build//libunwind : <library>unwind ] ;
local AUTO_DEPS = <target-os>linux:<library>dl [ check-target-builds ../build//WinDbg : <library>Dbghelp ] ;
local LINKSHARED_UNW = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_libunwind $(UNW_DEPS) ;
local LINKSHARED_BT = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_backtrace $(BT_DEPS) ;
local LINKSHARED_WIND = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_windbg $(WIND_DEPS) ;
local LINKSHARED_NOOP = <link>shared <define>BOOST_STACKTRACE_DYN_LINK <library>/boost/stacktrace//boost_stacktrace_noop $(NOOP_DEPS) ;
lib test_impl_lib_libunwind : test_impl.cpp : $(LINKSHARED_UNW) ;
lib test_impl_lib_backtrace : test_impl.cpp : $(LINKSHARED_BT) ;
lib test_impl_lib_windbg : test_impl.cpp : $(LINKSHARED_WIND) ;
lib test_impl_lib_noop : test_impl.cpp : $(LINKSHARED_NOOP) ;
@@ -38,26 +34,22 @@ lib test_impl_lib_noop : test_impl.cpp : $(LINKSHARED_NOOP) ;
test-suite stacktrace_tests
:
# Header only tests
[ run test.cpp test_impl.cpp : : : <define>BOOST_STACKTRACE_USE_LIBUNWIND $(UNW_DEPS) : libunwind_ho ]
[ run test.cpp test_impl.cpp : : : <define>BOOST_STACKTRACE_USE_BACKTRACE $(BT_DEPS) : backtrace_ho ]
[ run test.cpp test_impl.cpp : : : <define>BOOST_STACKTRACE_USE_WINDBG $(WIND_DEPS) : windbg_ho ]
[ run test_noop.cpp test_impl.cpp : : : <define>BOOST_STACKTRACE_USE_NOOP $(NOOP_DEPS) : noop_ho ]
[ run test.cpp test_impl.cpp : : : $(AUTO_DEPS) : autodetect_ho ]
# Test with shared linked backends
[ run test.cpp : : : <library>.//test_impl_lib_libunwind $(LINKSHARED_UNW) : libunwind_lib ]
[ run test.cpp : : : <library>.//test_impl_lib_backtrace $(LINKSHARED_BT) : backtrace_lib ]
[ run test.cpp : : : <library>.//test_impl_lib_windbg $(LINKSHARED_WIND) : windbg_lib ]
[ run test_noop.cpp : : : <library>.//test_impl_lib_noop $(LINKSHARED_NOOP) : noop_lib ]
# Making sure that the examples work
[ run ../example/getting_started.cpp : : : <define>BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_UNW) : libunwind_getting_started ]
[ run ../example/getting_started.cpp : : : <define>BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_BT) : backtrace_getting_started ]
[ run ../example/getting_started.cpp : : : <define>BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_WIND) : windbg_getting_started ]
[ run ../example/getting_started.cpp : : : <define>BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(LINKSHARED_NOOP) : noop_getting_started ]
[ run ../example/getting_started.cpp : : : <define>BOOST_ENABLE_ASSERT_DEBUG_HANDLER $(AUTO_DEPS) : autodetect_getting_started ]
[ run ../example/throwing_st.cpp : : : $(LINKSHARED_UNW) : libunwind_throwing_st ]
[ run ../example/throwing_st.cpp : : : $(LINKSHARED_BT) : backtrace_throwing_st ]
[ run ../example/throwing_st.cpp : : : $(LINKSHARED_WIND) : windbg_throwing_st ]
[ run ../example/throwing_st.cpp : : : $(LINKSHARED_NOOP) : noop_throwing_st ]