frame_unwind.ipp 3.1 KB

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