123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- // Copyright Antony Polukhin, 2016-2024.
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
- #define BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
- #include <boost/config.hpp>
- #ifdef BOOST_HAS_PRAGMA_ONCE
- # pragma once
- #endif
- #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
- # include <dlfcn.h>
- #else
- # include <boost/winapi/dll.hpp>
- #endif
- #ifdef _AIX
- /* AIX doesn't provide dladdr syscall.
- This provides a minimal implementation of dladdr which retrieves
- only files information.
- TODO: Implement the symbol name. */
- #include <sys/ldr.h>
- #include <sys/debug.h>
- #include <cstring>
- #include <string>
- #include <vector>
- namespace boost { namespace stacktrace { namespace detail {
- struct Dl_info {
- std::string fname_storage{};
- const char *dli_fname = nullptr;
- const char *dli_sname = nullptr;
- };
- int dladdr(const void* address_raw, Dl_info* info) noexcept {
- static constexpr std::size_t dl_buff_size = 0x1000;
- try {
- std::vector<struct ld_info> pld_info_storage;
- pld_info_storage.resize(
- (dl_buff_size + sizeof(struct ld_info) - 1) / sizeof(struct ld_info)
- );
- if (loadquery(L_GETINFO, pld_info_storage.data(), dl_buff_size) == -1) {
- return 0;
- }
- const auto* pld_info = pld_info_storage.data();
- const char* const address = static_cast<const char*>(address_raw);
- while (true) {
- const auto* const dataorg = static_cast<char*>(pld_info->ldinfo_dataorg);
- const auto* const textorg = static_cast<char*>(pld_info->ldinfo_textorg);
- if ((address >= dataorg && address < dataorg + pld_info->ldinfo_datasize )
- || (address >= textorg && address < textorg + pld_info->ldinfo_textsize )) {
- /* ldinfo_filename is the null-terminated path name followed
- by null-terminated member name.
- If the file is not an archive, then member name is null. */
- const auto size_filename = std::strlen(pld_info->ldinfo_filename);
- const auto size_member = std::strlen(pld_info->ldinfo_filename + size_filename + 1);
- /* If member is not null, '(' and ')' must be added to create a
- fname looking like "filename(membername)". */
- info->fname_storage.reserve(size_filename + (size_member ? size_member + 3 : 1));
- info->fname_storage = pld_info->ldinfo_filename;
- if (size_member) {
- info->fname_storage += "(";
- info->fname_storage += pld_info->ldinfo_filename + size_filename + 1;
- info->fname_storage += ")";
- }
- info->dli_fname = info->fname_storage.c_str();
- return 1;
- }
- if (!pld_info->ldinfo_next) {
- break;
- }
- pld_info = reinterpret_cast<const struct ld_info *>(
- reinterpret_cast<const char*>(pld_info) + pld_info->ldinfo_next
- );
- };
- } catch (...) {
- // ignore
- }
- return 0;
- }
- }}} // namespace boost::stacktrace::detail
- #elif !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
- namespace boost { namespace stacktrace { namespace detail {
- using Dl_info = ::Dl_info;
- inline int dladdr(const void* addr, Dl_info& dli) noexcept {
- // `dladdr` on Solaris accepts nonconst addresses
- return ::dladdr(const_cast<void*>(addr), &dli);
- }
- }}} // namespace boost::stacktrace::detail
- #endif
- namespace boost { namespace stacktrace { namespace detail {
- #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
- class location_from_symbol {
- boost::stacktrace::detail::Dl_info dli_;
- public:
- explicit location_from_symbol(const void* addr) noexcept
- : dli_()
- {
- if (!boost::stacktrace::detail::dladdr(addr, dli_)) {
- dli_.dli_fname = 0;
- }
- }
- bool empty() const noexcept {
- return !dli_.dli_fname;
- }
- const char* name() const noexcept {
- return dli_.dli_fname;
- }
- };
- class program_location {
- public:
- const char* name() const noexcept {
- return 0;
- }
- };
- #else
- class location_from_symbol {
- BOOST_STATIC_CONSTEXPR boost::winapi::DWORD_ DEFAULT_PATH_SIZE_ = 260;
- char file_name_[DEFAULT_PATH_SIZE_];
- public:
- explicit location_from_symbol(const void* addr) noexcept {
- file_name_[0] = '\0';
- boost::winapi::MEMORY_BASIC_INFORMATION_ mbi;
- if (!boost::winapi::VirtualQuery(addr, &mbi, sizeof(mbi))) {
- return;
- }
- boost::winapi::HMODULE_ handle = reinterpret_cast<boost::winapi::HMODULE_>(mbi.AllocationBase);
- if (!boost::winapi::GetModuleFileNameA(handle, file_name_, DEFAULT_PATH_SIZE_)) {
- file_name_[0] = '\0';
- return;
- }
- }
- bool empty() const noexcept {
- return file_name_[0] == '\0';
- }
- const char* name() const noexcept {
- return file_name_;
- }
- };
- class program_location {
- BOOST_STATIC_CONSTEXPR boost::winapi::DWORD_ DEFAULT_PATH_SIZE_ = 260;
- char file_name_[DEFAULT_PATH_SIZE_];
- public:
- program_location() noexcept {
- file_name_[0] = '\0';
- const boost::winapi::HMODULE_ handle = 0;
- if (!boost::winapi::GetModuleFileNameA(handle, file_name_, DEFAULT_PATH_SIZE_)) {
- file_name_[0] = '\0';
- }
- }
- const char* name() const noexcept {
- return file_name_[0] ? file_name_ : 0;
- }
- };
- #endif
- }}} // namespace boost::stacktrace::detail
- #endif // BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
|