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