frame_unwind.ipp 2.8 KB

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