blob: a3e99ac20b4adee69d8e8a790664cbd62789b22f [file] [log] [blame]
// Copyright Antony Polukhin, 2016-2019.
//
// 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_FRAME_UNWIND_IPP
#define BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#include <boost/stacktrace/frame.hpp>
#include <boost/stacktrace/detail/to_hex_array.hpp>
#include <boost/stacktrace/detail/location_from_symbol.hpp>
#include <boost/stacktrace/detail/to_dec_array.hpp>
#include <boost/core/demangle.hpp>
#include <cstdio>
#ifdef BOOST_STACKTRACE_USE_BACKTRACE
# include <boost/stacktrace/detail/libbacktrace_impls.hpp>
#elif defined(BOOST_STACKTRACE_USE_ADDR2LINE)
# include <boost/stacktrace/detail/addr2line_impls.hpp>
#else
# include <boost/stacktrace/detail/unwind_base_impls.hpp>
#endif
namespace boost { namespace stacktrace { namespace detail {
template <class Base>
class to_string_impl_base: private Base {
public:
std::string operator()(boost::stacktrace::detail::native_frame_ptr_t addr) {
Base::res.clear();
Base::prepare_function_name(addr);
if (!Base::res.empty()) {
Base::res = boost::core::demangle(Base::res.c_str());
} else {
Base::res = to_hex_array(addr).data();
}
if (Base::prepare_source_location(addr)) {
return Base::res;
}
boost::stacktrace::detail::location_from_symbol loc(addr);
if (!loc.empty()) {
Base::res += " in ";
Base::res += loc.name();
}
return Base::res;
}
};
std::string to_string(const frame* frames, std::size_t size) {
std::string res;
res.reserve(64 * size);
to_string_impl impl;
for (std::size_t i = 0; i < size; ++i) {
if (i < 10) {
res += ' ';
}
res += boost::stacktrace::detail::to_dec_array(i).data();
res += '#';
res += ' ';
res += impl(frames[i].address());
res += '\n';
}
return res;
}
} // namespace detail
std::string frame::name() const {
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
::Dl_info dli;
const bool dl_ok = !!::dladdr(const_cast<void*>(addr_), &dli); // `dladdr` on Solaris accepts nonconst addresses
if (dl_ok && dli.dli_sname) {
return boost::core::demangle(dli.dli_sname);
}
#endif
return boost::stacktrace::detail::name_impl(addr_);
}
std::string to_string(const frame& f) {
boost::stacktrace::detail::to_string_impl impl;
return impl(f.address());
}
}} // namespace boost::stacktrace
#endif // BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP