File indexing completed on 2025-09-13 08:31:11
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
0009 #define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
0010
0011 #include <boost/dll/config.hpp>
0012 #include <boost/dll/shared_library_load_mode.hpp>
0013 #include <boost/dll/detail/posix/path_from_handle.hpp>
0014 #include <boost/dll/detail/posix/program_location_impl.hpp>
0015
0016 #include <boost/core/invoke_swap.hpp>
0017 #include <boost/predef/os.h>
0018
0019 #include <utility> // std::move
0020
0021 #include <dlfcn.h>
0022 #include <cstring> // strncmp
0023 #if !BOOST_OS_MACOS && !BOOST_OS_IOS && !BOOST_OS_QNX
0024 # include <link.h>
0025 #elif BOOST_OS_QNX
0026
0027 # include <sys/link.h>
0028 #endif
0029
0030 #ifdef BOOST_HAS_PRAGMA_ONCE
0031 # pragma once
0032 #endif
0033
0034 namespace boost { namespace dll { namespace detail {
0035
0036 class shared_library_impl {
0037 public:
0038 typedef void* native_handle_t;
0039
0040 shared_library_impl() noexcept
0041 : handle_(nullptr)
0042 {}
0043
0044 ~shared_library_impl() noexcept {
0045 unload();
0046 }
0047
0048 shared_library_impl(shared_library_impl&& sl) noexcept
0049 : handle_(sl.handle_)
0050 {
0051 sl.handle_ = nullptr;
0052 }
0053
0054 explicit shared_library_impl(native_handle_t handle) noexcept
0055 : handle_(handle)
0056 {}
0057
0058 shared_library_impl & operator=(shared_library_impl&& sl) noexcept {
0059 swap(sl);
0060 return *this;
0061 }
0062
0063
0064 static boost::dll::fs::path decorate(const boost::dll::fs::path & sl) {
0065 boost::dll::fs::path actual_path = (
0066 std::strncmp(sl.filename().string().c_str(), "lib", 3)
0067 ? boost::dll::fs::path((sl.has_parent_path() ? sl.parent_path() / "lib" : "lib").native() + sl.filename().native())
0068 : sl
0069 );
0070 actual_path += suffix();
0071 return actual_path;
0072 }
0073
0074 void load(boost::dll::fs::path sl, load_mode::type portable_mode, std::error_code &ec) {
0075 typedef int native_mode_t;
0076 native_mode_t native_mode = static_cast<native_mode_t>(portable_mode);
0077 unload();
0078
0079
0080 if (sl.empty()) {
0081 boost::dll::detail::reset_dlerror();
0082 ec = std::make_error_code(
0083 std::errc::bad_file_descriptor
0084 );
0085
0086 return;
0087 }
0088
0089
0090 if (!(native_mode & load_mode::rtld_now)) {
0091 native_mode |= load_mode::rtld_lazy;
0092 }
0093
0094 if (!(native_mode & load_mode::rtld_global)) {
0095 native_mode |= load_mode::rtld_local;
0096 }
0097
0098 #if BOOST_OS_LINUX || BOOST_OS_ANDROID
0099 if (!sl.has_parent_path() && !(native_mode & load_mode::search_system_folders)) {
0100 sl = "." / sl;
0101 }
0102 #else
0103 if (!sl.is_absolute() && !(native_mode & load_mode::search_system_folders)) {
0104 boost::dll::fs::error_code current_path_ec;
0105 boost::dll::fs::path prog_loc = boost::dll::fs::current_path(current_path_ec);
0106 if (!current_path_ec) {
0107 prog_loc /= sl;
0108 sl.swap(prog_loc);
0109 }
0110 }
0111 #endif
0112
0113 native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::search_system_folders);
0114
0115
0116 if (!!(native_mode & load_mode::append_decorations)) {
0117 native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::append_decorations);
0118
0119 boost::dll::fs::path actual_path = decorate(sl);
0120 handle_ = dlopen(actual_path.c_str(), native_mode);
0121 if (handle_) {
0122 boost::dll::detail::reset_dlerror();
0123 return;
0124 }
0125 boost::dll::fs::error_code prog_loc_err;
0126 boost::dll::fs::path loc = boost::dll::detail::program_location_impl(prog_loc_err);
0127 if (boost::dll::fs::exists(actual_path) && !boost::dll::fs::equivalent(sl, loc, prog_loc_err)) {
0128
0129 ec = std::make_error_code(
0130 std::errc::executable_format_error
0131 );
0132 return;
0133 }
0134 }
0135
0136
0137 handle_ = dlopen(sl.c_str(), native_mode);
0138 if (handle_) {
0139 boost::dll::detail::reset_dlerror();
0140 return;
0141 }
0142
0143 ec = std::make_error_code(
0144 std::errc::bad_file_descriptor
0145 );
0146
0147
0148
0149
0150 boost::dll::fs::error_code prog_loc_err;
0151 boost::dll::fs::path loc = boost::dll::detail::program_location_impl(prog_loc_err);
0152 if (!prog_loc_err && boost::dll::fs::equivalent(sl, loc, prog_loc_err) && !prog_loc_err) {
0153
0154
0155
0156
0157 ec.clear();
0158 boost::dll::detail::reset_dlerror();
0159 handle_ = dlopen(nullptr, native_mode);
0160 if (!handle_) {
0161 ec = std::make_error_code(
0162 std::errc::bad_file_descriptor
0163 );
0164 }
0165 }
0166 }
0167
0168 bool is_loaded() const noexcept {
0169 return (handle_ != 0);
0170 }
0171
0172 void unload() noexcept {
0173 if (!is_loaded()) {
0174 return;
0175 }
0176
0177 dlclose(handle_);
0178 handle_ = 0;
0179 }
0180
0181 void swap(shared_library_impl& rhs) noexcept {
0182 boost::core::invoke_swap(handle_, rhs.handle_);
0183 }
0184
0185 boost::dll::fs::path full_module_path(std::error_code &ec) const {
0186 return boost::dll::detail::path_from_handle(handle_, ec);
0187 }
0188
0189 static boost::dll::fs::path suffix() {
0190
0191 #if BOOST_OS_MACOS || BOOST_OS_IOS
0192 return ".dylib";
0193 #else
0194 return ".so";
0195 #endif
0196 }
0197
0198 void* symbol_addr(const char* sb, std::error_code &ec) const noexcept {
0199
0200 void* const symbol = dlsym(handle_, sb);
0201 if (symbol == nullptr) {
0202 ec = std::make_error_code(
0203 std::errc::invalid_seek
0204 );
0205 }
0206
0207
0208
0209
0210
0211
0212 return symbol;
0213 }
0214
0215 native_handle_t native() const noexcept {
0216 return handle_;
0217 }
0218
0219 private:
0220 native_handle_t handle_;
0221 };
0222
0223 }}}
0224
0225 #endif