• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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