Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/boost/stacktrace/detail/frame_unwind.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ std::string frame::name() const {
}

#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
::Dl_info dli;
const bool dl_ok = !!::dladdr(const_cast<void*>(addr_), &dli); // `dladdr` on Solaris accepts nonconst addresses
boost::stacktrace::detail::Dl_info dli;
const bool dl_ok = !!boost::stacktrace::detail::dladdr(addr_, dli);
if (dl_ok && dli.dli_sname) {
return boost::core::demangle(dli.dli_sname);
}
Expand Down
97 changes: 95 additions & 2 deletions include/boost/stacktrace/detail/location_from_symbol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,110 @@
# 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 {
::Dl_info dli_;
boost::stacktrace::detail::Dl_info dli_;

public:
explicit location_from_symbol(const void* addr) BOOST_NOEXCEPT
: dli_()
{
if (!::dladdr(const_cast<void*>(addr), &dli_)) { // `dladdr` on Solaris accepts nonconst addresses
if (!boost::stacktrace::detail::dladdr(addr, dli_)) {
dli_.dli_fname = 0;
}
}
Expand Down