Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-30 08:31:18

0001 // Copyright Antony Polukhin, 2016-2024.
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
0008 #define BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
0009 
0010 #include <boost/config.hpp>
0011 #ifdef BOOST_HAS_PRAGMA_ONCE
0012 #   pragma once
0013 #endif
0014 
0015 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
0016 #   include <dlfcn.h>
0017 #else
0018 #   include <boost/winapi/dll.hpp>
0019 #endif
0020 
0021 #ifdef _AIX
0022 /* AIX doesn't provide dladdr syscall.
0023    This provides a minimal implementation of dladdr which retrieves
0024    only files information.
0025    TODO: Implement the symbol name.  */
0026 
0027 #include <sys/ldr.h>
0028 #include <sys/debug.h>
0029 #include <cstring>
0030 #include <string>
0031 #include <vector>
0032 
0033 namespace boost { namespace stacktrace { namespace detail {
0034 
0035 struct Dl_info {
0036   std::string fname_storage{};
0037   const char *dli_fname = nullptr;
0038   const char *dli_sname = nullptr;
0039 };
0040 
0041 int dladdr(const void* address_raw, Dl_info* info) noexcept {
0042   static constexpr std::size_t dl_buff_size = 0x1000;
0043 
0044   try {
0045     std::vector<struct ld_info> pld_info_storage;
0046     pld_info_storage.resize(
0047         (dl_buff_size + sizeof(struct ld_info) - 1) / sizeof(struct ld_info)
0048     );
0049 
0050     if (loadquery(L_GETINFO, pld_info_storage.data(), dl_buff_size) == -1) {
0051       return 0;
0052     }
0053 
0054     const auto* pld_info = pld_info_storage.data();
0055     const char* const address = static_cast<const char*>(address_raw);
0056     while (true) {
0057       const auto* const dataorg = static_cast<char*>(pld_info->ldinfo_dataorg);
0058       const auto* const textorg = static_cast<char*>(pld_info->ldinfo_textorg);
0059       if ((address >= dataorg && address < dataorg + pld_info->ldinfo_datasize )
0060           || (address >= textorg && address < textorg + pld_info->ldinfo_textsize )) {
0061 
0062         /* ldinfo_filename is the null-terminated path name followed
0063            by null-terminated member name.
0064            If the file is not an archive, then member name is null. */
0065         const auto size_filename = std::strlen(pld_info->ldinfo_filename);
0066         const auto size_member = std::strlen(pld_info->ldinfo_filename + size_filename + 1);
0067 
0068         /* If member is not null, '(' and ')' must be added to create a
0069            fname looking like "filename(membername)".  */
0070         info->fname_storage.reserve(size_filename + (size_member ? size_member  + 3 : 1));
0071         info->fname_storage = pld_info->ldinfo_filename;
0072         if (size_member) {
0073           info->fname_storage += "(";
0074           info->fname_storage += pld_info->ldinfo_filename + size_filename + 1;
0075           info->fname_storage += ")";
0076         }
0077 
0078         info->dli_fname = info->fname_storage.c_str();
0079         return 1;
0080       }
0081 
0082       if (!pld_info->ldinfo_next) {
0083         break;
0084       }
0085 
0086       pld_info = reinterpret_cast<const struct ld_info *>(
0087         reinterpret_cast<const char*>(pld_info) + pld_info->ldinfo_next
0088       );
0089     };
0090   } catch (...) {
0091     // ignore
0092   }
0093 
0094   return 0;
0095 }
0096 
0097 }}} // namespace boost::stacktrace::detail
0098 
0099 #elif !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
0100 
0101 namespace boost { namespace stacktrace { namespace detail {
0102 
0103 using Dl_info = ::Dl_info;
0104 
0105 inline int dladdr(const void* addr, Dl_info& dli) noexcept {
0106   // `dladdr` on Solaris accepts nonconst addresses
0107   return ::dladdr(const_cast<void*>(addr), &dli);
0108 }
0109 
0110 }}} // namespace boost::stacktrace::detail
0111 
0112 #endif
0113 
0114 namespace boost { namespace stacktrace { namespace detail {
0115 
0116 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
0117 class location_from_symbol {
0118     boost::stacktrace::detail::Dl_info dli_;
0119 
0120 public:
0121     explicit location_from_symbol(const void* addr) noexcept
0122         : dli_()
0123     {
0124         if (!boost::stacktrace::detail::dladdr(addr, dli_)) {
0125             dli_.dli_fname = 0;
0126         }
0127     }
0128 
0129     bool empty() const noexcept {
0130         return !dli_.dli_fname;
0131     }
0132 
0133     const char* name() const noexcept {
0134         return dli_.dli_fname;
0135     }
0136 };
0137 
0138 class program_location {
0139 public:
0140     const char* name() const noexcept {
0141         return 0;
0142     }
0143 };
0144 
0145 #else
0146 
0147 class location_from_symbol {
0148     BOOST_STATIC_CONSTEXPR boost::winapi::DWORD_ DEFAULT_PATH_SIZE_ = 260;
0149     char file_name_[DEFAULT_PATH_SIZE_];
0150 
0151 public:
0152     explicit location_from_symbol(const void* addr) noexcept {
0153         file_name_[0] = '\0';
0154 
0155         boost::winapi::MEMORY_BASIC_INFORMATION_ mbi;
0156         if (!boost::winapi::VirtualQuery(addr, &mbi, sizeof(mbi))) {
0157             return;
0158         }
0159 
0160         boost::winapi::HMODULE_ handle = reinterpret_cast<boost::winapi::HMODULE_>(mbi.AllocationBase);
0161         if (!boost::winapi::GetModuleFileNameA(handle, file_name_, DEFAULT_PATH_SIZE_)) {
0162             file_name_[0] = '\0';
0163             return;
0164         }
0165     }
0166 
0167     bool empty() const noexcept {
0168         return file_name_[0] == '\0';
0169     }
0170 
0171     const char* name() const noexcept {
0172         return file_name_;
0173     }
0174 };
0175 
0176 class program_location {
0177     BOOST_STATIC_CONSTEXPR boost::winapi::DWORD_ DEFAULT_PATH_SIZE_ = 260;
0178     char file_name_[DEFAULT_PATH_SIZE_];
0179 
0180 public:
0181     program_location() noexcept {
0182         file_name_[0] = '\0';
0183 
0184         const boost::winapi::HMODULE_ handle = 0;
0185         if (!boost::winapi::GetModuleFileNameA(handle, file_name_, DEFAULT_PATH_SIZE_)) {
0186             file_name_[0] = '\0';
0187         }
0188     }
0189 
0190     const char* name() const noexcept {
0191         return file_name_[0] ? file_name_ : 0;
0192     }
0193 };
0194 #endif
0195 
0196 }}} // namespace boost::stacktrace::detail
0197 
0198 #endif // BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP