#ifndef SAFE_DL_HPP #define SAFE_DL_HPP #include "../utils/common.hpp" #include "../utils/utils.hpp" #include "../utils/program_name.hpp" #include #include #include #include #include #include #if CPPTRACE_HAS_DL_FIND_OBJECT #if IS_LINUX || IS_APPLE #include #include #include #endif namespace cpptrace { namespace detail { inline void get_minimal_object_frame(frame_ptr address, minimal_object_frame* out) { dl_find_object result; if(_dl_find_object(reinterpret_cast(address), &result) == 0) { out->raw_address = address; out->address_relative_to_object_base_in_memory = address - reinterpret_cast(result.dlfo_map_start); if(result.dlfo_link_map->l_name != nullptr && result.dlfo_link_map->l_name[0] != 0) { std::size_t path_length = std::strlen(result.dlfo_link_map->l_name); std::memcpy( out->object_path, result.dlfo_link_map->l_name, std::min(path_length + 1, std::size_t(CPPTRACE_PATH_MAX + 1)) ); } else { // empty l_name, this means it's the currently running executable memset(out->object_path, 0, PATH_MAX + 1); auto res = readlink("/proc/self/exe", out->object_path, PATH_MAX); if(res == -1) { // error handling? } // TODO: Special handling for /proc/pid/exe unlink edge case } } else { // std::cout<<"error"<raw_address = address; out->address_relative_to_object_base_in_memory = 0; out->object_path[0] = 0; } // TODO: Handle this part of the documentation? // The address can be a code address or data address. On architectures using function descriptors, no attempt is // made to decode the function descriptor. Depending on how these descriptors are implemented, _dl_find_object // may return the object that defines the function descriptor (and not the object that contains the code // implementing the function), or fail to find any object at all. } } } #else namespace cpptrace { namespace detail { inline void get_minimal_object_frame(frame_ptr address, minimal_object_frame* out) { out->raw_address = 0; out->address_relative_to_object_base_in_memory = 0; out->object_path[0] = 0; } } } #endif #endif