1// Copyright Antony Polukhin, 2016-2019. 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_FRAME_UNWIND_IPP 8#define BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP 9 10#include <boost/config.hpp> 11#ifdef BOOST_HAS_PRAGMA_ONCE 12# pragma once 13#endif 14 15#include <boost/stacktrace/frame.hpp> 16 17#include <boost/stacktrace/detail/to_hex_array.hpp> 18#include <boost/stacktrace/detail/location_from_symbol.hpp> 19#include <boost/stacktrace/detail/to_dec_array.hpp> 20#include <boost/core/demangle.hpp> 21 22#include <cstdio> 23 24#ifdef BOOST_STACKTRACE_USE_BACKTRACE 25# include <boost/stacktrace/detail/libbacktrace_impls.hpp> 26#elif defined(BOOST_STACKTRACE_USE_ADDR2LINE) 27# include <boost/stacktrace/detail/addr2line_impls.hpp> 28#else 29# include <boost/stacktrace/detail/unwind_base_impls.hpp> 30#endif 31 32namespace boost { namespace stacktrace { namespace detail { 33 34template <class Base> 35class to_string_impl_base: private Base { 36public: 37 std::string operator()(boost::stacktrace::detail::native_frame_ptr_t addr) { 38 Base::res.clear(); 39 Base::prepare_function_name(addr); 40 if (!Base::res.empty()) { 41 Base::res = boost::core::demangle(Base::res.c_str()); 42 } else { 43 Base::res = to_hex_array(addr).data(); 44 } 45 46 if (Base::prepare_source_location(addr)) { 47 return Base::res; 48 } 49 50 boost::stacktrace::detail::location_from_symbol loc(addr); 51 if (!loc.empty()) { 52 Base::res += " in "; 53 Base::res += loc.name(); 54 } 55 56 return Base::res; 57 } 58}; 59 60std::string to_string(const frame* frames, std::size_t size) { 61 std::string res; 62 if (size == 0) { 63 return res; 64 } 65 res.reserve(64 * size); 66 67 to_string_impl impl; 68 69 for (std::size_t i = 0; i < size; ++i) { 70 if (i < 10) { 71 res += ' '; 72 } 73 res += boost::stacktrace::detail::to_dec_array(i).data(); 74 res += '#'; 75 res += ' '; 76 res += impl(frames[i].address()); 77 res += '\n'; 78 } 79 80 return res; 81} 82 83 84} // namespace detail 85 86 87std::string frame::name() const { 88 if (!addr_) { 89 return std::string(); 90 } 91 92#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) 93 ::Dl_info dli; 94 const bool dl_ok = !!::dladdr(const_cast<void*>(addr_), &dli); // `dladdr` on Solaris accepts nonconst addresses 95 if (dl_ok && dli.dli_sname) { 96 return boost::core::demangle(dli.dli_sname); 97 } 98#endif 99 return boost::stacktrace::detail::name_impl(addr_); 100} 101 102std::string to_string(const frame& f) { 103 if (!f) { 104 return std::string(); 105 } 106 107 boost::stacktrace::detail::to_string_impl impl; 108 return impl(f.address()); 109} 110 111 112}} // namespace boost::stacktrace 113 114#endif // BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP 115