?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/dll.tar
???????
import_mangled.hpp 0000644 00000026434 15125237303 0010270 0 ustar 00 // Copyright 2015-2018 Klemens D. Morgenstern // Copyright 2019-2020 Antony Polukhin // // 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_DLL_IMPORT_MANGLED_HPP_ #define BOOST_DLL_IMPORT_MANGLED_HPP_ /// \file boost/dll/import_mangled.hpp /// \warning Extremely experimental! Requires C++11! Will change in next version of Boost! boost/dll/import_mangled.hpp is not included in boost/dll.hpp /// \brief Contains the boost::dll::experimental::import_mangled function for importing mangled symbols. #include <boost/dll/config.hpp> #if (__cplusplus < 201103L) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201103L) # error This file requires C++11 at least! #endif #include <boost/make_shared.hpp> #include <boost/move/move.hpp> #include <boost/dll/smart_library.hpp> #include <boost/dll/detail/import_mangled_helpers.hpp> #include <boost/core/addressof.hpp> #include <boost/core/enable_if.hpp> #include <boost/type_traits/conditional.hpp> #include <boost/type_traits/is_object.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { namespace experimental { namespace detail { template <class ... Ts> class mangled_library_function { // Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster. boost::shared_ptr<shared_library> lib_; function_tuple<Ts...> f_; public: constexpr mangled_library_function(const boost::shared_ptr<shared_library>& lib, Ts*... func_ptr) BOOST_NOEXCEPT : lib_(lib) , f_(func_ptr...) {} // Compilation error at this point means that imported function // was called with unmatching parameters. // // Example: // auto f = dll::import_mangled<void(int), void(double)>("function", "lib.so"); // f("Hello"); // error: invalid conversion from 'const char*' to 'int' // f(1, 2); // error: too many arguments to function // f(); // error: too few arguments to function template <class... Args> auto operator()(Args&&... args) const -> decltype( f_(static_cast<Args&&>(args)...) ) { return f_(static_cast<Args&&>(args)...); } }; template<class Class, class Sequence> class mangled_library_mem_fn; template <class Class, class ... Ts> class mangled_library_mem_fn<Class, sequence<Ts...>> { // Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster. typedef mem_fn_tuple<Ts...> call_tuple_t; boost::shared_ptr<shared_library> lib_; call_tuple_t f_; public: constexpr mangled_library_mem_fn(const boost::shared_ptr<shared_library>& lib, typename Ts::mem_fn... func_ptr) BOOST_NOEXCEPT : lib_(lib) , f_(func_ptr...) {} template <class ClassIn, class... Args> auto operator()(ClassIn *cl, Args&&... args) const -> decltype( f_(cl, static_cast<Args&&>(args)...) ) { return f_(cl, static_cast<Args&&>(args)...); } }; // simple enough to be here template<class Seq> struct is_variable : boost::false_type {}; template<typename T> struct is_variable<sequence<T>> : boost::is_object<T> {}; template <class Sequence, bool isFunction = is_function_seq<Sequence>::value, bool isMemFn = is_mem_fn_seq <Sequence>::value, bool isVariable = is_variable <Sequence>::value> struct mangled_import_type; template <class ...Args> struct mangled_import_type<sequence<Args...>, true,false,false> //is function { typedef boost::dll::experimental::detail::mangled_library_function<Args...> type; static type make( const boost::dll::experimental::smart_library& p, const std::string& name) { return type( boost::make_shared<shared_library>(p.shared_lib()), boost::addressof(p.get_function<Args>(name))...); } }; template <class Class, class ...Args> struct mangled_import_type<sequence<Class, Args...>, false, true, false> //is member-function { typedef typename boost::dll::experimental::detail::make_mem_fn_seq<Class, Args...>::type actual_sequence; typedef typename boost::dll::experimental::detail::mangled_library_mem_fn<Class, actual_sequence> type; template<class ... ArgsIn> static type make_impl( const boost::dll::experimental::smart_library& p, const std::string & name, sequence<ArgsIn...> * ) { return type(boost::make_shared<shared_library>(p.shared_lib()), p.get_mem_fn<typename ArgsIn::class_type, typename ArgsIn::func_type>(name)...); } static type make( const boost::dll::experimental::smart_library& p, const std::string& name) { return make_impl(p, name, static_cast<actual_sequence*>(nullptr)); } }; template <class T> struct mangled_import_type<sequence<T>, false, false, true> //is variable { typedef boost::shared_ptr<T> type; static type make( const boost::dll::experimental::smart_library& p, const std::string& name) { return type( boost::make_shared<shared_library>(p.shared_lib()), boost::addressof(p.get_variable<T>(name))); } }; } // namespace detail #ifndef BOOST_DLL_DOXYGEN # define BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE inline typename \ boost::dll::experimental::detail::mangled_import_type<boost::dll::experimental::detail::sequence<Args...>>::type #endif /* * Variants: * import_mangled<int>("Stuff"); * import_mangled<thingy(xyz)>("Function"); * import mangled<thingy, void(int)>("Function"); */ /*! * Returns callable object or boost::shared_ptr<T> that holds the symbol imported * from the loaded library. Returned value refcounts usage * of the loaded shared library, so that it won't get unload until all copies of return value * are not destroyed. * * For importing symbols by \b alias names use \forcedlink{import_alias} method. * * \b Examples: * * \code * boost::function<int(int)> f = import_mangled<int(int)>("test_lib.so", "integer_func_name"); * * auto f_cpp11 = import_mangled<int(int)>("test_lib.so", "integer_func_name"); * \endcode * * \code * boost::shared_ptr<int> i = import_mangled<int>("test_lib.so", "integer_name"); * \endcode * * Additionally you can also import overloaded symbols, including member-functions. * * \code * auto fp = import_mangled<void(int), void(double)>("test_lib.so", "func"); * \endcode * * \code * auto fp = import_mangled<my_class, void(int), void(double)>("test_lib.so", "func"); * \endcode * * If qualified member-functions are needed, this can be set by repeating the class name with const or volatile. * All following signatures after the redifintion will use this, i.e. the latest. * * * * \code * auto fp = import_mangled<my_class, void(int), void(double), * const my_class, void(int), void(double)>("test_lib.so", "func"); * \endcode * * \b Template \b parameter \b T: Type of the symbol that we are going to import. Must be explicitly specified. * * \param lib Path to shared library or shared library to load function from. * \param name Null-terminated C or C++ mangled name of the function to import. Can handle std::string, char*, const char*. * \param mode An mode that will be used on library load. * * \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. * Overload that accepts path also throws std::bad_alloc in case of insufficient memory. */ template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const boost::dll::fs::path& lib, const char* name, load_mode::type mode = load_mode::default_mode) { typedef typename boost::dll::experimental::detail::mangled_import_type< boost::dll::experimental::detail::sequence<Args...>> type; boost::dll::experimental::smart_library p(lib, mode); //the load return type::make(p, name); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const boost::dll::fs::path& lib, const std::string& name, load_mode::type mode = load_mode::default_mode) { return import_mangled<Args...>(lib, name.c_str(), mode); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const smart_library& lib, const char* name) { typedef typename boost::dll::experimental::detail::mangled_import_type<detail::sequence<Args...>> type; return type::make(lib, name); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const smart_library& lib, const std::string& name) { return import_mangled<Args...>(lib, name.c_str()); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(BOOST_RV_REF(smart_library) lib, const char* name) { typedef typename boost::dll::experimental::detail::mangled_import_type<detail::sequence<Args...>> type; return type::make(lib, name); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(BOOST_RV_REF(smart_library) lib, const std::string& name) { return import_mangled<Args...>(boost::move(lib), name.c_str()); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const shared_library& lib, const char* name) { typedef typename boost::dll::experimental::detail::mangled_import_type<detail::sequence<Args...>> type; boost::shared_ptr<boost::dll::experimental::smart_library> p = boost::make_shared<boost::dll::experimental::smart_library>(lib); return type::make(p, name); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const shared_library& lib, const std::string& name) { return import_mangled<Args...>(lib, name.c_str()); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(BOOST_RV_REF(shared_library) lib, const char* name) { typedef typename boost::dll::experimental::detail::mangled_import_type<detail::sequence<Args...>> type; boost::dll::experimental::smart_library p(boost::move(lib)); return type::make(p, name); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class ...Args> BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(BOOST_RV_REF(shared_library) lib, const std::string& name) { return import_mangled<Args...>(boost::move(lib), name.c_str()); } #undef BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE }}} #endif /* BOOST_DLL_IMPORT_MANGLED_HPP_ */ alias.hpp 0000644 00000030350 15125237303 0006350 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_ALIAS_HPP #define BOOST_DLL_ALIAS_HPP #include <boost/dll/config.hpp> #include <boost/static_assert.hpp> #include <boost/predef/compiler.h> #include <boost/predef/os.h> #include <boost/dll/detail/aggressive_ptr_cast.hpp> #if BOOST_COMP_GNUC // MSVC does not have <stdint.h> and defines it in some other header, MinGW requires that header. #include <stdint.h> // intptr_t #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif /// \file boost/dll/alias.hpp /// \brief Includes alias methods and macro. You can include this header or /// boost/dll/shared_library.hpp to reduce dependencies /// in case you do not use the refcountable functions. namespace boost { namespace dll { #ifdef BOOST_DLL_DOXYGEN /// Define this macro to explicitly specify translation unit in which alias must be instantiated. /// See section 'Limitations' for more info. You may find usage examples in source codes of almost each tutorial. /// Must be used in code, when \forcedmacrolink{BOOST_DLL_FORCE_NO_WEAK_EXPORTS} is defined #define BOOST_DLL_FORCE_ALIAS_INSTANTIATION /// Define this macro to disable exporting weak symbols and start using the \forcedmacrolink{BOOST_DLL_FORCE_ALIAS_INSTANTIATION}. /// This may be useful for working around linker problems or to test your program for compatibility with linkers that do not support export of weak symbols. #define BOOST_DLL_FORCE_NO_WEAK_EXPORTS #endif #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows #define BOOST_DLL_SELECTANY __declspec(selectany) #define BOOST_DLL_SECTION(SectionName, Permissions) \ BOOST_STATIC_ASSERT_MSG( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ __pragma(section(#SectionName, Permissions)) __declspec(allocate(#SectionName)) \ /**/ #else // #if BOOST_COMP_MSVC #if BOOST_OS_WINDOWS || BOOST_OS_ANDROID || BOOST_COMP_IBM // There are some problems with mixing `__dllexport__` and `weak` using MinGW // See https://sourceware.org/bugzilla/show_bug.cgi?id=17480 // // Android had an issue with exporting weak symbols // https://code.google.com/p/android/issues/detail?id=70206 #define BOOST_DLL_SELECTANY #else // #if BOOST_OS_WINDOWS /*! * \brief Macro that allows linker to select any occurrence of this symbol instead of * failing with 'multiple definitions' error at linktime. * * This macro does not work on Android, IBM XL C/C++ and MinGW+Windows * because of linker problems with exporting weak symbols * (See https://code.google.com/p/android/issues/detail?id=70206, https://sourceware.org/bugzilla/show_bug.cgi?id=17480) */ #define BOOST_DLL_SELECTANY __attribute__((weak)) #endif // #if BOOST_OS_WINDOWS // TODO: improve section permissions using following info: // http://stackoverflow.com/questions/6252812/what-does-the-aw-flag-in-the-section-attribute-mean #if !BOOST_OS_MACOS && !BOOST_OS_IOS /*! * \brief Macro that puts symbol to a specific section. On MacOS all the sections are put into "__DATA" segment. * \param SectionName Name of the section. Must be a valid C identifier without quotes not longer than 8 bytes. * \param Permissions Can be "read" or "write" (without quotes!). */ #define BOOST_DLL_SECTION(SectionName, Permissions) \ BOOST_STATIC_ASSERT_MSG( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ __attribute__ ((section (#SectionName))) \ /**/ #else // #if !BOOST_OS_MACOS && !BOOST_OS_IOS #define BOOST_DLL_SECTION(SectionName, Permissions) \ BOOST_STATIC_ASSERT_MSG( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ __attribute__ ((section ( "__DATA," #SectionName))) \ /**/ #endif // #if #if !BOOST_OS_MACOS && !BOOST_OS_IOS #endif // #if BOOST_COMP_MSVC // Alias - is just a variable that pointers to original data // // A few attempts were made to avoid additional indirection: // 1) // // Does not work on Windows, work on Linux // extern "C" BOOST_SYMBOL_EXPORT void AliasName() { // reinterpret_cast<void (*)()>(Function)(); // } // // 2) // // Does not work on Linux (changes permissions of .text section and produces incorrect DSO) // extern "C" BOOST_SYMBOL_EXPORT void* __attribute__ ((section(".text#"))) // func_ptr = *reinterpret_cast<std::ptrdiff_t**>(&foo::bar); // // 3) // requires mangled name of `Function` // // AliasName() __attribute__ ((weak, alias ("Function"))) // // // hard to use // `#pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue")` /*! * \brief Makes an alias name for exported function or variable. * * This macro is useful in cases of long mangled C++ names. For example some `void boost::foo(std::string)` * function name will change to something like `N5boostN3foosE` after mangling. * Importing function by `N5boostN3foosE` name does not looks user friendly, especially assuming the fact * that different compilers have different mangling schemes. AliasName is the name that won't be mangled * and can be used as a portable import name. * * * Can be used in any namespace, including global. FunctionOrVar must be fully qualified, * so that address of it could be taken. Multiple different aliases for a single variable/function * are allowed. * * Make sure that AliasNames are unique per library/executable. Functions or variables * in global namespace must not have names same as AliasNames. * * Same AliasName in different translation units must point to the same FunctionOrVar. * * Puts all the aliases into the \b "boostdll" read only section of the binary. Equal to * \forcedmacrolink{BOOST_DLL_ALIAS_SECTIONED}(FunctionOrVar, AliasName, boostdll). * * \param FunctionOrVar Function or variable for which an alias must be made. * \param AliasName Name of the alias. Must be a valid C identifier. * * \b Example: * \code * namespace foo { * void bar(std::string&); * * BOOST_DLL_ALIAS(foo::bar, foo_bar) * } * * BOOST_DLL_ALIAS(foo::bar, foo_bar_another_alias_name) * \endcode * * \b See: \forcedmacrolink{BOOST_DLL_ALIAS_SECTIONED} for making alias in a specific section. */ #define BOOST_DLL_ALIAS(FunctionOrVar, AliasName) \ BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, boostdll) \ /**/ #if ((BOOST_COMP_GNUC && BOOST_OS_WINDOWS) || BOOST_OS_ANDROID || BOOST_COMP_IBM || defined(BOOST_DLL_FORCE_NO_WEAK_EXPORTS)) \ && !defined(BOOST_DLL_FORCE_ALIAS_INSTANTIATION) && !defined(BOOST_DLL_DOXYGEN) #define BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, SectionName) \ namespace _autoaliases { \ extern "C" BOOST_SYMBOL_EXPORT const void *AliasName; \ } /* namespace _autoaliases */ \ /**/ #define BOOST_DLL_AUTO_ALIAS(FunctionOrVar) \ namespace _autoaliases { \ extern "C" BOOST_SYMBOL_EXPORT const void *FunctionOrVar; \ } /* namespace _autoaliases */ \ /**/ #else // Note: we can not use `aggressive_ptr_cast` here, because in that case GCC applies // different permissions to the section and it causes Segmentation fault. // Note: we can not use `boost::addressof()` here, because in that case GCC // may optimize away the FunctionOrVar instance and we'll get a pointer to unexisting symbol. /*! * \brief Same as \forcedmacrolink{BOOST_DLL_ALIAS} but puts alias name into the user specified section. * * \param FunctionOrVar Function or variable for which an alias must be made. * \param AliasName Name of the alias. Must be a valid C identifier. * \param SectionName Name of the section. Must be a valid C identifier without quotes not longer than 8 bytes. * * \b Example: * \code * namespace foo { * void bar(std::string&); * * BOOST_DLL_ALIAS_SECTIONED(foo::bar, foo_bar, sect_1) // section "sect_1" now exports "foo_bar" * } * \endcode * */ #define BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, SectionName) \ namespace _autoaliases { \ extern "C" BOOST_SYMBOL_EXPORT const void *AliasName; \ BOOST_DLL_SECTION(SectionName, read) BOOST_DLL_SELECTANY \ const void * AliasName = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>( \ &FunctionOrVar \ )); \ } /* namespace _autoaliases */ \ /**/ /*! * \brief Exports variable or function with unmangled alias name. * * This macro is useful in cases of long mangled C++ names. For example some `void boost::foo(std::string)` * function name will change to something like `N5boostN3foosE` after mangling. * Importing function by `N5boostN3foosE` name does not looks user friendly, especially assuming the fact * that different compilers have different mangling schemes.* * * Must be used in scope where FunctionOrVar declared. FunctionOrVar must be a valid C name, which means that * it must not contain `::`. * * Functions or variables * in global namespace must not have names same as FunctionOrVar. * * Puts all the aliases into the \b "boostdll" read only section of the binary. Almost same as * \forcedmacrolink{BOOST_DLL_ALIAS}(FunctionOrVar, FunctionOrVar). * * \param FunctionOrVar Function or variable for which an unmangled alias must be made. * * \b Example: * \code * namespace foo { * void bar(std::string&); * BOOST_DLL_AUTO_ALIAS(bar) * } * * \endcode * * \b See: \forcedmacrolink{BOOST_DLL_ALIAS} for making an alias with different names. */ #define BOOST_DLL_AUTO_ALIAS(FunctionOrVar) \ namespace _autoaliases { \ BOOST_DLL_SELECTANY const void * dummy_ ## FunctionOrVar \ = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>( \ &FunctionOrVar \ )); \ extern "C" BOOST_SYMBOL_EXPORT const void *FunctionOrVar; \ BOOST_DLL_SECTION(boostdll, read) BOOST_DLL_SELECTANY \ const void * FunctionOrVar = dummy_ ## FunctionOrVar; \ } /* namespace _autoaliases */ \ /**/ #endif }} // namespace boost::dll #endif // BOOST_DLL_ALIAS_HPP config.hpp 0000644 00000004613 15125237303 0006527 0 ustar 00 // Copyright 2018-2019 Antony Polukhin. // // 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) /// \file boost/dll/config.hpp /// \brief Imports filesystem, error_code, errc, system_error, make_error_code from Boost or C++17 into `boost::dll::fs` namespace. #ifndef BOOST_DLL_DETAIL_CONFIG_HPP #define BOOST_DLL_DETAIL_CONFIG_HPP #include <boost/config.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #ifdef BOOST_DLL_DOXYGEN /// Define this macro to make Boost.DLL use C++17's std::filesystem::path, std::system_error and std::error_code. #define BOOST_DLL_USE_STD_FS BOOST_DLL_USE_STD_FS /// This namespace contains aliases to the Boost or C++17 classes. Aliases are configured using BOOST_DLL_USE_STD_FS macro. namespace boost { namespace dll { namespace fs { /// Alias to `std::filesystem::path` if \forcedmacrolink{BOOST_DLL_USE_STD_FS} is defined by user. /// Alias to `boost::filesystem::path` otherwise. using path = std::conditional_t<BOOST_DLL_USE_STD_FS, std::filesystem::path, boost::filesystem::path>; /// Alias to `std::error_code` if \forcedmacrolink{BOOST_DLL_USE_STD_FS} is defined by user. /// boost::system::error_code otherwise. using error_code = std::conditional_t<BOOST_DLL_USE_STD_FS, std::error_code, boost::system::error_code>; /// Alias to `std::system_error` if \forcedmacrolink{BOOST_DLL_USE_STD_FS} is defined by user. /// Alias to `boost::system::system_error` otherwise. using system_error = std::conditional_t<BOOST_DLL_USE_STD_FS, std::system_error, boost::system::system_error>; }}} #endif #ifdef BOOST_DLL_USE_STD_FS #include <filesystem> #include <system_error> namespace boost { namespace dll { namespace fs { using namespace std::filesystem; using std::error_code; using std::system_error; using std::make_error_code; using std::errc; using std::system_category; }}} #else // BOOST_DLL_USE_STD_FS #include <boost/filesystem/path.hpp> #include <boost/filesystem/operations.hpp> #include <boost/system/error_code.hpp> namespace boost { namespace dll { namespace fs { using namespace boost::filesystem; using boost::system::error_code; using boost::system::system_error; using boost::system::errc::make_error_code; namespace errc = boost::system::errc; using boost::system::system_category; }}} #endif // BOOST_DLL_USE_STD_FS #endif // BOOST_DLL_DETAIL_PUSH_OPTIONS_HPP runtime_symbol_info.hpp 0000644 00000021617 15125237303 0011350 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_RUNTIME_SYMBOL_INFO_HPP #define BOOST_DLL_RUNTIME_SYMBOL_INFO_HPP #include <boost/dll/config.hpp> #include <boost/predef/os.h> #include <boost/predef/compiler/visualc.h> #include <boost/dll/detail/aggressive_ptr_cast.hpp> #if BOOST_OS_WINDOWS # include <boost/winapi/dll.hpp> # include <boost/dll/detail/windows/path_from_handle.hpp> #else # include <dlfcn.h> # include <boost/dll/detail/posix/program_location_impl.hpp> #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif /// \file boost/dll/runtime_symbol_info.hpp /// \brief Provides methods for getting acceptable by boost::dll::shared_library location of symbol, source line or program. namespace boost { namespace dll { #if BOOST_OS_WINDOWS namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code& ec) { return boost::dll::detail::path_from_handle(NULL, ec); } } // namespace detail #endif /*! * On success returns full path and name to the binary object that holds symbol pointed by ptr_to_symbol. * * \param ptr_to_symbol Pointer to symbol which location is to be determined. * \param ec Variable that will be set to the result of the operation. * \return Path to the binary object that holds symbol or empty path in case error. * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}. * * \b Examples: * \code * int main() { * dll::symbol_location_ptr(std::set_terminate(0)); // returns "/some/path/libmy_terminate_handler.so" * dll::symbol_location_ptr(::signal(SIGSEGV, SIG_DFL)); // returns "/some/path/libmy_symbol_handler.so" * } * \endcode */ template <class T> inline boost::dll::fs::path symbol_location_ptr(T ptr_to_symbol, boost::dll::fs::error_code& ec) { BOOST_STATIC_ASSERT_MSG(boost::is_pointer<T>::value, "boost::dll::symbol_location_ptr works only with pointers! `ptr_to_symbol` must be a pointer"); boost::dll::fs::path ret; if (!ptr_to_symbol) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_address ); return ret; } ec.clear(); const void* ptr = boost::dll::detail::aggressive_ptr_cast<const void*>(ptr_to_symbol); #if BOOST_OS_WINDOWS boost::winapi::MEMORY_BASIC_INFORMATION_ mbi; if (!boost::winapi::VirtualQuery(ptr, &mbi, sizeof(mbi))) { ec = boost::dll::detail::last_error_code(); return ret; } return boost::dll::detail::path_from_handle(reinterpret_cast<boost::winapi::HMODULE_>(mbi.AllocationBase), ec); #else Dl_info info; // Some of the libc headers miss `const` in `dladdr(const void*, Dl_info*)` const int res = dladdr(const_cast<void*>(ptr), &info); if (res) { ret = info.dli_fname; } else { boost::dll::detail::reset_dlerror(); ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_address ); } return ret; #endif } //! \overload symbol_location_ptr(const void* ptr_to_symbol, boost::dll::fs::error_code& ec) template <class T> inline boost::dll::fs::path symbol_location_ptr(T ptr_to_symbol) { boost::dll::fs::path ret; boost::dll::fs::error_code ec; ret = boost::dll::symbol_location_ptr(ptr_to_symbol, ec); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::symbol_location_ptr(T ptr_to_symbol) failed"); } return ret; } /*! * On success returns full path and name of the binary object that holds symbol. * * \tparam T Type of the symbol, must not be explicitly specified. * \param symbol Symbol which location is to be determined. * \param ec Variable that will be set to the result of the operation. * \return Path to the binary object that holds symbol or empty path in case error. * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}. * * \b Examples: * \code * int var; * void foo() {} * * int main() { * dll::symbol_location(var); // returns program location * dll::symbol_location(foo); // returns program location * dll::symbol_location(std::cerr); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" * dll::symbol_location(std::placeholders::_1); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" * dll::symbol_location(std::puts); // returns location of libc: "/lib/x86_64-linux-gnu/libc.so.6" * } * \endcode */ template <class T> inline boost::dll::fs::path symbol_location(const T& symbol, boost::dll::fs::error_code& ec) { ec.clear(); return boost::dll::symbol_location_ptr( boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)), ec ); } #if BOOST_COMP_MSVC < BOOST_VERSION_NUMBER(14,0,0) // Without this MSVC 7.1 fails with: // ..\boost\dll\runtime_symbol_info.hpp(133) : error C2780: 'filesystem::path dll::symbol_location(const T &)' : expects 1 arguments - 2 provided template <class T> inline boost::dll::fs::path symbol_location(const T& symbol, const char* /*workaround*/ = 0) #else //! \overload symbol_location(const T& symbol, boost::dll::fs::error_code& ec) template <class T> inline boost::dll::fs::path symbol_location(const T& symbol) #endif { boost::dll::fs::path ret; boost::dll::fs::error_code ec; ret = boost::dll::symbol_location_ptr( boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)), ec ); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::symbol_location(const T& symbol) failed"); } return ret; } /// @cond // We have anonymous namespace here to make sure that `this_line_location()` method is instantiated in // current translation unit and is not shadowed by instantiations from other units. namespace { /// @endcond /*! * On success returns full path and name of the binary object that holds the current line of code * (the line in which the `this_line_location()` method was called). * * \param ec Variable that will be set to the result of the operation. * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}. */ static inline boost::dll::fs::path this_line_location(boost::dll::fs::error_code& ec) { typedef boost::dll::fs::path(func_t)(boost::dll::fs::error_code& ); func_t& f = this_line_location; return boost::dll::symbol_location(f, ec); } //! \overload this_line_location(boost::dll::fs::error_code& ec) static inline boost::dll::fs::path this_line_location() { boost::dll::fs::path ret; boost::dll::fs::error_code ec; ret = this_line_location(ec); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::this_line_location() failed"); } return ret; } /// @cond } // anonymous namespace /// @endcond /*! * On success returns full path and name of the currently running program (the one which contains the `main()` function). * * Return value can be used as a parameter for shared_library. See Tutorial "Linking plugin into the executable" * for usage example. Flag '-rdynamic' must be used when linking the plugin into the executable * on Linux OS. * * \param ec Variable that will be set to the result of the operation. * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}. */ inline boost::dll::fs::path program_location(boost::dll::fs::error_code& ec) { ec.clear(); return boost::dll::detail::program_location_impl(ec); } //! \overload program_location(boost::dll::fs::error_code& ec) { inline boost::dll::fs::path program_location() { boost::dll::fs::path ret; boost::dll::fs::error_code ec; ret = boost::dll::detail::program_location_impl(ec); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::program_location() failed"); } return ret; } }} // namespace boost::dll #endif // BOOST_DLL_RUNTIME_SYMBOL_INFO_HPP shared_library_load_mode.hpp 0000644 00000017734 15125237303 0012267 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_SHARED_LIBRARY_MODE_HPP #define BOOST_DLL_SHARED_LIBRARY_MODE_HPP #include <boost/dll/config.hpp> #include <boost/predef/os.h> #include <boost/predef/library/c.h> #if BOOST_OS_WINDOWS # include <boost/winapi/dll.hpp> #else # include <dlfcn.h> #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif /// \file boost/dll/shared_library_load_mode.hpp /// \brief Contains only the boost::dll::load_mode::type enum and operators related to it. namespace boost { namespace dll { namespace load_mode { /*! Library load modes. * * Each of system family provides own modes. Flags not supported by a particular platform will be silently ignored. * * For a detailed description of platform specific options see: * <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx">Windows specific options</a>, * <a href="http://pubs.opengroup.org/onlinepubs/000095399/functions/dlopen.html">POSIX specific options</a>. * */ enum type { #ifdef BOOST_DLL_DOXYGEN /*! * Default open mode. See the \b Default: comments below to find out the flags that are enabled by default. */ default_mode, /*! * \b Platforms: Windows * * \b Default: disabled * * If this value is used, and the executable module is a DLL, the system does * not call DllMain for process and thread initialization and termination. * Also, the system does not load additional executable modules that are * referenced by the specified module. * * Note Do not use this value; it is provided only for backward compatibility. * If you are planning to access only data or resources in the DLL, use * LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE or LOAD_LIBRARY_AS_IMAGE_RESOURCE * or both. */ dont_resolve_dll_references, /*! * \b Platforms: Windows * * \b Default: disabled * * If this value is used, the system does not check AppLocker rules or * apply Software Restriction Policies for the DLL. */ load_ignore_code_authz_level, /*! * \b Platforms: Windows * * \b Default: disabled * * If this value is used and lpFileName specifies an absolute path, * the system uses the alternate file search strategy. * * This value cannot be combined with any LOAD_LIBRARY_SEARCH flag. */ load_with_altered_search_path, /*! * \b Platforms: POSIX * * \b Default: enabled * * Relocations shall be performed at an implementation-defined time, ranging * from the time of the dlopen() call until the first reference to a given * symbol occurs. * * Specifying RTLD_LAZY should improve performance on implementations * supporting dynamic symbol binding as a process may not reference all of * the functions in any given object. And, for systems supporting dynamic * symbol resolution for normal process execution, this behavior mimics * the normal handling of process execution. */ rtld_lazy, /*! * \b Platforms: POSIX * * \b Default: disabled * * All necessary relocations shall be performed when the object is first * loaded. This may waste some processing if relocations are performed for * functions that are never referenced. This behavior may be useful for * plugins that need to know as soon as an object is loaded that all * symbols referenced during execution are available. */ rtld_now, /*! * \b Platforms: POSIX * * \b Default: disabled * * The object's symbols shall be made available for the relocation * processing of any other object. In addition, symbol lookup using * dlopen(0, mode) and an associated dlsym() allows objects loaded * with this mode to be searched. */ rtld_global, /*! * \b Platforms: POSIX * * \b Default: enabled * * The object's symbols shall not be made available for the relocation * processing of any other object. * * This is a default Windows behavior that can not be changed. */ rtld_local, /*! * \b Platforms: POSIX (requires glibc >= 2.3.4) * * \b Default: disabled * * The object will use its own symbols in preference to global symbols * with the same name contained in libraries that have already been loaded. * This flag is not specified in POSIX.1-2001. */ rtld_deepbind, /*! * \b Platforms: Windows, POSIX * * \b Default: disabled * * Append a platform specific extension and prefix to shared library filename before trying to load it. * If load attempt fails, try to load with exactly specified name. * * \b Example: * \code * // Opens `./my_plugins/plugin1.dll` on Windows, `./my_plugins/libplugin1.so` on Linux, `./my_plugins/libplugin1.dylib` on MacOS. * // If that fails, loads `./my_plugins/plugin1` * boost::dll::shared_library lib("./my_plugins/plugin1", load_mode::append_decorations); * \endcode */ append_decorations, /*! * \b Platforms: Windows, POSIX * * \b Default: disabled * * Allow loading from system folders if path to library contains no parent path. */ search_system_folders #elif BOOST_OS_WINDOWS default_mode = 0, dont_resolve_dll_references = boost::winapi::DONT_RESOLVE_DLL_REFERENCES_, load_ignore_code_authz_level = boost::winapi::LOAD_IGNORE_CODE_AUTHZ_LEVEL_, load_with_altered_search_path = boost::winapi::LOAD_WITH_ALTERED_SEARCH_PATH_, rtld_lazy = 0, rtld_now = 0, rtld_global = 0, rtld_local = 0, rtld_deepbind = 0, append_decorations = 0x00800000, search_system_folders = (append_decorations << 1) #else default_mode = 0, dont_resolve_dll_references = 0, load_ignore_code_authz_level = 0, load_with_altered_search_path = 0, rtld_lazy = RTLD_LAZY, rtld_now = RTLD_NOW, rtld_global = RTLD_GLOBAL, rtld_local = RTLD_LOCAL, #if BOOST_LIB_C_GNU < BOOST_VERSION_NUMBER(2,3,4) rtld_deepbind = 0, #else rtld_deepbind = RTLD_DEEPBIND, #endif append_decorations = 0x00800000, search_system_folders = (append_decorations << 1) #endif }; /// Free operators for load_mode::type flag manipulation. BOOST_CONSTEXPR inline type operator|(type left, type right) BOOST_NOEXCEPT { return static_cast<type>( static_cast<unsigned int>(left) | static_cast<unsigned int>(right) ); } BOOST_CXX14_CONSTEXPR inline type& operator|=(type& left, type right) BOOST_NOEXCEPT { left = left | right; return left; } BOOST_CONSTEXPR inline type operator&(type left, type right) BOOST_NOEXCEPT { return static_cast<type>( static_cast<unsigned int>(left) & static_cast<unsigned int>(right) ); } BOOST_CXX14_CONSTEXPR inline type& operator&=(type& left, type right) BOOST_NOEXCEPT { left = left & right; return left; } BOOST_CONSTEXPR inline type operator^(type left, type right) BOOST_NOEXCEPT { return static_cast<type>( static_cast<unsigned int>(left) ^ static_cast<unsigned int>(right) ); } BOOST_CXX14_CONSTEXPR inline type& operator^=(type& left, type right) BOOST_NOEXCEPT { left = left ^ right; return left; } BOOST_CONSTEXPR inline type operator~(type left) BOOST_NOEXCEPT { return static_cast<type>( ~static_cast<unsigned int>(left) ); } }}} // boost::dll::load_mode #endif // BOOST_DLL_SHARED_LIBRARY_MODE_HPP detail/elf_info.hpp 0000644 00000025511 15125237303 0010305 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_DETAIL_POSIX_ELF_INFO_HPP #define BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP #include <boost/dll/config.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #include <cstring> #include <fstream> #include <limits> #include <boost/cstdint.hpp> #include <boost/throw_exception.hpp> namespace boost { namespace dll { namespace detail { template <class AddressOffsetT> struct Elf_Ehdr_template { unsigned char e_ident[16]; /* Magic number and other info */ boost::uint16_t e_type; /* Object file type */ boost::uint16_t e_machine; /* Architecture */ boost::uint32_t e_version; /* Object file version */ AddressOffsetT e_entry; /* Entry point virtual address */ AddressOffsetT e_phoff; /* Program header table file offset */ AddressOffsetT e_shoff; /* Section header table file offset */ boost::uint32_t e_flags; /* Processor-specific flags */ boost::uint16_t e_ehsize; /* ELF header size in bytes */ boost::uint16_t e_phentsize; /* Program header table entry size */ boost::uint16_t e_phnum; /* Program header table entry count */ boost::uint16_t e_shentsize; /* Section header table entry size */ boost::uint16_t e_shnum; /* Section header table entry count */ boost::uint16_t e_shstrndx; /* Section header string table index */ }; typedef Elf_Ehdr_template<boost::uint32_t> Elf32_Ehdr_; typedef Elf_Ehdr_template<boost::uint64_t> Elf64_Ehdr_; template <class AddressOffsetT> struct Elf_Shdr_template { boost::uint32_t sh_name; /* Section name (string tbl index) */ boost::uint32_t sh_type; /* Section type */ AddressOffsetT sh_flags; /* Section flags */ AddressOffsetT sh_addr; /* Section virtual addr at execution */ AddressOffsetT sh_offset; /* Section file offset */ AddressOffsetT sh_size; /* Section size in bytes */ boost::uint32_t sh_link; /* Link to another section */ boost::uint32_t sh_info; /* Additional section information */ AddressOffsetT sh_addralign; /* Section alignment */ AddressOffsetT sh_entsize; /* Entry size if section holds table */ }; typedef Elf_Shdr_template<boost::uint32_t> Elf32_Shdr_; typedef Elf_Shdr_template<boost::uint64_t> Elf64_Shdr_; template <class AddressOffsetT> struct Elf_Sym_template; template <> struct Elf_Sym_template<boost::uint32_t> { typedef boost::uint32_t AddressOffsetT; boost::uint32_t st_name; /* Symbol name (string tbl index) */ AddressOffsetT st_value; /* Symbol value */ AddressOffsetT st_size; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ boost::uint16_t st_shndx; /* Section index */ }; template <> struct Elf_Sym_template<boost::uint64_t> { typedef boost::uint64_t AddressOffsetT; boost::uint32_t st_name; /* Symbol name (string tbl index) */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ boost::uint16_t st_shndx; /* Section index */ AddressOffsetT st_value; /* Symbol value */ AddressOffsetT st_size; /* Symbol size */ }; typedef Elf_Sym_template<boost::uint32_t> Elf32_Sym_; typedef Elf_Sym_template<boost::uint64_t> Elf64_Sym_; template <class AddressOffsetT> class elf_info { typedef boost::dll::detail::Elf_Ehdr_template<AddressOffsetT> header_t; typedef boost::dll::detail::Elf_Shdr_template<AddressOffsetT> section_t; typedef boost::dll::detail::Elf_Sym_template<AddressOffsetT> symbol_t; BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_SYMTAB_ = 2); BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_STRTAB_ = 3); BOOST_STATIC_CONSTANT(unsigned char, STB_LOCAL_ = 0); /* Local symbol */ BOOST_STATIC_CONSTANT(unsigned char, STB_GLOBAL_ = 1); /* Global symbol */ BOOST_STATIC_CONSTANT(unsigned char, STB_WEAK_ = 2); /* Weak symbol */ /* Symbol visibility specification encoded in the st_other field. */ BOOST_STATIC_CONSTANT(unsigned char, STV_DEFAULT_ = 0); /* Default symbol visibility rules */ BOOST_STATIC_CONSTANT(unsigned char, STV_INTERNAL_ = 1); /* Processor specific hidden class */ BOOST_STATIC_CONSTANT(unsigned char, STV_HIDDEN_ = 2); /* Sym unavailable in other modules */ BOOST_STATIC_CONSTANT(unsigned char, STV_PROTECTED_ = 3); /* Not preemptible, not exported */ public: static bool parsing_supported(std::ifstream& fs) { const unsigned char magic_bytes[5] = { 0x7f, 'E', 'L', 'F', sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 1 : 2 }; unsigned char ch; fs.seekg(0); for (std::size_t i = 0; i < sizeof(magic_bytes); ++i) { fs >> ch; if (ch != magic_bytes[i]) { return false; } } return true; } static std::vector<std::string> sections(std::ifstream& fs) { std::vector<std::string> ret; std::vector<char> names; sections_names_raw(fs, names); const char* name_begin = &names[0]; const char* const name_end = name_begin + names.size(); ret.reserve(header(fs).e_shnum); do { ret.push_back(name_begin); name_begin += ret.back().size() + 1; } while (name_begin != name_end); return ret; } private: template <class Integer> static void checked_seekg(std::ifstream& fs, Integer pos) { /* TODO: use cmp_less, cmp_greater if ((std::numeric_limits<std::streamoff>::max)() < pos) { boost::throw_exception(std::runtime_error("Integral overflow while getting info from ELF file")); } if ((std::numeric_limits<std::streamoff>::min)() > pos){ boost::throw_exception(std::runtime_error("Integral underflow while getting info from ELF file")); } */ fs.seekg(static_cast<std::streamoff>(pos)); } template <class T> static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) { fs.read(reinterpret_cast<char*>(&value), size); } static header_t header(std::ifstream& fs) { header_t elf; fs.seekg(0); read_raw(fs, elf); return elf; } static void sections_names_raw(std::ifstream& fs, std::vector<char>& sections) { const header_t elf = header(fs); section_t section_names_section; checked_seekg(fs, elf.e_shoff + elf.e_shstrndx * sizeof(section_t)); read_raw(fs, section_names_section); sections.resize(static_cast<std::size_t>(section_names_section.sh_size)); checked_seekg(fs, section_names_section.sh_offset); read_raw(fs, sections[0], static_cast<std::size_t>(section_names_section.sh_size)); } static void symbols_text(std::ifstream& fs, std::vector<symbol_t>& symbols, std::vector<char>& text) { const header_t elf = header(fs); checked_seekg(fs, elf.e_shoff); for (std::size_t i = 0; i < elf.e_shnum; ++i) { section_t section; read_raw(fs, section); if (section.sh_type == SHT_SYMTAB_) { symbols.resize(static_cast<std::size_t>(section.sh_size / sizeof(symbol_t))); const std::ifstream::pos_type pos = fs.tellg(); checked_seekg(fs, section.sh_offset); read_raw(fs, symbols[0], static_cast<std::size_t>(section.sh_size - (section.sh_size % sizeof(symbol_t))) ); checked_seekg(fs, pos); } else if (section.sh_type == SHT_STRTAB_) { text.resize(static_cast<std::size_t>(section.sh_size)); const std::ifstream::pos_type pos = fs.tellg(); checked_seekg(fs, section.sh_offset); read_raw(fs, text[0], static_cast<std::size_t>(section.sh_size)); checked_seekg(fs, pos); } } } static bool is_visible(const symbol_t& sym) BOOST_NOEXCEPT { // `(sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size` check also workarounds the // GCC's issue https://sourceware.org/bugzilla/show_bug.cgi?id=13621 return (sym.st_other & 0x03) == STV_DEFAULT_ && (sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size; } public: static std::vector<std::string> symbols(std::ifstream& fs) { std::vector<std::string> ret; std::vector<symbol_t> symbols; std::vector<char> text; symbols_text(fs, symbols, text); ret.reserve(symbols.size()); for (std::size_t i = 0; i < symbols.size(); ++i) { if (is_visible(symbols[i])) { ret.push_back(&text[0] + symbols[i].st_name); if (ret.back().empty()) { ret.pop_back(); // Do not show empty names } } } return ret; } static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) { std::vector<std::string> ret; std::size_t index = 0; std::size_t ptrs_in_section_count = 0; { std::vector<char> names; sections_names_raw(fs, names); const header_t elf = header(fs); for (; index < elf.e_shnum; ++index) { section_t section; checked_seekg(fs, elf.e_shoff + index * sizeof(section_t)); read_raw(fs, section); if (!std::strcmp(&names[0] + section.sh_name, section_name)) { if (!section.sh_entsize) { section.sh_entsize = 1; } ptrs_in_section_count = static_cast<std::size_t>(section.sh_size / section.sh_entsize); break; } } } std::vector<symbol_t> symbols; std::vector<char> text; symbols_text(fs, symbols, text); if (ptrs_in_section_count < symbols.size()) { ret.reserve(ptrs_in_section_count); } else { ret.reserve(symbols.size()); } for (std::size_t i = 0; i < symbols.size(); ++i) { if (symbols[i].st_shndx == index && is_visible(symbols[i])) { ret.push_back(&text[0] + symbols[i].st_name); if (ret.back().empty()) { ret.pop_back(); // Do not show empty names } } } return ret; } }; typedef elf_info<boost::uint32_t> elf_info32; typedef elf_info<boost::uint64_t> elf_info64; }}} // namespace boost::dll::detail #endif // BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP detail/ctor_dtor.hpp 0000644 00000014761 15125237303 0010530 0 ustar 00 // Copyright 2016 Klemens Morgenstern, Antony Polukhin // // 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) // For more information, see http://www.boost.org #ifndef BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ #define BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ #include <boost/dll/config.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #include <boost/dll/detail/aggressive_ptr_cast.hpp> #include <boost/dll/detail/get_mem_fn_type.hpp> #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows # include <boost/dll/detail/demangling/msvc.hpp> #else # include <boost/dll/detail/demangling/itanium.hpp> #endif namespace boost { namespace dll { namespace detail { /*! * This class stores a constructor. * * In some compilers there are several constructors in code, which may include an allocating one. * This can be used if the imported class shall be put on the heap, which is why the class provied both types. */ template<typename Signature> struct constructor; template<typename Class, typename ...Args> struct constructor<Class(Args...)> { typedef typename detail::get_mem_fn_type<Class, void(Args...)>::mem_fn standard_t; typedef Class*(*allocating_t)(Args...); //! The standard, i.e. not allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_standard instead. standard_t standard; //! The allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_allocating instead. allocating_t allocating; //! Call the standard constructor void call_standard (Class * const ptr, Args...args){ (ptr->*standard)(static_cast<Args>(args)...); } //! Call the deleting destructor Class * call_allocating(Args...args){ return allocating(static_cast<Args>(args)...); } //! True if a allocating constructor could be loaded. bool has_allocating() const { return allocating != nullptr; } //! True if a standard constructor could be loaded. bool has_standard() const { return standard != nullptr; } //! False if neither the allocating nor the standard constructor is available. bool is_empty() const { return (allocating == nullptr) && (standard == nullptr) ; } constructor() = delete; constructor(const constructor &) = default; explicit constructor(standard_t standard, allocating_t allocating = nullptr) : standard(standard) , allocating(allocating) {} }; template <typename Class> struct destructor { #if !defined(_WIN32) typedef void(*type)(Class* const); #elif !defined(_WIN64) typedef void(__thiscall * type)(Class* const); #else typedef void(__cdecl * type)(Class* const); #endif typedef type standard_t; typedef type deleting_t; //! The standard, i.e. not deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_standard instead. standard_t standard; //! The deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_deallocating instead. deleting_t deleting; //! Call the standard constructor void call_standard(Class * const ptr){ standard(ptr); } //! Call the deleting destructor void call_deleting(Class * const ptr){ deleting(ptr); } //! True if a deleting destructor could be loaded. bool has_deleting() const { return deleting != nullptr; } //! True if a standard destructor could be loaded. bool has_standard() const { return standard != nullptr; } //! False if neither the deleting nor the standard destructor is available. bool is_empty() const { return (deleting == nullptr) && (standard == nullptr) ; } destructor() = delete; //! Copy destructor. destructor(const destructor &) = default; //! Construct it from both the standard destructor and the allocating destructor explicit destructor(const standard_t &standard, const deleting_t &deleting = nullptr) : standard(standard) , deleting(deleting) {} }; #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows template<typename Signature, typename Lib> constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) { typedef typename constructor<Signature>::standard_t standard_t; standard_t ctor = lib.template get<standard_t>(ct); return constructor<Signature>(ctor); } template<typename Class, typename Lib> destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) { typedef typename destructor<Class>::standard_t standard_t; //@apolukhin That does NOT work this way with MSVC-14 x32 via memcpy. The x64 is different. //standard_t dtor = &lib.template get< typename boost::remove_pointer<standard_t>::type >(dt); void * buf = &lib.template get<unsigned char>(dt); standard_t dtor; std::memcpy(&dtor, &buf, sizeof(dtor)); return destructor<Class>(dtor); } #else template<typename Signature, typename Lib> constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) { typedef typename constructor<Signature>::standard_t stand; typedef typename constructor<Signature>::allocating_t alloc; stand s = nullptr; alloc a = nullptr; //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor if (!ct.C1.empty()) { //the only way this works on mingw/win. //For some reason there is always an 0xA in the following poniter, which screws with the this pointer. void *buf = &lib.template get<unsigned char>(ct.C1); std::memcpy(&s, &buf, sizeof(void*)); } if (!ct.C3.empty()) { void *buf = &lib.template get<unsigned char>(ct.C3); std::memcpy(&a, &buf, sizeof(void*)); } return constructor<Signature>(s,a); } template<typename Class, typename Lib> destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) { typedef typename destructor<Class>::standard_t stand; typedef typename destructor<Class>::deleting_t delet; stand s = nullptr; delet d = nullptr; //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor if (!dt.D1.empty()) { s = &lib.template get< typename boost::remove_pointer<stand>::type >(dt.D1); } if (!dt.D0.empty()) { d = &lib.template get< typename boost::remove_pointer<delet>::type >(dt.D0); } return destructor<Class>(s,d); } #endif }}} // namespace boost::dll::detail #endif /* BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ */ detail/pe_info.hpp 0000644 00000040621 15125237303 0010142 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2020 Antony Polukhin. // // 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_DLL_DETAIL_WINDOWS_PE_INFO_HPP #define BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP #include <boost/dll/config.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #include <cstring> #include <fstream> #include <string> // for std::getline #include <boost/assert.hpp> #include <boost/cstdint.hpp> namespace boost { namespace dll { namespace detail { // reference: // http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/ // http://msdn.microsoft.com/en-us/magazine/ms809762.aspx // http://msdn.microsoft.com/en-us/magazine/cc301808.aspx // // Basic Windows typedefs. We can not use <boost/winapi/basic_types.hpp> header // because that header must be included only on Windows platform typedef unsigned char BYTE_; typedef unsigned short WORD_; typedef boost::uint32_t DWORD_; typedef boost::int32_t LONG_; typedef boost::uint32_t ULONG_; typedef boost::int64_t LONGLONG_; typedef boost::uint64_t ULONGLONG_; struct IMAGE_DOS_HEADER_ { // 32/64 independent header boost::dll::detail::WORD_ e_magic; // Magic number boost::dll::detail::WORD_ e_cblp; // Bytes on last page of file boost::dll::detail::WORD_ e_cp; // Pages in file boost::dll::detail::WORD_ e_crlc; // Relocations boost::dll::detail::WORD_ e_cparhdr; // Size of header in paragraphs boost::dll::detail::WORD_ e_minalloc; // Minimum extra paragraphs needed boost::dll::detail::WORD_ e_maxalloc; // Maximum extra paragraphs needed boost::dll::detail::WORD_ e_ss; // Initial (relative) SS value boost::dll::detail::WORD_ e_sp; // Initial SP value boost::dll::detail::WORD_ e_csum; // Checksum boost::dll::detail::WORD_ e_ip; // Initial IP value boost::dll::detail::WORD_ e_cs; // Initial (relative) CS value boost::dll::detail::WORD_ e_lfarlc; // File address of relocation table boost::dll::detail::WORD_ e_ovno; // Overlay number boost::dll::detail::WORD_ e_res[4]; // Reserved words boost::dll::detail::WORD_ e_oemid; // OEM identifier (for e_oeminfo) boost::dll::detail::WORD_ e_oeminfo; // OEM information; e_oemid specific boost::dll::detail::WORD_ e_res2[10]; // Reserved words boost::dll::detail::LONG_ e_lfanew; // File address of new exe header }; struct IMAGE_FILE_HEADER_ { // 32/64 independent header boost::dll::detail::WORD_ Machine; boost::dll::detail::WORD_ NumberOfSections; boost::dll::detail::DWORD_ TimeDateStamp; boost::dll::detail::DWORD_ PointerToSymbolTable; boost::dll::detail::DWORD_ NumberOfSymbols; boost::dll::detail::WORD_ SizeOfOptionalHeader; boost::dll::detail::WORD_ Characteristics; }; struct IMAGE_DATA_DIRECTORY_ { // 32/64 independent header boost::dll::detail::DWORD_ VirtualAddress; boost::dll::detail::DWORD_ Size; }; struct IMAGE_EXPORT_DIRECTORY_ { // 32/64 independent header boost::dll::detail::DWORD_ Characteristics; boost::dll::detail::DWORD_ TimeDateStamp; boost::dll::detail::WORD_ MajorVersion; boost::dll::detail::WORD_ MinorVersion; boost::dll::detail::DWORD_ Name; boost::dll::detail::DWORD_ Base; boost::dll::detail::DWORD_ NumberOfFunctions; boost::dll::detail::DWORD_ NumberOfNames; boost::dll::detail::DWORD_ AddressOfFunctions; boost::dll::detail::DWORD_ AddressOfNames; boost::dll::detail::DWORD_ AddressOfNameOrdinals; }; struct IMAGE_SECTION_HEADER_ { // 32/64 independent header static const std::size_t IMAGE_SIZEOF_SHORT_NAME_ = 8; boost::dll::detail::BYTE_ Name[IMAGE_SIZEOF_SHORT_NAME_]; union { boost::dll::detail::DWORD_ PhysicalAddress; boost::dll::detail::DWORD_ VirtualSize; } Misc; boost::dll::detail::DWORD_ VirtualAddress; boost::dll::detail::DWORD_ SizeOfRawData; boost::dll::detail::DWORD_ PointerToRawData; boost::dll::detail::DWORD_ PointerToRelocations; boost::dll::detail::DWORD_ PointerToLinenumbers; boost::dll::detail::WORD_ NumberOfRelocations; boost::dll::detail::WORD_ NumberOfLinenumbers; boost::dll::detail::DWORD_ Characteristics; }; template <class AddressOffsetT> struct IMAGE_OPTIONAL_HEADER_template { static const std::size_t IMAGE_NUMBEROF_DIRECTORY_ENTRIES_ = 16; boost::dll::detail::WORD_ Magic; boost::dll::detail::BYTE_ MajorLinkerVersion; boost::dll::detail::BYTE_ MinorLinkerVersion; boost::dll::detail::DWORD_ SizeOfCode; boost::dll::detail::DWORD_ SizeOfInitializedData; boost::dll::detail::DWORD_ SizeOfUninitializedData; boost::dll::detail::DWORD_ AddressOfEntryPoint; union { boost::dll::detail::DWORD_ BaseOfCode; unsigned char padding_[sizeof(AddressOffsetT) == 8 ? 4 : 8]; // in x64 version BaseOfData does not exist } BaseOfCode_and_BaseOfData; AddressOffsetT ImageBase; boost::dll::detail::DWORD_ SectionAlignment; boost::dll::detail::DWORD_ FileAlignment; boost::dll::detail::WORD_ MajorOperatingSystemVersion; boost::dll::detail::WORD_ MinorOperatingSystemVersion; boost::dll::detail::WORD_ MajorImageVersion; boost::dll::detail::WORD_ MinorImageVersion; boost::dll::detail::WORD_ MajorSubsystemVersion; boost::dll::detail::WORD_ MinorSubsystemVersion; boost::dll::detail::DWORD_ Win32VersionValue; boost::dll::detail::DWORD_ SizeOfImage; boost::dll::detail::DWORD_ SizeOfHeaders; boost::dll::detail::DWORD_ CheckSum; boost::dll::detail::WORD_ Subsystem; boost::dll::detail::WORD_ DllCharacteristics; AddressOffsetT SizeOfStackReserve; AddressOffsetT SizeOfStackCommit; AddressOffsetT SizeOfHeapReserve; AddressOffsetT SizeOfHeapCommit; boost::dll::detail::DWORD_ LoaderFlags; boost::dll::detail::DWORD_ NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY_ DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES_]; }; typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::DWORD_> IMAGE_OPTIONAL_HEADER32_; typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::ULONGLONG_> IMAGE_OPTIONAL_HEADER64_; template <class AddressOffsetT> struct IMAGE_NT_HEADERS_template { boost::dll::detail::DWORD_ Signature; IMAGE_FILE_HEADER_ FileHeader; IMAGE_OPTIONAL_HEADER_template<AddressOffsetT> OptionalHeader; }; typedef IMAGE_NT_HEADERS_template<boost::dll::detail::DWORD_> IMAGE_NT_HEADERS32_; typedef IMAGE_NT_HEADERS_template<boost::dll::detail::ULONGLONG_> IMAGE_NT_HEADERS64_; template <class AddressOffsetT> class pe_info { typedef IMAGE_NT_HEADERS_template<AddressOffsetT> header_t; typedef IMAGE_EXPORT_DIRECTORY_ exports_t; typedef IMAGE_SECTION_HEADER_ section_t; typedef IMAGE_DOS_HEADER_ dos_t; template <class T> static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) { fs.read(reinterpret_cast<char*>(&value), size); } public: static bool parsing_supported(std::ifstream& fs) { dos_t dos; fs.seekg(0); fs.read(reinterpret_cast<char*>(&dos), sizeof(dos)); // 'MZ' and 'ZM' according to Wikipedia if (dos.e_magic != 0x4D5A && dos.e_magic != 0x5A4D) { return false; } header_t h; fs.seekg(dos.e_lfanew); fs.read(reinterpret_cast<char*>(&h), sizeof(h)); return h.Signature == 0x00004550 // 'PE00' && h.OptionalHeader.Magic == (sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 0x10B : 0x20B); } private: static header_t header(std::ifstream& fs) { header_t h; dos_t dos; fs.seekg(0); read_raw(fs, dos); fs.seekg(dos.e_lfanew); read_raw(fs, h); return h; } static exports_t exports(std::ifstream& fs, const header_t& h) { static const unsigned int IMAGE_DIRECTORY_ENTRY_EXPORT_ = 0; const std::size_t exp_virtual_address = h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT_].VirtualAddress; exports_t exports; if (exp_virtual_address == 0) { // The virtual address can be 0 in case there are no exported symbols std::memset(&exports, 0, sizeof(exports)); return exports; } const std::size_t real_offset = get_file_offset(fs, exp_virtual_address, h); BOOST_ASSERT(real_offset); fs.seekg(real_offset); read_raw(fs, exports); return exports; } static std::size_t get_file_offset(std::ifstream& fs, std::size_t virtual_address, const header_t& h) { BOOST_ASSERT(virtual_address); section_t image_section_header; { // fs.seekg to the beginning on section headers dos_t dos; fs.seekg(0); read_raw(fs, dos); fs.seekg(dos.e_lfanew + sizeof(header_t)); } for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) { read_raw(fs, image_section_header); if (virtual_address >= image_section_header.VirtualAddress && virtual_address < image_section_header.VirtualAddress + image_section_header.SizeOfRawData) { return image_section_header.PointerToRawData + virtual_address - image_section_header.VirtualAddress; } } return 0; } public: static std::vector<std::string> sections(std::ifstream& fs) { std::vector<std::string> ret; const header_t h = header(fs); ret.reserve(h.FileHeader.NumberOfSections); // get names, e.g: .text .rdata .data .rsrc .reloc section_t image_section_header; char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1]; std::memset(name_helper, 0, sizeof(name_helper)); for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) { // There is no terminating null character if the string is exactly eight characters long read_raw(fs, image_section_header); std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_); if (name_helper[0] != '/') { ret.push_back(name_helper); } else { // For longer names, image_section_header.Name contains a slash (/) followed by ASCII representation of a decimal number. // this number is an offset into the string table. // TODO: fixme ret.push_back(name_helper); } } return ret; } static std::vector<std::string> symbols(std::ifstream& fs) { std::vector<std::string> ret; const header_t h = header(fs); const exports_t exprt = exports(fs, h); const std::size_t exported_symbols = exprt.NumberOfNames; if (exported_symbols == 0) { return ret; } const std::size_t fixed_names_addr = get_file_offset(fs, exprt.AddressOfNames, h); ret.reserve(exported_symbols); boost::dll::detail::DWORD_ name_offset; std::string symbol_name; for (std::size_t i = 0;i < exported_symbols;++i) { fs.seekg(fixed_names_addr + i * sizeof(name_offset)); read_raw(fs, name_offset); fs.seekg(get_file_offset(fs, name_offset, h)); std::getline(fs, symbol_name, '\0'); ret.push_back(symbol_name); } return ret; } static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) { std::vector<std::string> ret; const header_t h = header(fs); std::size_t section_begin_addr = 0; std::size_t section_end_addr = 0; { // getting address range for the section section_t image_section_header; char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1]; std::memset(name_helper, 0, sizeof(name_helper)); for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) { // There is no terminating null character if the string is exactly eight characters long read_raw(fs, image_section_header); std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_); if (!std::strcmp(section_name, name_helper)) { section_begin_addr = image_section_header.PointerToRawData; section_end_addr = section_begin_addr + image_section_header.SizeOfRawData; } } // returning empty result if section was not found if(section_begin_addr == 0 || section_end_addr == 0) return ret; } const exports_t exprt = exports(fs, h); const std::size_t exported_symbols = exprt.NumberOfFunctions; const std::size_t fixed_names_addr = get_file_offset(fs, exprt.AddressOfNames, h); const std::size_t fixed_ordinals_addr = get_file_offset(fs, exprt.AddressOfNameOrdinals, h); const std::size_t fixed_functions_addr = get_file_offset(fs, exprt.AddressOfFunctions, h); ret.reserve(exported_symbols); boost::dll::detail::DWORD_ ptr; boost::dll::detail::WORD_ ordinal; std::string symbol_name; for (std::size_t i = 0;i < exported_symbols;++i) { // getting ordinal fs.seekg(fixed_ordinals_addr + i * sizeof(ordinal)); read_raw(fs, ordinal); // getting function addr fs.seekg(fixed_functions_addr + ordinal * sizeof(ptr)); read_raw(fs, ptr); ptr = static_cast<boost::dll::detail::DWORD_>( get_file_offset(fs, ptr, h) ); if (ptr >= section_end_addr || ptr < section_begin_addr) { continue; } fs.seekg(fixed_names_addr + i * sizeof(ptr)); read_raw(fs, ptr); fs.seekg(get_file_offset(fs, ptr, h)); std::getline(fs, symbol_name, '\0'); ret.push_back(symbol_name); } return ret; } // a test method to get dependents modules, // who my plugin imports (1st level only) /* e.g. for myself I get: KERNEL32.dll MSVCP110D.dll boost_system-vc-mt-gd-1_56.dll MSVCR110D.dll */ /* static std::vector<std::string> depend_of(boost::dll::fs::error_code &ec) BOOST_NOEXCEPT { std::vector<std::string> ret; IMAGE_DOS_HEADER* image_dos_header = (IMAGE_DOS_HEADER*)native(); if(!image_dos_header) { // ERROR_BAD_EXE_FORMAT ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::executable_format_error ); return ret; } IMAGE_OPTIONAL_HEADER* image_optional_header = (IMAGE_OPTIONAL_HEADER*)((boost::dll::detail::BYTE_*)native() + image_dos_header->e_lfanew + 24); if(!image_optional_header) { // ERROR_BAD_EXE_FORMAT ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::executable_format_error ); return ret; } IMAGE_IMPORT_DESCRIPTOR* image_import_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)((boost::dll::detail::BYTE_*)native() + image_optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); if(!image_import_descriptor) { // ERROR_BAD_EXE_FORMAT ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::executable_format_error ); return ret; } while(image_import_descriptor->FirstThunk) { std::string module_name = reinterpret_cast<char*>((boost::dll::detail::BYTE_*)native() + image_import_descriptor->Name); if(module_name.size()) { ret.push_back(module_name); } image_import_descriptor++; } return ret; } */ }; typedef pe_info<boost::dll::detail::DWORD_> pe_info32; typedef pe_info<boost::dll::detail::ULONGLONG_> pe_info64; }}} // namespace boost::dll::detail #endif // BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP detail/macho_info.hpp 0000644 00000033706 15125237303 0010633 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2020 Antony Polukhin. // // 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_DLL_DETAIL_MACHO_INFO_HPP #define BOOST_DLL_DETAIL_MACHO_INFO_HPP #include <boost/dll/config.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #include <algorithm> #include <fstream> #include <string> // for std::getline #include <boost/cstdint.hpp> namespace boost { namespace dll { namespace detail { typedef int integer_t; typedef int vm_prot_t; typedef integer_t cpu_type_t; typedef integer_t cpu_subtype_t; template <class AddressOffsetT> struct mach_header_template { boost::uint32_t magic; cpu_type_t cputype; cpu_subtype_t cpusubtype; boost::uint32_t filetype; boost::uint32_t ncmds; boost::uint32_t sizeofcmds; boost::uint32_t flags[sizeof(AddressOffsetT) / sizeof(uint32_t)]; // Flags and reserved }; typedef mach_header_template<boost::uint32_t> mach_header_32_; typedef mach_header_template<boost::uint64_t> mach_header_64_; struct load_command_ { boost::uint32_t cmd; /* type of command */ boost::uint32_t cmdsize; }; struct load_command_types { BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_ = 0x1); /* segment of this file to be mapped */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMTAB_ = 0x2); /* link-edit stab symbol table info */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMSEG_ = 0x3); /* link-edit gdb symbol table info (obsolete) */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_THREAD_ = 0x4); /* thread */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UNIXTHREAD_ = 0x5); /* unix thread (includes a stack) */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOADFVMLIB_ = 0x6); /* load a specified fixed VM shared library */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDFVMLIB_ = 0x7); /* fixed VM shared library identification */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDENT_ = 0x8); /* object identification info (obsolete) */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_FVMFILE_ = 0x9); /* fixed VM file inclusion (internal use) */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREPAGE_ = 0xa); /* prepage command (internal use) */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYSYMTAB_ = 0xb); /* dynamic link-edit symbol table info */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLIB_ = 0xc); /* load a dynamically linked shared library */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLIB_ = 0xd); /* dynamically linked shared lib ident */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLINKER_ = 0xe); /* load a dynamic linker */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLINKER_ = 0xf); /* dynamic linker identification */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBOUND_DYLIB_ = 0x10); /* modules prebound for a dynamically linked shared library */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_ = 0x11); /* image routines */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_FRAMEWORK_ = 0x12); /* sub framework */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_UMBRELLA_ = 0x13); /* sub umbrella */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_CLIENT_ = 0x14); /* sub client */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_LIBRARY_ = 0x15); /* sub library */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_TWOLEVEL_HINTS_ = 0x16); /* two-level namespace lookup hints */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBIND_CKSUM_ = 0x17); /* prebind checksum */ /* * After MacOS X 10.1 when a new load command is added that is required to be * understood by the dynamic linker for the image to execute properly the * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic * linker sees such a load command it it does not understand will issue a * "unknown load command required for execution" error and refuse to use the * image. Other load commands without this bit that are not understood will * simply be ignored. */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REQ_DYLD_ = 0x80000000); /* * load a dynamically linked shared library that is allowed to be missing * (all symbols are weak imported). */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_WEAK_DYLIB_ = (0x18 | LC_REQ_DYLD_)); BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_64_ = 0x19); /* 64-bit segment of this file to be mapped */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_64_ = 0x1a); /* 64-bit image routines */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UUID_ = 0x1b); /* the uuid */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_RPATH_ = (0x1c | LC_REQ_DYLD_)); /* runpath additions */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_CODE_SIGNATURE_ = 0x1d); /* local of code signature */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_SPLIT_INFO_= 0x1e); /* local of info to split segments */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REEXPORT_DYLIB_ = (0x1f | LC_REQ_DYLD_)); /* load and re-export dylib */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LAZY_LOAD_DYLIB_ = 0x20); /* delay load of dylib until first use */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ENCRYPTION_INFO_ = 0x21); /* encrypted segment information */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ = 0x22); /* compressed dyld information */ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ONLY_ = (0x22|LC_REQ_DYLD_)); /* compressed dyld information only */ }; template <class AddressOffsetT> struct segment_command_template { boost::uint32_t cmd; /* LC_SEGMENT_ */ boost::uint32_t cmdsize; /* includes sizeof section structs */ char segname[16]; /* segment name */ AddressOffsetT vmaddr; /* memory address of this segment */ AddressOffsetT vmsize; /* memory size of this segment */ AddressOffsetT fileoff; /* file offset of this segment */ AddressOffsetT filesize; /* amount to map from the file */ vm_prot_t maxprot; /* maximum VM protection */ vm_prot_t initprot; /* initial VM protection */ boost::uint32_t nsects; /* number of sections in segment */ boost::uint32_t flags; /* flags */ }; typedef segment_command_template<boost::uint32_t> segment_command_32_; typedef segment_command_template<boost::uint64_t> segment_command_64_; template <class AddressOffsetT> struct section_template { char sectname[16]; /* name of this section */ char segname[16]; /* segment this section goes in */ AddressOffsetT addr; /* memory address of this section */ AddressOffsetT size; /* size in bytes of this section */ boost::uint32_t offset; /* file offset of this section */ boost::uint32_t align; /* section alignment (power of 2) */ boost::uint32_t reloff; /* file offset of relocation entries */ boost::uint32_t nreloc; /* number of relocation entries */ boost::uint32_t flags; /* flags (section type and attributes)*/ boost::uint32_t reserved[1 + sizeof(AddressOffsetT) / sizeof(uint32_t)]; }; typedef section_template<boost::uint32_t> section_32_; typedef section_template<boost::uint64_t> section_64_; struct symtab_command_ { boost::uint32_t cmd; /* LC_SYMTAB_ */ boost::uint32_t cmdsize; /* sizeof(struct symtab_command) */ boost::uint32_t symoff; /* symbol table offset */ boost::uint32_t nsyms; /* number of symbol table entries */ boost::uint32_t stroff; /* string table offset */ boost::uint32_t strsize; /* string table size in bytes */ }; template <class AddressOffsetT> struct nlist_template { boost::uint32_t n_strx; boost::uint8_t n_type; boost::uint8_t n_sect; boost::uint16_t n_desc; AddressOffsetT n_value; }; typedef nlist_template<boost::uint32_t> nlist_32_; typedef nlist_template<boost::uint64_t> nlist_64_; template <class AddressOffsetT> class macho_info { typedef boost::dll::detail::mach_header_template<AddressOffsetT> header_t; typedef boost::dll::detail::load_command_ load_command_t; typedef boost::dll::detail::segment_command_template<AddressOffsetT> segment_t; typedef boost::dll::detail::section_template<AddressOffsetT> section_t; typedef boost::dll::detail::symtab_command_ symbol_header_t; typedef boost::dll::detail::nlist_template<AddressOffsetT> nlist_t; BOOST_STATIC_CONSTANT(boost::uint32_t, SEGMENT_CMD_NUMBER = (sizeof(AddressOffsetT) > 4 ? load_command_types::LC_SEGMENT_64_ : load_command_types::LC_SEGMENT_)); public: static bool parsing_supported(std::ifstream& fs) { static const uint32_t magic_bytes = (sizeof(AddressOffsetT) <= sizeof(uint32_t) ? 0xfeedface : 0xfeedfacf); uint32_t magic; fs.seekg(0); fs.read(reinterpret_cast<char*>(&magic), sizeof(magic)); return (magic_bytes == magic); } private: template <class T> static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) { fs.read(reinterpret_cast<char*>(&value), size); } template <class F> static void command_finder(std::ifstream& fs, uint32_t cmd_num, F callback_f) { const header_t h = header(fs); load_command_t command; fs.seekg(sizeof(header_t)); for (std::size_t i = 0; i < h.ncmds; ++i) { const std::ifstream::pos_type pos = fs.tellg(); read_raw(fs, command); if (command.cmd != cmd_num) { fs.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize)); continue; } fs.seekg(pos); callback_f(fs); fs.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize)); } } struct section_names_gather { std::vector<std::string>& ret; void operator()(std::ifstream& fs) const { segment_t segment; read_raw(fs, segment); section_t section; ret.reserve(ret.size() + segment.nsects); for (std::size_t j = 0; j < segment.nsects; ++j) { read_raw(fs, section); // `segname` goes right after the `sectname`. // Forcing `sectname` to end on '\0' section.segname[0] = '\0'; ret.push_back(section.sectname); if (ret.back().empty()) { ret.pop_back(); // Do not show empty names } } } }; struct symbol_names_gather { std::vector<std::string>& ret; std::size_t section_index; void operator()(std::ifstream& fs) const { symbol_header_t symbh; read_raw(fs, symbh); ret.reserve(ret.size() + symbh.nsyms); nlist_t symbol; std::string symbol_name; for (std::size_t j = 0; j < symbh.nsyms; ++j) { fs.seekg(symbh.symoff + j * sizeof(nlist_t)); read_raw(fs, symbol); if (!symbol.n_strx) { continue; // Symbol has no name } if ((symbol.n_type & 0x0e) != 0xe || !symbol.n_sect) { continue; // Symbol has no section } if (section_index && section_index != symbol.n_sect) { continue; // Not in the required section } fs.seekg(symbh.stroff + symbol.n_strx); std::getline(fs, symbol_name, '\0'); if (symbol_name.empty()) { continue; } if (symbol_name[0] == '_') { // Linker adds additional '_' symbol. Could not find official docs for that case. ret.push_back(symbol_name.c_str() + 1); } else { ret.push_back(symbol_name); } } } }; public: static std::vector<std::string> sections(std::ifstream& fs) { std::vector<std::string> ret; section_names_gather f = { ret }; command_finder(fs, SEGMENT_CMD_NUMBER, f); return ret; } private: static header_t header(std::ifstream& fs) { header_t h; fs.seekg(0); read_raw(fs, h); return h; } public: static std::vector<std::string> symbols(std::ifstream& fs) { std::vector<std::string> ret; symbol_names_gather f = { ret, 0 }; command_finder(fs, load_command_types::LC_SYMTAB_, f); return ret; } static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) { // Not very optimal solution std::vector<std::string> ret = sections(fs); std::vector<std::string>::iterator it = std::find(ret.begin(), ret.end(), section_name); if (it == ret.end()) { // No section with such name ret.clear(); return ret; } // section indexes start from 1 symbol_names_gather f = { ret, static_cast<std::size_t>(1 + (it - ret.begin())) }; ret.clear(); command_finder(fs, load_command_types::LC_SYMTAB_, f); return ret; } }; typedef macho_info<boost::uint32_t> macho_info32; typedef macho_info<boost::uint64_t> macho_info64; }}} // namespace boost::dll::detail #endif // BOOST_DLL_DETAIL_MACHO_INFO_HPP detail/posix/shared_library_impl.hpp 0000644 00000016461 15125237303 0013705 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_SHARED_LIBRARY_IMPL_HPP #define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP #include <boost/dll/config.hpp> #include <boost/dll/shared_library_load_mode.hpp> #include <boost/dll/detail/posix/path_from_handle.hpp> #include <boost/dll/detail/posix/program_location_impl.hpp> #include <boost/move/utility.hpp> #include <boost/swap.hpp> #include <boost/predef/os.h> #include <dlfcn.h> #include <cstring> // strncmp #if !BOOST_OS_MACOS && !BOOST_OS_IOS && !BOOST_OS_QNX # include <link.h> #elif BOOST_OS_QNX // QNX's copy of <elf.h> and <link.h> reside in sys folder # include <sys/link.h> #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { namespace detail { class shared_library_impl { BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl) public: typedef void* native_handle_t; shared_library_impl() BOOST_NOEXCEPT : handle_(NULL) {} ~shared_library_impl() BOOST_NOEXCEPT { unload(); } shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT : handle_(sl.handle_) { sl.handle_ = NULL; } shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT { swap(sl); return *this; } static boost::dll::fs::path decorate(const boost::dll::fs::path & sl) { boost::dll::fs::path actual_path = ( std::strncmp(sl.filename().string().c_str(), "lib", 3) ? boost::dll::fs::path((sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib").native() + sl.filename().native()) : sl ); actual_path += suffix(); return actual_path; } void load(boost::dll::fs::path sl, load_mode::type portable_mode, boost::dll::fs::error_code &ec) { typedef int native_mode_t; native_mode_t native_mode = static_cast<native_mode_t>(portable_mode); unload(); // Do not allow opening NULL paths. User must use program_location() instead if (sl.empty()) { boost::dll::detail::reset_dlerror(); ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); return; } // Fixing modes if (!(native_mode & load_mode::rtld_now)) { native_mode |= load_mode::rtld_lazy; } if (!(native_mode & load_mode::rtld_global)) { native_mode |= load_mode::rtld_local; } #if BOOST_OS_LINUX || BOOST_OS_ANDROID if (!sl.has_parent_path() && !(native_mode & load_mode::search_system_folders)) { sl = "." / sl; } #else if (!sl.is_absolute() && !(native_mode & load_mode::search_system_folders)) { boost::dll::fs::error_code current_path_ec; boost::dll::fs::path prog_loc = boost::dll::fs::current_path(current_path_ec); if (!current_path_ec) { prog_loc /= sl; sl.swap(prog_loc); } } #endif native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::search_system_folders); // Trying to open with appended decorations if (!!(native_mode & load_mode::append_decorations)) { native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::append_decorations); boost::dll::fs::path actual_path = decorate(sl); handle_ = dlopen(actual_path.c_str(), native_mode); if (handle_) { boost::dll::detail::reset_dlerror(); return; } boost::dll::fs::error_code prog_loc_err; boost::dll::fs::path loc = boost::dll::detail::program_location_impl(prog_loc_err); if (boost::dll::fs::exists(actual_path) && !boost::dll::fs::equivalent(sl, loc, prog_loc_err)) { // decorated path exists : current error is not a bad file descriptor and we are not trying to load the executable itself ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::executable_format_error ); return; } } // Opening by exactly specified path handle_ = dlopen(sl.c_str(), native_mode); if (handle_) { boost::dll::detail::reset_dlerror(); return; } ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); // Maybe user wanted to load the executable itself? Checking... // We assume that usually user wants to load a dynamic library not the executable itself, that's why // we try this only after traditional load fails. boost::dll::fs::error_code prog_loc_err; boost::dll::fs::path loc = boost::dll::detail::program_location_impl(prog_loc_err); if (!prog_loc_err && boost::dll::fs::equivalent(sl, loc, prog_loc_err) && !prog_loc_err) { // As is known the function dlopen() loads the dynamic library file // named by the null-terminated string filename and returns an opaque // "handle" for the dynamic library. If filename is NULL, then the // returned handle is for the main program. ec.clear(); boost::dll::detail::reset_dlerror(); handle_ = dlopen(NULL, native_mode); if (!handle_) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); } } } bool is_loaded() const BOOST_NOEXCEPT { return (handle_ != 0); } void unload() BOOST_NOEXCEPT { if (!is_loaded()) { return; } dlclose(handle_); handle_ = 0; } void swap(shared_library_impl& rhs) BOOST_NOEXCEPT { boost::swap(handle_, rhs.handle_); } boost::dll::fs::path full_module_path(boost::dll::fs::error_code &ec) const { return boost::dll::detail::path_from_handle(handle_, ec); } static boost::dll::fs::path suffix() { // https://sourceforge.net/p/predef/wiki/OperatingSystems/ #if BOOST_OS_MACOS || BOOST_OS_IOS return ".dylib"; #else return ".so"; #endif } void* symbol_addr(const char* sb, boost::dll::fs::error_code &ec) const BOOST_NOEXCEPT { // dlsym - obtain the address of a symbol from a dlopen object void* const symbol = dlsym(handle_, sb); if (symbol == NULL) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::invalid_seek ); } // If handle does not refer to a valid object opened by dlopen(), // or if the named symbol cannot be found within any of the objects // associated with handle, dlsym() shall return NULL. // More detailed diagnostic information shall be available through dlerror(). return symbol; } native_handle_t native() const BOOST_NOEXCEPT { return handle_; } private: native_handle_t handle_; }; }}} // boost::dll::detail #endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP detail/posix/program_location_impl.hpp 0000644 00000007454 15125237303 0014254 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP #define BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP #include <boost/dll/config.hpp> #include <boost/dll/detail/system_error.hpp> #include <boost/predef/os.h> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #if BOOST_OS_MACOS || BOOST_OS_IOS #include <mach-o/dyld.h> namespace boost { namespace dll { namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code &ec) { ec.clear(); char path[1024]; uint32_t size = sizeof(path); if (_NSGetExecutablePath(path, &size) == 0) return boost::dll::fs::path(path); char *p = new char[size]; if (_NSGetExecutablePath(p, &size) != 0) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); } boost::dll::fs::path ret(p); delete[] p; return ret; } }}} // namespace boost::dll::detail #elif BOOST_OS_SOLARIS #include <stdlib.h> namespace boost { namespace dll { namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code& ec) { ec.clear(); return boost::dll::fs::path(getexecname()); } }}} // namespace boost::dll::detail #elif BOOST_OS_BSD_FREE #include <sys/types.h> #include <sys/sysctl.h> #include <stdlib.h> namespace boost { namespace dll { namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code& ec) { ec.clear(); int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; char buf[10240]; size_t cb = sizeof(buf); sysctl(mib, 4, buf, &cb, NULL, 0); return boost::dll::fs::path(buf); } }}} // namespace boost::dll::detail #elif BOOST_OS_BSD_NET namespace boost { namespace dll { namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code &ec) { return boost::dll::fs::read_symlink("/proc/curproc/exe", ec); } }}} // namespace boost::dll::detail #elif BOOST_OS_BSD_DRAGONFLY namespace boost { namespace dll { namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code &ec) { return boost::dll::fs::read_symlink("/proc/curproc/file", ec); } }}} // namespace boost::dll::detail #elif BOOST_OS_QNX #include <fstream> #include <string> // for std::getline namespace boost { namespace dll { namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code &ec) { ec.clear(); std::string s; std::ifstream ifs("/proc/self/exefile"); std::getline(ifs, s); if (ifs.fail() || s.empty()) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); } return boost::dll::fs::path(s); } }}} // namespace boost::dll::detail #else // BOOST_OS_LINUX || BOOST_OS_UNIX || BOOST_OS_HPUX || BOOST_OS_ANDROID namespace boost { namespace dll { namespace detail { inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code &ec) { // We can not use // boost::dll::detail::path_from_handle(dlopen(NULL, RTLD_LAZY | RTLD_LOCAL), ignore); // because such code returns empty path. return boost::dll::fs::read_symlink("/proc/self/exe", ec); // Linux specific } }}} // namespace boost::dll::detail #endif #endif // BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP detail/posix/path_from_handle.hpp 0000644 00000014016 15125237303 0013156 0 ustar 00 // Copyright 2014-2015 Renato Tegon Forti, Antony Polukhin. // Copyright 2016-2019 Antony Polukhin. // // 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_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP #define BOOST_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP #include <boost/dll/config.hpp> #include <boost/dll/detail/system_error.hpp> #include <boost/dll/detail/posix/program_location_impl.hpp> #include <boost/predef/os.h> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #if BOOST_OS_MACOS || BOOST_OS_IOS # include <mach-o/dyld.h> # include <mach-o/nlist.h> # include <cstddef> // for std::ptrdiff_t namespace boost { namespace dll { namespace detail { inline void* strip_handle(void* handle) BOOST_NOEXCEPT { return reinterpret_cast<void*>( (reinterpret_cast<std::ptrdiff_t>(handle) >> 2) << 2 ); } inline boost::dll::fs::path path_from_handle(void* handle, boost::dll::fs::error_code &ec) { handle = strip_handle(handle); // Iterate through all images currently in memory // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dyld.3.html const std::size_t count = _dyld_image_count(); // not thread safe: other thread my [un]load images for (std::size_t i = 0; i <= count; ++i) { // on last iteration `i` is equal to `count` which is out of range, so `_dyld_get_image_name` // will return NULL. `dlopen(NULL, RTLD_LAZY)` call will open the current executable. const char* image_name = _dyld_get_image_name(i); // dlopen/dlclose must not affect `_dyld_image_count()`, because libraries are already loaded and only the internal counter is affected void* probe_handle = dlopen(image_name, RTLD_LAZY); dlclose(probe_handle); // If the handle is the same as what was passed in (modulo mode bits), return this image name if (handle == strip_handle(probe_handle)) { boost::dll::detail::reset_dlerror(); return image_name; } } boost::dll::detail::reset_dlerror(); ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); return boost::dll::fs::path(); } }}} // namespace boost::dll::detail #elif BOOST_OS_ANDROID #include <boost/dll/runtime_symbol_info.hpp> namespace boost { namespace dll { namespace detail { struct soinfo { // if defined(__work_around_b_24465209__), then an array of char[128] goes here. // Unfortunately, __work_around_b_24465209__ is visible only during compilation of Android's linker const void* phdr; size_t phnum; void* entry; void* base; // ... // Ignoring remaning parts of the structure }; inline boost::dll::fs::path path_from_handle(const void* handle, boost::dll::fs::error_code &ec) { static const std::size_t work_around_b_24465209__offset = 128; const struct soinfo* si = reinterpret_cast<const struct soinfo*>( static_cast<const char*>(handle) + work_around_b_24465209__offset ); boost::dll::fs::path ret = boost::dll::symbol_location_ptr(si->base, ec); if (ec) { ec.clear(); si = static_cast<const struct soinfo*>(handle); return boost::dll::symbol_location_ptr(si->base, ec); } return ret; } }}} // namespace boost::dll::detail #else // #if BOOST_OS_MACOS || BOOST_OS_IOS || BOOST_OS_ANDROID // for dlinfo #include <dlfcn.h> #if BOOST_OS_QNX // QNX's copy of <elf.h> and <link.h> reside in sys folder # include <sys/link.h> #else # include <link.h> // struct link_map #endif namespace boost { namespace dll { namespace detail { #if BOOST_OS_QNX // Android and QNX miss struct link_map. QNX misses ElfW macro, so avoiding it. struct link_map { void *l_addr; // Base address shared object is loaded at char *l_name; // Absolute file name object was found in // ... // Ignoring remaning parts of the structure }; #endif // #if BOOST_OS_QNX inline boost::dll::fs::path path_from_handle(void* handle, boost::dll::fs::error_code &ec) { // RTLD_DI_LINKMAP (RTLD_DI_ORIGIN returns only folder and is not suitable for this case) // Obtain the Link_map for the handle that is specified. // The p argument points to a Link_map pointer (Link_map // **p). The actual storage for the Link_map structure is // maintained by ld.so.1. // // Unfortunately we can not use `dlinfo(handle, RTLD_DI_LINKMAP, &link_map) < 0` // because it is not supported on MacOS X 10.3, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, // HP-UX 11, IRIX 6.5, OSF/1 5.1, Cygwin, mingw, Interix 3.5, BeOS. // Fortunately investigating the sources of open source projects brought the understanding, that // `handle` is just a `struct link_map*` that contains full library name. const struct link_map* link_map = 0; #if BOOST_OS_BSD_FREE // FreeBSD has it's own logic http://code.metager.de/source/xref/freebsd/libexec/rtld-elf/rtld.c // Fortunately it has the dlinfo call. if (dlinfo(handle, RTLD_DI_LINKMAP, &link_map) < 0) { link_map = 0; } #else link_map = static_cast<const struct link_map*>(handle); #endif if (!link_map) { boost::dll::detail::reset_dlerror(); ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); return boost::dll::fs::path(); } if (!link_map->l_name || *link_map->l_name == '\0') { return program_location_impl(ec); } return boost::dll::fs::path(link_map->l_name); } }}} // namespace boost::dll::detail #endif // #if BOOST_OS_MACOS || BOOST_OS_IOS #endif // BOOST_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP detail/get_mem_fn_type.hpp 0000644 00000002327 15125237303 0011665 0 ustar 00 // Copyright 2016 Klemens Morgenstern // // 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) // For more information, see http://www.boost.org #ifndef BOOST_DLL_DETAIL_GET_MEM_FN_TYPE_HPP_ #define BOOST_DLL_DETAIL_GET_MEM_FN_TYPE_HPP_ namespace boost { namespace dll { namespace detail { template<typename Class, typename Func> struct get_mem_fn_type; template<typename Class, typename Return, typename ...Args> struct get_mem_fn_type<Class, Return(Args...)> { typedef Return (Class::*mem_fn)(Args...); }; template<typename Class, typename Return, typename ...Args> struct get_mem_fn_type<const Class, Return(Args...)> { typedef Return (Class::*mem_fn)(Args...) const ; }; template<typename Class, typename Return, typename ...Args> struct get_mem_fn_type<volatile Class, Return(Args...)> { typedef Return (Class::*mem_fn)(Args...) volatile; }; template<typename Class, typename Return, typename ...Args> struct get_mem_fn_type<const volatile Class, Return(Args...)> { typedef Return (Class::*mem_fn)(Args...) const volatile ; }; }}} // namespace boost::dll::detail #endif /* BOOST_DLL_SMART_LIBRARY_HPP_ */ detail/windows/shared_library_impl.hpp 0000644 00000014621 15125237303 0014231 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_SHARED_LIBRARY_IMPL_HPP #define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP #include <boost/dll/config.hpp> #include <boost/dll/shared_library_load_mode.hpp> #include <boost/dll/detail/aggressive_ptr_cast.hpp> #include <boost/dll/detail/system_error.hpp> #include <boost/dll/detail/windows/path_from_handle.hpp> #include <boost/move/utility.hpp> #include <boost/swap.hpp> #include <boost/winapi/dll.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { namespace detail { class shared_library_impl { BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl) public: typedef boost::winapi::HMODULE_ native_handle_t; shared_library_impl() BOOST_NOEXCEPT : handle_(NULL) {} ~shared_library_impl() BOOST_NOEXCEPT { unload(); } shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT : handle_(sl.handle_) { sl.handle_ = NULL; } shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT { swap(sl); return *this; } static boost::dll::fs::path decorate(const boost::dll::fs::path& sl) { boost::dll::fs::path actual_path = sl; actual_path += suffix(); return actual_path; } void load(boost::dll::fs::path sl, load_mode::type portable_mode, boost::dll::fs::error_code &ec) { typedef boost::winapi::DWORD_ native_mode_t; native_mode_t native_mode = static_cast<native_mode_t>(portable_mode); unload(); if (!sl.is_absolute() && !(native_mode & load_mode::search_system_folders)) { boost::dll::fs::error_code current_path_ec; boost::dll::fs::path prog_loc = boost::dll::fs::current_path(current_path_ec); if (!current_path_ec) { prog_loc /= sl; sl.swap(prog_loc); } } native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::search_system_folders); // Trying to open with appended decorations if (!!(native_mode & load_mode::append_decorations)) { native_mode = static_cast<unsigned>(native_mode) & ~static_cast<unsigned>(load_mode::append_decorations); if (load_impl(decorate(sl), native_mode, ec)) { return; } // MinGW loves 'lib' prefix and puts it even on Windows platform. const boost::dll::fs::path mingw_load_path = ( sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib" ).native() + sl.filename().native() + suffix().native(); if (load_impl(mingw_load_path, native_mode, ec)) { return; } } // From MSDN: If the string specifies a module name without a path and the // file name extension is omitted, the function appends the default library // extension .dll to the module name. // // From experiments: Default library extension appended to the module name even if // we have some path. So we do not check for path, only for extension. We can not be sure that // such behavior remain across all platforms, so we add L"." by hand. if (sl.has_extension()) { handle_ = boost::winapi::LoadLibraryExW(sl.c_str(), 0, native_mode); } else { handle_ = boost::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, native_mode); } // LoadLibraryExW method is capable of self loading from program_location() path. No special actions // must be taken to allow self loading. if (!handle_) { ec = boost::dll::detail::last_error_code(); } } bool is_loaded() const BOOST_NOEXCEPT { return (handle_ != 0); } void unload() BOOST_NOEXCEPT { if (handle_) { boost::winapi::FreeLibrary(handle_); handle_ = 0; } } void swap(shared_library_impl& rhs) BOOST_NOEXCEPT { boost::swap(handle_, rhs.handle_); } boost::dll::fs::path full_module_path(boost::dll::fs::error_code &ec) const { return boost::dll::detail::path_from_handle(handle_, ec); } static boost::dll::fs::path suffix() { return L".dll"; } void* symbol_addr(const char* sb, boost::dll::fs::error_code &ec) const BOOST_NOEXCEPT { if (is_resource()) { // `GetProcAddress` could not be called for libraries loaded with // `LOAD_LIBRARY_AS_DATAFILE`, `LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE` // or `LOAD_LIBRARY_AS_IMAGE_RESOURCE`. ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::operation_not_supported ); return NULL; } // Judging by the documentation of GetProcAddress // there is no version for UNICODE on desktop/server Windows, because // names of functions are stored in narrow characters. void* const symbol = boost::dll::detail::aggressive_ptr_cast<void*>( boost::winapi::get_proc_address(handle_, sb) ); if (symbol == NULL) { ec = boost::dll::detail::last_error_code(); } return symbol; } native_handle_t native() const BOOST_NOEXCEPT { return handle_; } private: // Returns true if this load attempt should be the last one. bool load_impl(const boost::dll::fs::path &load_path, boost::winapi::DWORD_ mode, boost::dll::fs::error_code &ec) { handle_ = boost::winapi::LoadLibraryExW(load_path.c_str(), 0, mode); if (handle_) { return true; } ec = boost::dll::detail::last_error_code(); if (boost::dll::fs::exists(load_path)) { // decorated path exists : current error is not a bad file descriptor return true; } ec.clear(); return false; } bool is_resource() const BOOST_NOEXCEPT { return false; /*!!( reinterpret_cast<boost::winapi::ULONG_PTR_>(handle_) & static_cast<boost::winapi::ULONG_PTR_>(3) );*/ } native_handle_t handle_; }; }}} // boost::dll::detail #endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP detail/windows/path_from_handle.hpp 0000644 00000004662 15125237303 0013514 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP #define BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP #include <boost/dll/config.hpp> #include <boost/dll/detail/system_error.hpp> #include <boost/winapi/dll.hpp> #include <boost/winapi/get_last_error.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { namespace detail { inline boost::dll::fs::error_code last_error_code() BOOST_NOEXCEPT { boost::winapi::DWORD_ err = boost::winapi::GetLastError(); return boost::dll::fs::error_code( static_cast<int>(err), boost::dll::fs::system_category() ); } inline boost::dll::fs::path path_from_handle(boost::winapi::HMODULE_ handle, boost::dll::fs::error_code &ec) { BOOST_STATIC_CONSTANT(boost::winapi::DWORD_, ERROR_INSUFFICIENT_BUFFER_ = 0x7A); BOOST_STATIC_CONSTANT(boost::winapi::DWORD_, DEFAULT_PATH_SIZE_ = 260); // On success, GetModuleFileNameW() doesn't reset last error to ERROR_SUCCESS. Resetting it manually. boost::winapi::GetLastError(); // If `handle` parameter is NULL, GetModuleFileName retrieves the path of the // executable file of the current process. boost::winapi::WCHAR_ path_hldr[DEFAULT_PATH_SIZE_]; boost::winapi::GetModuleFileNameW(handle, path_hldr, DEFAULT_PATH_SIZE_); ec = boost::dll::detail::last_error_code(); if (!ec) { return boost::dll::fs::path(path_hldr); } for (unsigned i = 2; i < 1025 && static_cast<boost::winapi::DWORD_>(ec.value()) == ERROR_INSUFFICIENT_BUFFER_; i *= 2) { std::wstring p(DEFAULT_PATH_SIZE_ * i, L'\0'); const std::size_t size = boost::winapi::GetModuleFileNameW(handle, &p[0], DEFAULT_PATH_SIZE_ * i); ec = boost::dll::detail::last_error_code(); if (!ec) { p.resize(size); return boost::dll::fs::path(p); } } // Error other than ERROR_INSUFFICIENT_BUFFER_ occurred or failed to allocate buffer big enough. return boost::dll::fs::path(); } }}} // namespace boost::dll::detail #endif // BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP detail/system_error.hpp 0000644 00000002554 15125237303 0011263 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_SYSTEM_ERROR_HPP #define BOOST_DLL_SYSTEM_ERROR_HPP #include <boost/dll/config.hpp> #include <boost/predef/os.h> #include <boost/throw_exception.hpp> #if !BOOST_OS_WINDOWS # include <dlfcn.h> #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { namespace detail { inline void reset_dlerror() BOOST_NOEXCEPT { #if !BOOST_OS_WINDOWS const char* const error_txt = dlerror(); (void)error_txt; #endif } inline void report_error(const boost::dll::fs::error_code& ec, const char* message) { #if !BOOST_OS_WINDOWS const char* const error_txt = dlerror(); if (error_txt) { boost::throw_exception( boost::dll::fs::system_error( ec, message + std::string(" (dlerror system message: ") + error_txt + std::string(")") ) ); } #endif boost::throw_exception( boost::dll::fs::system_error( ec, message ) ); } }}} // boost::dll::detail #endif // BOOST_DLL_SYSTEM_ERROR_HPP detail/demangling/mangled_storage_base.hpp 0000644 00000007224 15125237303 0014757 0 ustar 00 // Copyright 2016 Klemens Morgenstern // // 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_DLL_DETAIL_MANGLE_STORAGE_BASE_HPP_ #define BOOST_DLL_DETAIL_MANGLE_STORAGE_BASE_HPP_ #include <vector> #include <string> #include <map> #include <boost/dll/detail/demangling/demangle_symbol.hpp> #include <boost/dll/library_info.hpp> #include <boost/type_index/ctti_type_index.hpp> #include <boost/type_traits/remove_reference.hpp> namespace boost { namespace dll { namespace detail { ///stores the mangled names with the demangled name. struct mangled_storage_base { struct entry { std::string mangled; std::string demangled; entry() = default; entry(const std::string & m, const std::string &d) : mangled(m), demangled(d) {} entry(const entry&) = default; entry(entry&&) = default; entry &operator= (const entry&) = default; entry &operator= (entry&&) = default; }; protected: std::vector<entry> storage_; ///if a unknown class is imported it can be overloaded by this type std::map<boost::typeindex::ctti_type_index, std::string> aliases_; public: void assign(const mangled_storage_base & storage) { aliases_ = storage.aliases_; storage_ = storage.storage_; } void swap( mangled_storage_base & storage) { aliases_.swap(storage.aliases_); storage_.swap(storage.storage_); } void clear() { storage_.clear(); aliases_.clear(); } std::vector<entry> & get_storage() {return storage_;}; template<typename T> std::string get_name() const { using boost::typeindex::ctti_type_index; auto tx = ctti_type_index::type_id<T>(); auto val = (aliases_.count(tx) > 0) ? aliases_.at(tx) : tx.pretty_name(); return val; } mangled_storage_base() = default; mangled_storage_base(mangled_storage_base&&) = default; mangled_storage_base(const mangled_storage_base&) = default; mangled_storage_base(const std::vector<std::string> & symbols) { add_symbols(symbols);} explicit mangled_storage_base(library_info & li) : mangled_storage_base(li.symbols()) {} explicit mangled_storage_base( const boost::dll::fs::path& library_path, bool throw_if_not_native_format = true) : mangled_storage_base(library_info(library_path, throw_if_not_native_format).symbols()) { } void load(library_info & li) { storage_.clear(); add_symbols(li.symbols()); }; void load(const boost::dll::fs::path& library_path, bool throw_if_not_native_format = true) { storage_.clear(); add_symbols(library_info(library_path, throw_if_not_native_format).symbols()); }; /*! Allows do add a class as alias, if the class imported is not known * in this binary. * @tparam Alias The Alias type * @param The name to create the alias for. * * @note There can be multiple aliases, this is on purpose. */ template<typename Alias> void add_alias(const std::string& name) { aliases_.emplace( boost::typeindex::ctti_type_index::type_id<Alias>(), name ); } void add_symbols(const std::vector<std::string> & symbols) { for (auto & sym : symbols) { auto dm = demangle_symbol(sym); if (!dm.empty()) storage_.emplace_back(sym, dm); else storage_.emplace_back(sym, sym); } } }; }}} #endif /* BOOST_DLL_DETAIL_MANGLE_STORAGE_HPP_ */ detail/demangling/demangle_symbol.hpp 0000644 00000004273 15125237303 0013774 0 ustar 00 // Copyright 2015 Klemens Morgenstern // // This file provides a demangling for function names, i.e. entry points of a dll. // // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_DLL_DEMANGLE_SYMBOL_HPP_ #define BOOST_DLL_DEMANGLE_SYMBOL_HPP_ #include <boost/dll/config.hpp> #include <string> #include <algorithm> #include <memory> #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows namespace boost { namespace dll { namespace detail { typedef void * (__cdecl * allocation_function)(std::size_t); typedef void (__cdecl * free_function)(void *); extern "C" char* __unDName( char* outputString, const char* name, int maxStringLength, // Note, COMMA is leading following optional arguments allocation_function pAlloc, free_function pFree, unsigned short disableFlags ); inline std::string demangle_symbol(const char *mangled_name) { allocation_function alloc = [](std::size_t size){return static_cast<void*>(new char[size]);}; free_function free_f = [](void* p){delete [] static_cast<char*>(p);}; std::unique_ptr<char> name { __unDName( nullptr, mangled_name, 0, alloc, free_f, static_cast<unsigned short>(0))}; return std::string(name.get()); } inline std::string demangle_symbol(const std::string& mangled_name) { return demangle_symbol(mangled_name.c_str()); } }}} #else #include <boost/core/demangle.hpp> namespace boost { namespace dll { namespace detail { inline std::string demangle_symbol(const char *mangled_name) { if (*mangled_name == '_') { //because it start's with an underline _ auto dm = boost::core::demangle(mangled_name); if (!dm.empty()) return dm; else return (mangled_name); } //could not demangled return ""; } //for my personal convenience inline std::string demangle_symbol(const std::string& mangled_name) { return demangle_symbol(mangled_name.c_str()); } } namespace experimental { using ::boost::dll::detail::demangle_symbol; } }} #endif #endif /* BOOST_DEMANGLE_HPP_ */ detail/demangling/msvc.hpp 0000644 00000033052 15125237303 0011600 0 ustar 00 // Copyright 2016 Klemens Morgenstern // // 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_DLL_DETAIL_DEMANGLING_MSVC_HPP_ #define BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ #include <boost/dll/detail/demangling/mangled_storage_base.hpp> #include <iterator> #include <algorithm> #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_volatile.hpp> #include <boost/type_traits/is_lvalue_reference.hpp> #include <boost/type_traits/is_rvalue_reference.hpp> #include <boost/type_traits/function_traits.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/spirit/home/x3.hpp> namespace boost { namespace dll { namespace detail { class mangled_storage_impl : public mangled_storage_base { template<typename T> struct dummy {}; template<typename Return, typename ...Args> std::vector<std::string> get_func_params(dummy<Return(Args...)>) const { return {get_name<Args>()...}; } template<typename Return, typename ...Args> std::string get_return_type(dummy<Return(Args...)>) const { return get_name<Return>(); } //function to remove preceding 'class ' or 'struct ' if the are given in this format. inline static void trim_typename(std::string & val); public: using ctor_sym = std::string; using dtor_sym = std::string; using mangled_storage_base::mangled_storage_base; template<typename T> std::string get_variable(const std::string &name) const; template<typename Func> std::string get_function(const std::string &name) const; template<typename Class, typename Func> std::string get_mem_fn(const std::string &name) const; template<typename Signature> ctor_sym get_constructor() const; template<typename Class> dtor_sym get_destructor() const; template<typename T> //overload, does not need to virtual. std::string get_name() const { auto nm = mangled_storage_base::get_name<T>(); trim_typename(nm); return nm; } template<typename T> std::string get_vtable() const; template<typename T> std::vector<std::string> get_related() const; }; void mangled_storage_impl::trim_typename(std::string & val) { //remove preceding class or struct, because you might want to use a struct as class, et vice versa if (val.size() >= 6) { using namespace std; static constexpr char class_ [7] = "class "; static constexpr char struct_[8] = "struct "; if (equal(begin(class_), end(class_)-1, val.begin())) //aklright, starts with 'class ' val.erase(0, 6); else if (val.size() >= 7) if (equal(begin(struct_), end(struct_)-1, val.begin())) val.erase(0, 7); } } namespace parser { namespace x3 = spirit::x3; inline auto ptr_rule_impl(std::integral_constant<std::size_t, 32>) { return -((-x3::space) >> "__ptr32"); } inline auto ptr_rule_impl(std::integral_constant<std::size_t, 64>) { return -((-x3::space) >> "__ptr64"); } inline auto ptr_rule() { return ptr_rule_impl(std::integral_constant<std::size_t, sizeof(std::size_t)*8>()); } auto const visibility = ("public:" | x3::lit("protected:") | "private:"); auto const virtual_ = x3::space >> "virtual"; auto const static_ = x3::space >> x3::lit("static") ; inline auto const_rule_impl(true_type ) {return x3::space >> "const";}; inline auto const_rule_impl(false_type) {return x3::eps;}; template<typename T> auto const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());} inline auto volatile_rule_impl(true_type ) {return x3::space >> "volatile";}; inline auto volatile_rule_impl(false_type) {return x3::eps;}; template<typename T> auto volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());} inline auto inv_const_rule_impl(true_type ) {return "const" >> x3::space ;}; inline auto inv_const_rule_impl(false_type) {return x3::eps;}; template<typename T> auto inv_const_rule() {using t = is_const<typename remove_reference<T>::type>; return inv_const_rule_impl(t());} inline auto inv_volatile_rule_impl(true_type ) {return "volatile" >> x3::space;}; inline auto inv_volatile_rule_impl(false_type) {return x3::eps;}; template<typename T> auto inv_volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return inv_volatile_rule_impl(t());} inline auto reference_rule_impl(false_type, false_type) {return x3::eps;} inline auto reference_rule_impl(true_type, false_type) {return x3::space >>"&" ;} inline auto reference_rule_impl(false_type, true_type ) {return x3::space >>"&&" ;} template<typename T> auto reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());} auto const class_ = ("class" | x3::lit("struct")); //it takes a string, because it may be overloaded. template<typename T> auto type_rule(const std::string & type_name) { using namespace std; return -(class_ >> x3::space)>> x3::string(type_name) >> const_rule<T>() >> volatile_rule<T>() >> reference_rule<T>() >> ptr_rule(); } template<> inline auto type_rule<void>(const std::string &) { return x3::string("void"); }; auto const cdecl_ = "__cdecl" >> x3::space; auto const stdcall = "__stdcall" >> x3::space; #if defined(_WIN64)//seems to be necessary by msvc 14-x64 auto const thiscall = "__cdecl" >> x3::space; #else auto const thiscall = "__thiscall" >> x3::space; #endif template<typename Return, typename Arg> auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg)) { using namespace std; return type_rule<Arg>(ms.get_name<Arg>()); } template<typename Return, typename First, typename Second, typename ...Args> auto arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...)) { using next_type = Return (*)(Second, Args...); return type_rule<First>(ms.get_name<First>()) >> x3::char_(',') >> arg_list(ms, next_type()); } template<typename Return> auto arg_list(const mangled_storage_impl& /*ms*/, Return (*)()) { return x3::string("void"); } } template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const { using namespace std; using namespace boost; namespace x3 = spirit::x3; using namespace parser; auto type_name = get_name<T>(); auto matcher = -(visibility >> static_ >> x3::space) >> //it may be a static class-member parser::type_rule<T>(type_name) >> x3::space >> name; auto predicate = [&](const mangled_storage_base::entry & e) { if (e.demangled == name)//maybe not mangled, return true; auto itr = e.demangled.begin(); auto end = e.demangled.end(); auto res = x3::parse(itr, end, matcher); return res && (itr == end); }; auto found = std::find_if(storage_.begin(), storage_.end(), predicate); if (found != storage_.end()) return found->mangled; else return ""; } template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const { namespace x3 = spirit::x3; using namespace parser; using func_type = Func*; using return_type = typename function_traits<Func>::result_type; std::string return_type_name = get_name<return_type>(); auto matcher = -(visibility >> static_ >> x3::space) >> //it may be a static class-member, which does however not have the static attribute. parser::type_rule<return_type>(return_type_name) >> x3::space >> cdecl_ >> //cdecl declaration for methods. stdcall cannot be name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule(); auto predicate = [&](const mangled_storage_base::entry & e) { if (e.demangled == name)//maybe not mangled, return true; auto itr = e.demangled.begin(); auto end = e.demangled.end(); auto res = x3::parse(itr, end, matcher); return res && (itr == end); }; auto found = std::find_if(storage_.begin(), storage_.end(), predicate); if (found != storage_.end()) return found->mangled; else return ""; } template<typename Class, typename Func> std::string mangled_storage_impl::get_mem_fn(const std::string &name) const { namespace x3 = spirit::x3; using namespace parser; using func_type = Func*; using return_type = typename function_traits<Func>::result_type; auto return_type_name = get_name<return_type>(); auto cname = get_name<Class>(); auto matcher = visibility >> -virtual_ >> x3::space >> parser::type_rule<return_type>(return_type_name) >> x3::space >> thiscall >> //cdecl declaration for methods. stdcall cannot be cname >> "::" >> name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> inv_const_rule<Class>() >> inv_volatile_rule<Class>() >> parser::ptr_rule(); auto predicate = [&](const mangled_storage_base::entry & e) { auto itr = e.demangled.begin(); auto end = e.demangled.end(); auto res = x3::parse(itr, end, matcher); return res && (itr == end); }; auto found = std::find_if(storage_.begin(), storage_.end(), predicate); if (found != storage_.end()) return found->mangled; else return ""; } template<typename Signature> auto mangled_storage_impl::get_constructor() const -> ctor_sym { namespace x3 = spirit::x3; using namespace parser; using func_type = Signature*; std::string ctor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { auto class_name = get_return_type(dummy<Signature>()); auto pos = class_name.rfind("::"); if (pos == std::string::npos) { ctor_name = class_name+ "::" + class_name ; unscoped_cname = class_name; } else { unscoped_cname = class_name.substr(pos+2) ; ctor_name = class_name+ "::" + unscoped_cname; } } auto matcher = visibility >> x3::space >> thiscall >> //cdecl declaration for methods. stdcall cannot be ctor_name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule(); auto predicate = [&](const mangled_storage_base::entry & e) { auto itr = e.demangled.begin(); auto end = e.demangled.end(); auto res = x3::parse(itr, end, matcher); return res && (itr == end); }; auto f = std::find_if(storage_.begin(), storage_.end(), predicate); if (f != storage_.end()) return f->mangled; else return ""; } template<typename Class> auto mangled_storage_impl::get_destructor() const -> dtor_sym { namespace x3 = spirit::x3; using namespace parser; std::string dtor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { auto class_name = get_name<Class>(); auto pos = class_name.rfind("::"); if (pos == std::string::npos) { dtor_name = class_name+ "::~" + class_name + "(void)"; unscoped_cname = class_name; } else { unscoped_cname = class_name.substr(pos+2) ; dtor_name = class_name+ "::~" + unscoped_cname + "(void)"; } } auto matcher = visibility >> -virtual_ >> x3::space >> thiscall >> //cdecl declaration for methods. stdcall cannot be dtor_name >> parser::ptr_rule(); auto predicate = [&](const mangled_storage_base::entry & e) { auto itr = e.demangled.begin(); auto end = e.demangled.end(); auto res = x3::parse(itr, end, matcher); return res && (itr == end); }; auto found = std::find_if(storage_.begin(), storage_.end(), predicate); if (found != storage_.end()) return found->mangled; else return ""; } template<typename T> std::string mangled_storage_impl::get_vtable() const { std::string id = "const " + get_name<T>() + "::`vftable'"; auto predicate = [&](const mangled_storage_base::entry & e) { return e.demangled == id; }; auto found = std::find_if(storage_.begin(), storage_.end(), predicate); if (found != storage_.end()) return found->mangled; else return ""; } template<typename T> std::vector<std::string> mangled_storage_impl::get_related() const { std::vector<std::string> ret; auto name = get_name<T>(); for (auto & c : storage_) { if (c.demangled.find(name) != std::string::npos) ret.push_back(c.demangled); } return ret; } }}} #endif /* BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */ detail/demangling/itanium.hpp 0000644 00000034357 15125237303 0012307 0 ustar 00 // Copyright 2016 Klemens Morgenstern // // 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_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ #define BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ #include <boost/dll/detail/demangling/mangled_storage_base.hpp> #include <iterator> #include <algorithm> #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_volatile.hpp> #include <boost/type_traits/is_rvalue_reference.hpp> #include <boost/type_traits/is_lvalue_reference.hpp> #include <boost/type_traits/function_traits.hpp> namespace boost { namespace dll { namespace detail { class mangled_storage_impl : public mangled_storage_base { template<typename T> struct dummy {}; template<typename Return, typename ...Args> std::vector<std::string> get_func_params(dummy<Return(Args...)>) const { return {get_name<Args>()...}; } template<typename Return, typename ...Args> std::string get_return_type(dummy<Return(Args...)>) const { return get_name<Return>(); } public: using mangled_storage_base::mangled_storage_base; struct ctor_sym { std::string C1; std::string C2; std::string C3; bool empty() const { return C1.empty() && C2.empty() && C3.empty(); } }; struct dtor_sym { std::string D0; std::string D1; std::string D2; bool empty() const { return D0.empty() && D1.empty() && D2.empty(); } }; template<typename T> std::string get_variable(const std::string &name) const; template<typename Func> std::string get_function(const std::string &name) const; template<typename Class, typename Func> std::string get_mem_fn(const std::string &name) const; template<typename Signature> ctor_sym get_constructor() const; template<typename Class> dtor_sym get_destructor() const; template<typename T> std::string get_type_info() const; template<typename T> std::vector<std::string> get_related() const; }; namespace parser { //! declare template <typename... T> struct dummy; template <typename T> std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*); template <typename... T, template <typename...> class Tn> std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*); template <typename... T, template <typename...> class Tn> std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*); template <typename T> std::string parse_type(const mangled_storage_impl & ms, dummy<T>*); template <typename T1, typename T2, typename... T3> std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*); template <typename R, typename... Args> std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*); std::string parse_type(const mangled_storage_impl & ms, dummy<>*); template<typename T> std::string type_name(const mangled_storage_impl &); //The purpose of this class template is to separate the pure type from the rule name from the target type template<typename T> struct pure_type { typedef T type; inline static std::string type_rule() { return ""; } }; template<typename T> struct pure_type<T*> { typedef typename pure_type<T>::type type; inline static std::string type_rule() { return pure_type<T>::type_rule() + "*"; } }; template<typename T> struct pure_type<T const> { typedef typename pure_type<T>::type type; inline static std::string type_rule() { return pure_type<T>::type_rule() + " const"; } }; template<typename T> struct pure_type<T volatile> { typedef typename pure_type<T>::type type; inline static std::string type_rule() { return pure_type<T>::type_rule() + " volatile"; } }; template<typename T> struct pure_type<T const volatile> { typedef typename pure_type<T>::type type; inline static std::string type_rule() { return pure_type<T>::type_rule() + " const volatile"; } }; template<typename T> struct pure_type<T&> { typedef typename pure_type<T>::type type; inline static std::string type_rule() { return pure_type<T>::type_rule() + "&"; } }; template<typename T> struct pure_type<T&&> { typedef typename pure_type<T>::type type; inline static std::string type_rule() { return pure_type<T>::type_rule() + "&&"; } }; inline std::string const_rule_impl(true_type ) {return " const";} inline std::string const_rule_impl(false_type) {return "";} template<typename T> std::string const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());} inline std::string volatile_rule_impl(true_type ) {return " volatile";} inline std::string volatile_rule_impl(false_type) {return "";} template<typename T> std::string volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());} inline std::string reference_rule_impl(false_type, false_type) {return "";} inline std::string reference_rule_impl(true_type, false_type) {return "&" ;} inline std::string reference_rule_impl(false_type, true_type ) {return "&&";} template<typename T> std::string reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());} //it takes a string, because it may be overloaded. template<typename Return, typename Arg> std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg)) { using namespace std; return type_name<Arg>(ms); } template<typename Return, typename First, typename Second, typename ...Args> std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...)) { using next_type = Return (*)(Second, Args...); return type_name<First>(ms) + ", " + arg_list(ms, next_type()); } template<typename Return> std::string arg_list(const mangled_storage_impl &, Return (*)()) { return ""; } //! implement template <typename T> inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*) { return ms.get_name<T>(); } template <typename... T, template <typename...> class Tn> inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*) { using type = dummy<Tn<T...>>*; return parse_type(ms, type()); } template <typename R, typename... Args> inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(*)(Args...)>*) { using args_type = dummy<Args...>*; using return_type = dummy<R>*; return parse_type(ms, return_type()) + " (*)(" + parse_type(ms, args_type()) + ")"; } template <typename R, typename... Args> inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*) { using args_type = dummy<Args...>*; using return_type = dummy<R>*; return parse_type(ms, return_type()) + " (" + parse_type(ms, args_type()) + ")"; } template <typename T> inline std::string parse_type(const mangled_storage_impl & ms, dummy<T>*) { using type = dummy<typename pure_type<T>::type>*; auto str = parse_type_helper(ms, type()); return str + pure_type<T>::type_rule(); } template <typename T1, typename T2, typename... T3> inline std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*) { using first_type = dummy<T1>*; using next_type = dummy<T2, T3...>*; return parse_type(ms, first_type()) + ", " + parse_type(ms, next_type()); } template <typename... T, template <typename...> class Tn> inline std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*) { using next_type = dummy<T...>*; std::string str = ms.get_name<Tn<T...>>(); auto frist = str.find_first_of("<"); std::string template_name = str.substr(0, frist); std::string args_name = parse_type(ms, next_type()); char last_ch = args_name[args_name.size() - 1]; return template_name + "<" + args_name + (last_ch == '>' ? " >" : ">"); } inline std::string parse_type(const mangled_storage_impl &, dummy<>*) { return ""; } template<typename T> inline std::string type_name(const mangled_storage_impl &ms) { using namespace parser; using type = dummy<T>*; return parse_type(ms, type()); } } template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const { auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == name;}); if (found != storage_.end()) return found->mangled; else return ""; } template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const { using func_type = Func*; auto matcher = name + '(' + parser::arg_list(*this, func_type()) + ')'; auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;}); if (found != storage_.end()) return found->mangled; else return ""; } template<typename Class, typename Func> std::string mangled_storage_impl::get_mem_fn(const std::string &name) const { using namespace parser; using func_type = Func*; std::string cname = get_name<Class>(); const auto matcher = cname + "::" + name + '(' + parser::arg_list(*this, func_type()) + ')' + const_rule<Class>() + volatile_rule<Class>(); // Linux export table contains int MyClass::Func<float>(), but expected in import_mangled MyClass::Func<float>() without returned type. auto found = std::find_if(storage_.begin(), storage_.end(), [&matcher](const entry& e) { if (e.demangled == matcher) { return true; } const auto pos = e.demangled.rfind(matcher); if (pos == std::string::npos) { // Not found. return false; } if (pos + matcher.size() != e.demangled.size()) { // There are some characters after the `matcher` string. return false; } // Double checking that we matched a full function name return e.demangled[pos - 1] == ' '; // `if (e.demangled == matcher)` makes sure that `pos > 0` }); if (found != storage_.end()) return found->mangled; else return ""; } template<typename Signature> auto mangled_storage_impl::get_constructor() const -> ctor_sym { using namespace parser; using func_type = Signature*; std::string ctor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { auto class_name = get_return_type(dummy<Signature>()); auto pos = class_name.rfind("::"); if (pos == std::string::npos) { ctor_name = class_name+ "::" +class_name ; unscoped_cname = class_name; } else { unscoped_cname = class_name.substr(pos+2) ; ctor_name = class_name+ "::" + unscoped_cname; } } auto matcher = ctor_name + '(' + parser::arg_list(*this, func_type()) + ')'; std::vector<entry> findings; std::copy_if(storage_.begin(), storage_.end(), std::back_inserter(findings), [&](const entry& e) {return e.demangled == matcher;}); ctor_sym ct; for (auto & e : findings) { if (e.mangled.find(unscoped_cname +"C1E") != std::string::npos) ct.C1 = e.mangled; else if (e.mangled.find(unscoped_cname +"C2E") != std::string::npos) ct.C2 = e.mangled; else if (e.mangled.find(unscoped_cname +"C3E") != std::string::npos) ct.C3 = e.mangled; } return ct; } template<typename Class> auto mangled_storage_impl::get_destructor() const -> dtor_sym { std::string dtor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { auto class_name = get_name<Class>(); auto pos = class_name.rfind("::"); if (pos == std::string::npos) { dtor_name = class_name+ "::~" + class_name + "()"; unscoped_cname = class_name; } else { unscoped_cname = class_name.substr(pos+2) ; dtor_name = class_name+ "::~" + unscoped_cname + "()"; } } auto d0 = unscoped_cname + "D0Ev"; auto d1 = unscoped_cname + "D1Ev"; auto d2 = unscoped_cname + "D2Ev"; dtor_sym dt; //this is so simple, i don#t need a predicate for (auto & s : storage_) { //alright, name fits if (s.demangled == dtor_name) { if (s.mangled.find(d0) != std::string::npos) dt.D0 = s.mangled; else if (s.mangled.find(d1) != std::string::npos) dt.D1 = s.mangled; else if (s.mangled.find(d2) != std::string::npos) dt.D2 = s.mangled; } } return dt; } template<typename T> std::string mangled_storage_impl::get_type_info() const { std::string id = "typeinfo for " + get_name<T>(); auto predicate = [&](const mangled_storage_base::entry & e) { return e.demangled == id; }; auto found = std::find_if(storage_.begin(), storage_.end(), predicate); if (found != storage_.end()) return found->mangled; else return ""; } template<typename T> std::vector<std::string> mangled_storage_impl::get_related() const { std::vector<std::string> ret; auto name = get_name<T>(); for (auto & c : storage_) { if (c.demangled.find(name) != std::string::npos) ret.push_back(c.demangled); } return ret; } }}} #endif /* BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ */ detail/import_mangled_helpers.hpp 0000644 00000020334 15125237303 0013245 0 ustar 00 // Copyright 2015-2018 Klemens D. Morgenstern // // 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_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ #define BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ #include <boost/type_traits/conditional.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_class.hpp> #include <boost/type_traits/is_function.hpp> #include <boost/type_traits/remove_cv.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { namespace experimental { namespace detail { //the following could be done by fusion, though it's simple enough to just declare it here. template<class ...Args> struct sequence {}; template<class Value, class Seq> struct push_front; template<class Value, class ...Args> struct push_front<Value, sequence<Args...>> { typedef sequence<Value, Args...> type; }; template<class Lhs, class Rhs> struct unqalified_is_same : boost::is_same< typename boost::remove_cv<Lhs>::type, typename boost::remove_cv<Rhs>::type > { }; /* ********************************** function sequence type traits ******************************/ //determine if it's a sequence of functions. template<class T> struct is_function_seq; //type-trait for function overloads template<class Class, class...Args> struct is_function_seq<sequence<Class, Args...>> : boost::conditional< boost::is_function<Class>::value, is_function_seq<sequence<Args...>>, boost::false_type>::type {}; template<class Class> struct is_function_seq<sequence<Class>> : boost::is_function<Class> { }; template<> struct is_function_seq<sequence<>> : boost::false_type { }; /* ********************************* Function Tuple *************************** */ //a tuple of plain functions. template <class ...Ts> struct function_tuple; template <class Return, class...Args, class T2, class ...Ts> struct function_tuple<Return(Args...), T2, Ts...> : function_tuple<T2, Ts...> { Return(*f_)(Args...); constexpr function_tuple(Return(* t)(Args...), T2* t2, Ts* ... ts) : function_tuple<T2, Ts...>(t2, ts...) , f_(t) {} Return operator()(Args...args) const { return (*f_)(static_cast<Args>(args)...); } using function_tuple<T2, Ts...>::operator(); }; template <class Return, class...Args> struct function_tuple<Return(Args...)> { Return(*f_)(Args...); constexpr function_tuple(Return(* t)(Args...)) : f_(t) {} Return operator()(Args...args) const { return (*f_)(static_cast<Args>(args)...); } }; /* ********************************** MemFn sequence type traits ******************************/ template<class Class, class Func> struct mem_fn_def { typedef Class class_type; typedef Func func_type; typedef typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn mem_fn; }; template<class ...Args> struct make_mem_fn_seq; // B: is T1 another version of T0? template<bool, class T0, class T1, class T2> struct make_mem_fn_seq_getter; template<class T0, class T1, class T2> struct make_mem_fn_seq_getter<true, T0, T1, T2> { typedef mem_fn_def<T1, T2> type; }; template<class T0, class T1, class T2> struct make_mem_fn_seq_getter<false, T0, T1, T2> { typedef mem_fn_def<T0, T1> type; }; template<class Class, class Signature> struct make_mem_fn_seq<Class, Signature> { typedef mem_fn_def<Class, Signature> mem_fn; typedef sequence<mem_fn> type; }; template<class Class> struct make_mem_fn_seq<Class> { typedef sequence<> type; }; template<class T0, class T1, class T2, class ... Args> struct make_mem_fn_seq<T0, T1, T2, Args...> { /* Since we might have ovls, it might be : * Class, void(int), void(int, int) //--> just us class for both * Class, const Class, void(int)//--> ovl class. * */ static_assert(boost::is_object<T0>::value, ""); typedef typename make_mem_fn_seq_getter< unqalified_is_same<T0, T1>::value, T0, T1, T2>::type mem_fn_type; typedef typename boost::conditional< unqalified_is_same<T0, T1>::value, make_mem_fn_seq<T1, Args...>, make_mem_fn_seq<T0, T2, Args...>> ::type next; typedef typename push_front<mem_fn_type, typename next::type>::type type; }; /* Ok, this needs to be documented, so here's some pseudo-code: * * @code * * bool unqalified_is_same(lhs, rhs) * { * return remove_cv(lhs) == remove_cv(rhs); * } * * mem_fn make_mem_fn_seq_getter(b, cl, T2, T3) * { * if (b) //b means, that T2 is another version of cl, i.e. qualified * return get_mem_fn_type(T2, T3); * else //means that T2 is a function. * return get_mem_fn_type(cl, T2); * } * * sequence make_mem_fn_seq(type cl, type T2, type T3, types...) * { * mem_fn = make_mem_fn_seq_getter( * unqalified_is_same(cl, T2), cl, T2, T3); * * next = unqalified_is_same(cl, T2) ? * make_mem_fn_seq(T2, types...) //because: T2 is another version of cl, hence i use this. T3 was already consumed. * : * make_mem_fn_seq(Class, T3, types...) //because: T2 was a function, hence it is consumed and class remains unchanged. * ; * return push_front(mem_fn, next) ; * }; * @endcode */ template<class T, class U, class ...Args> struct is_mem_fn_seq_impl { typedef typename boost::conditional< boost::is_function<U>::value || boost::dll::experimental::detail::unqalified_is_same<T, U>::value, typename is_mem_fn_seq_impl<T, Args...>::type, boost::false_type>::type type; }; template<class T, class U> struct is_mem_fn_seq_impl<T, U> { typedef typename boost::conditional< boost::is_function<U>::value && boost::is_object<T>::value, boost::true_type, boost::false_type>::type type; }; template<class T, class U, class Last> struct is_mem_fn_seq_impl<T, U, Last> { typedef typename boost::conditional< (boost::is_function<U>::value || boost::dll::experimental::detail::unqalified_is_same<T, U>::value) && boost::is_function<Last>::value, boost::true_type, boost::false_type>::type type; }; template<class T> struct is_mem_fn_seq : boost::false_type {}; //If only two arguments are provided at all. template<class T, class U> struct is_mem_fn_seq<sequence<T, U>> : boost::conditional< boost::is_object<T>::value && boost::is_function<U>::value, boost::true_type, boost::false_type>::type { }; template<class T, class Func, class ...Args> struct is_mem_fn_seq<sequence<T, Func, Args...>> : boost::conditional< boost::is_class<T>::value && boost::is_function<Func>::value, typename is_mem_fn_seq_impl<T, Args...>::type, boost::false_type>::type {}; /* ********************************** mem fn sequence tuple ******************************/ /* A tuple of member functions * Unlike for plain functions a sequence here might contain classes as well as functions. */ template <class ...Ts> struct mem_fn_tuple; template <class Class, class Return, class...Args, class T2, class ...Ts> struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>, T2, Ts...> : mem_fn_tuple<T2, Ts...> { typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn; mem_fn f_; constexpr mem_fn_tuple(mem_fn f, typename T2::mem_fn t2, typename Ts::mem_fn ... ts) : mem_fn_tuple<T2, Ts...>(t2, ts...) , f_(f) {} Return operator()(Class* const cl, Args...args) const { return (cl->*f_)(static_cast<Args>(args)...); } using mem_fn_tuple<T2, Ts...>::operator(); }; template <class Class, class Return, class...Args> struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>> { typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn; mem_fn f_; constexpr mem_fn_tuple(mem_fn f) : f_(f) {} Return operator()(Class * const cl, Args...args) const { return (cl->*f_)(static_cast<Args>(args)...); } }; }}}} #endif /* BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ */ detail/type_info.hpp 0000644 00000005164 15125237303 0010522 0 ustar 00 // Copyright 2016 Klemens Morgenstern, Antony Polukhin // // 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) // For more information, see http://www.boost.org #ifndef BOOST_DLL_DETAIL_TYPE_INFO_HPP_ #define BOOST_DLL_DETAIL_TYPE_INFO_HPP_ #include <typeinfo> #include <cstring> #include <boost/dll/config.hpp> #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows #include <boost/winapi/basic_types.hpp> #endif namespace boost { namespace dll { namespace detail { #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows #if defined ( _WIN64 ) template<typename Class, typename Lib, typename Storage> const std::type_info& load_type_info(Lib & lib, Storage & storage) { struct RTTICompleteObjectLocator { boost::winapi::DWORD_ signature; //always zero ? boost::winapi::DWORD_ offset; //offset of this vtable in the complete class boost::winapi::DWORD_ cdOffset; //constructor displacement offset boost::winapi::DWORD_ pTypeDescriptorOffset; //TypeDescriptor of the complete class boost::winapi::DWORD_ pClassDescriptorOffset; //describes inheritance hierarchy (ignored) }; RTTICompleteObjectLocator** vtable_p = &lib.template get<RTTICompleteObjectLocator*>(storage.template get_vtable<Class>()); vtable_p--; auto vtable = *vtable_p; auto nat = reinterpret_cast<const char*>(lib.native()); nat += vtable->pTypeDescriptorOffset; return *reinterpret_cast<const std::type_info*>(nat); } #else template<typename Class, typename Lib, typename Storage> const std::type_info& load_type_info(Lib & lib, Storage & storage) { struct RTTICompleteObjectLocator { boost::winapi::DWORD_ signature; //always zero ? boost::winapi::DWORD_ offset; //offset of this vtable in the complete class boost::winapi::DWORD_ cdOffset; //constructor displacement offset const std::type_info* pTypeDescriptor; //TypeDescriptor of the complete class void* pClassDescriptor; //describes inheritance hierarchy (ignored) }; RTTICompleteObjectLocator** vtable_p = &lib.template get<RTTICompleteObjectLocator*>(storage.template get_vtable<Class>()); vtable_p--; auto vtable = *vtable_p; return *vtable->pTypeDescriptor; } #endif //_WIN64 #else template<typename Class, typename Lib, typename Storage> const std::type_info& load_type_info(Lib & lib, Storage & storage) { return lib.template get<const std::type_info>(storage.template get_type_info<Class>()); } #endif }}} #endif /* BOOST_DLL_DETAIL_TYPE_INFO_HPP_ */ detail/aggressive_ptr_cast.hpp 0000644 00000011223 15125237303 0012555 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP #define BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP #include <boost/dll/config.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif #include <boost/core/addressof.hpp> #include <boost/core/enable_if.hpp> #include <boost/static_assert.hpp> #include <boost/type_traits/is_pointer.hpp> #include <boost/type_traits/is_member_pointer.hpp> #include <boost/type_traits/is_void.hpp> #include <boost/type_traits/is_reference.hpp> #include <boost/type_traits/remove_pointer.hpp> #include <boost/type_traits/remove_reference.hpp> #include <cstring> // std::memcpy #if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 301) # pragma GCC system_header #endif namespace boost { namespace dll { namespace detail { // GCC warns when reinterpret_cast between function pointer and object pointer occur. // This method suppress the warnings and ensures that such casts are safe. template <class To, class From> BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From v) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG( boost::is_pointer<To>::value && boost::is_pointer<From>::value, "`agressive_ptr_cast` function must be used only for pointer casting." ); BOOST_STATIC_ASSERT_MSG( boost::is_void< typename boost::remove_pointer<To>::type >::value || boost::is_void< typename boost::remove_pointer<From>::type >::value, "`agressive_ptr_cast` function must be used only for casting to or from void pointers." ); BOOST_STATIC_ASSERT_MSG( sizeof(v) == sizeof(To), "Pointer to function and pointer to object differ in size on your platform." ); return reinterpret_cast<To>(v); } #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable: 4172) // "returning address of local variable or temporary" but **v is not local! #endif template <class To, class From> BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From v) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG( boost::is_pointer<From>::value, "`agressive_ptr_cast` function must be used only for pointer casting." ); BOOST_STATIC_ASSERT_MSG( boost::is_void< typename boost::remove_pointer<From>::type >::value, "`agressive_ptr_cast` function must be used only for casting to or from void pointers." ); BOOST_STATIC_ASSERT_MSG( sizeof(v) == sizeof(typename boost::remove_reference<To>::type*), "Pointer to function and pointer to object differ in size on your platform." ); return static_cast<To>( **reinterpret_cast<typename boost::remove_reference<To>::type**>( v ) ); } #ifdef BOOST_MSVC # pragma warning(pop) #endif template <class To, class From> BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_member_pointer<To>::value || boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From v) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG( boost::is_pointer<From>::value, "`agressive_ptr_cast` function must be used only for pointer casting." ); BOOST_STATIC_ASSERT_MSG( boost::is_void< typename boost::remove_pointer<From>::type >::value, "`agressive_ptr_cast` function must be used only for casting to or from void pointers." ); To res = 0; std::memcpy(&res, &v, sizeof(From)); return res; } template <class To, class From> BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || !boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From /* v */) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG( boost::is_pointer<To>::value, "`agressive_ptr_cast` function must be used only for pointer casting." ); BOOST_STATIC_ASSERT_MSG( boost::is_void< typename boost::remove_pointer<To>::type >::value, "`agressive_ptr_cast` function must be used only for casting to or from void pointers." ); BOOST_STATIC_ASSERT_MSG( !sizeof(From), "Casting from member pointers to void pointer is not implemnted in `agressive_ptr_cast`." ); return 0; } }}} // boost::dll::detail #endif // BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP import_class.hpp 0000644 00000050720 15125237303 0007761 0 ustar 00 // Copyright 2015-2018 Klemens D. Morgenstern // Copyright 2019-2020 Antony Polukhin // // 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_DLL_IMPORT_CLASS_HPP_ #define BOOST_DLL_IMPORT_CLASS_HPP_ /// \file boost/dll/import_class.hpp /// \warning Extremely experimental! Requires C++11! Will change in next version of Boost! boost/dll/import_class.hpp is not included in boost/dll.hpp /// \brief Contains the boost::dll::experimental::import_class function for importing classes. #include <boost/dll/smart_library.hpp> #include <boost/dll/import_mangled.hpp> #include <memory> #if (__cplusplus < 201103L) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201103L) # error This file requires C++11 at least! #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { namespace experimental { namespace detail { template<typename T> struct deleter { destructor<T> dtor; bool use_deleting; deleter(const destructor<T> & dtor, bool use_deleting = false) : dtor(dtor), use_deleting(use_deleting) {} void operator()(T*t) { if (use_deleting) dtor.call_deleting(t); else { dtor.call_standard(t); //the thing is actually an array, so delete[] auto p = reinterpret_cast<char*>(t); delete [] p; } } }; template<class T, class = void> struct mem_fn_call_proxy; template<class Class, class U> struct mem_fn_call_proxy<Class, boost::dll::experimental::detail::mangled_library_mem_fn<Class, U>> { typedef boost::dll::experimental::detail::mangled_library_mem_fn<Class, U> mem_fn_t; Class* t; mem_fn_t & mem_fn; mem_fn_call_proxy(mem_fn_call_proxy&&) = default; mem_fn_call_proxy(const mem_fn_call_proxy & ) = delete; mem_fn_call_proxy(Class * t, mem_fn_t & mem_fn) : t(t), mem_fn(mem_fn) {} template<typename ...Args> auto operator()(Args&&...args) const { return mem_fn(t, std::forward<Args>(args)...); } }; template<class T, class Return, class ...Args> struct mem_fn_call_proxy<T, Return(Args...)> { T* t; const std::string &name; smart_library &_lib; mem_fn_call_proxy(mem_fn_call_proxy&&) = default; mem_fn_call_proxy(const mem_fn_call_proxy&) = delete; mem_fn_call_proxy(T *t, const std::string &name, smart_library & _lib) : t(t), name(name), _lib(_lib) {}; Return operator()(Args...args) const { auto f = _lib.get_mem_fn<T, Return(Args...)>(name); return (t->*f)(static_cast<Args>(args)...); } }; } template<typename T> class imported_class; template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib, Args...args); template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib, const std::string & alias_name, Args...args); template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib, std::size_t size, Args...args); template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib, std::size_t size, const std::string & alias_name, Args...args); /*! This class represents an imported class. * * \note It must be constructed via \ref boost::dll::import_class(const smart_library& lib, std::size_t, Args...) * * \tparam The type or type-alias of the imported class. */ template<typename T> class imported_class { smart_library _lib; std::unique_ptr<T, detail::deleter<T>> _data; bool _is_allocating; std::size_t _size; const std::type_info& _ti; template<typename ... Args> inline std::unique_ptr<T, detail::deleter<T>> make_data(const smart_library& lib, Args ... args); template<typename ... Args> inline std::unique_ptr<T, detail::deleter<T>> make_data(const smart_library& lib, std::size_t size, Args...args); template<typename ...Args> imported_class(detail::sequence<Args...> *, const smart_library& lib, Args...args); template<typename ...Args> imported_class(detail::sequence<Args...> *, const smart_library& lib, std::size_t size, Args...args); template<typename ...Args> imported_class(detail::sequence<Args...> *, smart_library&& lib, Args...args); template<typename ...Args> imported_class(detail::sequence<Args...> *, smart_library&& lib, std::size_t size, Args...args); public: //alias to construct with explicit parameter list template<typename ...Args> static imported_class<T> make(smart_library&& lib, Args...args) { typedef detail::sequence<Args...> *seq; return imported_class(seq(), boost::move(lib), static_cast<Args>(args)...); } template<typename ...Args> static imported_class<T> make(smart_library&& lib, std::size_t size, Args...args) { typedef detail::sequence<Args...> *seq; return imported_class(seq(), boost::move(lib), size, static_cast<Args>(args)...); } template<typename ...Args> static imported_class<T> make(const smart_library& lib, Args...args) { typedef detail::sequence<Args...> *seq; return imported_class(seq(), lib, static_cast<Args>(args)...); } template<typename ...Args> static imported_class<T> make(const smart_library& lib, std::size_t size, Args...args) { typedef detail::sequence<Args...> *seq; return imported_class(seq(), lib, size, static_cast<Args>(args)...); } typedef imported_class<T> base_t; ///Returns a pointer to the underlying class T* get() {return _data.get();} imported_class() = delete; imported_class(imported_class&) = delete; imported_class(imported_class&&) = default; ///<Move constructor imported_class& operator=(imported_class&) = delete; imported_class& operator=(imported_class&&) = default; ///<Move assignmend ///Check if the imported class is move-constructible bool is_move_constructible() {return !_lib.symbol_storage().template get_constructor<T(T&&)> ().empty();} ///Check if the imported class is move-assignable bool is_move_assignable() {return !_lib.symbol_storage().template get_mem_fn<T, T&(T&&)> ("operator=").empty();} ///Check if the imported class is copy-constructible bool is_copy_constructible() {return !_lib.symbol_storage().template get_constructor<T(const T&)>().empty();} ///Check if the imported class is copy-assignable bool is_copy_assignable() {return !_lib.symbol_storage().template get_mem_fn<T, T&(const T&)>("operator=").empty();} imported_class<T> copy() const; ///<Invoke the copy constructor. \attention Undefined behaviour if the imported object is not copy constructible. imported_class<T> move(); ///<Invoke the move constructor. \attention Undefined behaviour if the imported object is not move constructible. ///Invoke the copy assignment. \attention Undefined behaviour if the imported object is not copy assignable. void copy_assign(const imported_class<T> & lhs) const; ///Invoke the move assignment. \attention Undefined behaviour if the imported object is not move assignable. void move_assign( imported_class<T> & lhs); ///Check if the class is loaded. explicit operator bool() const {return _data;} ///Get a const reference to the std::type_info. const std::type_info& get_type_info() {return _ti;}; /*! Call a member function. This returns a proxy to the function. * The proxy mechanic mechanic is necessary, so the signaute can be passed. * * \b Example * * \code * im_class.call<void(const char*)>("function_name")("MyString"); * \endcode */ template<class Signature> const detail::mem_fn_call_proxy<T, Signature> call(const std::string& name) { return detail::mem_fn_call_proxy<T, Signature>(_data.get(), name, _lib); } /*! Call a qualified member function, i.e. const and or volatile. * * \b Example * * \code * im_class.call<const type_alias, void(const char*)>("function_name")("MyString"); * \endcode */ template<class Tin, class Signature, class = boost::enable_if<detail::unqalified_is_same<T, Tin>>> const detail::mem_fn_call_proxy<Tin, Signature> call(const std::string& name) { return detail::mem_fn_call_proxy<Tin, Signature>(_data.get(), name, _lib); } ///Overload of ->* for an imported method. template<class Tin, class T2> const detail::mem_fn_call_proxy<Tin, boost::dll::experimental::detail::mangled_library_mem_fn<Tin, T2>> operator->*(detail::mangled_library_mem_fn<Tin, T2>& mn) { return detail::mem_fn_call_proxy<Tin, boost::dll::experimental::detail::mangled_library_mem_fn<Tin, T2>>(_data.get(), mn); } ///Import a method of the class. template <class ...Args> typename boost::dll::experimental::detail::mangled_import_type<boost::dll::experimental::detail::sequence<T, Args...>>::type import(const std::string & name) { return boost::dll::experimental::import_mangled<T, Args...>(_lib, name); } }; //helper function, uses the allocating template<typename T> template<typename ... Args> inline std::unique_ptr<T, detail::deleter<T>> imported_class<T>::make_data(const smart_library& lib, Args ... args) { constructor<T(Args...)> ctor = lib.get_constructor<T(Args...)>(); destructor<T> dtor = lib.get_destructor <T>(); if (!ctor.has_allocating() || !dtor.has_deleting()) { boost::dll::fs::error_code ec; ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); // report_error() calls dlsym, do not use it here! boost::throw_exception( boost::dll::fs::system_error( ec, "boost::dll::detail::make_data() failed: no allocating ctor or dtor was found" ) ); } return std::unique_ptr<T, detail::deleter<T>> ( ctor.call_allocating(static_cast<Args>(args)...), detail::deleter<T>(dtor, false /* not deleting dtor*/)); } //helper function, using the standard template<typename T> template<typename ... Args> inline std::unique_ptr<T, detail::deleter<T>> imported_class<T>::make_data(const smart_library& lib, std::size_t size, Args...args) { constructor<T(Args...)> ctor = lib.get_constructor<T(Args...)>(); destructor<T> dtor = lib.get_destructor <T>(); if (!ctor.has_standard() || !dtor.has_standard()) { boost::dll::fs::error_code ec; ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); // report_error() calls dlsym, do not use it here! boost::throw_exception( boost::dll::fs::system_error( ec, "boost::dll::detail::make_data() failed: no regular ctor or dtor was found" ) ); } T *data = reinterpret_cast<T*>(new char[size]); ctor.call_standard(data, static_cast<Args>(args)...); return std::unique_ptr<T, detail::deleter<T>> ( reinterpret_cast<T*>(data), detail::deleter<T>(dtor, false /* not deleting dtor*/)); } template<typename T> template<typename ...Args> imported_class<T>::imported_class(detail::sequence<Args...> *, const smart_library & lib, Args...args) : _lib(lib), _data(make_data<Args...>(lib, static_cast<Args>(args)...)), _is_allocating(false), _size(0), _ti(lib.get_type_info<T>()) { } template<typename T> template<typename ...Args> imported_class<T>::imported_class(detail::sequence<Args...> *, const smart_library & lib, std::size_t size, Args...args) : _lib(lib), _data(make_data<Args...>(lib, size, static_cast<Args>(args)...)), _is_allocating(true), _size(size), _ti(lib.get_type_info<T>()) { } template<typename T> template<typename ...Args> imported_class<T>::imported_class(detail::sequence<Args...> *, smart_library && lib, Args...args) : _lib(boost::move(lib)), _data(make_data<Args...>(lib, static_cast<Args>(args)...)), _is_allocating(false), _size(0), _ti(lib.get_type_info<T>()) { } template<typename T> template<typename ...Args> imported_class<T>::imported_class(detail::sequence<Args...> *, smart_library && lib, std::size_t size, Args...args) : _lib(boost::move(lib)), _data(make_data<Args...>(lib, size, static_cast<Args>(args)...)), _is_allocating(true), _size(size), _ti(lib.get_type_info<T>()) { } template<typename T> inline imported_class<T> boost::dll::experimental::imported_class<T>::copy() const { if (this->_is_allocating) return imported_class<T>::template make<const T&>(_lib, *_data); else return imported_class<T>::template make<const T&>(_lib, _size, *_data); } template<typename T> inline imported_class<T> boost::dll::experimental::imported_class<T>::move() { if (this->_is_allocating) return imported_class<T>::template make<T&&>(_lib, *_data); else return imported_class<T>::template make<T&&>(_lib, _size, *_data); } template<typename T> inline void boost::dll::experimental::imported_class<T>::copy_assign(const imported_class<T>& lhs) const { this->call<T&(const T&)>("operator=")(*lhs._data); } template<typename T> inline void boost::dll::experimental::imported_class<T>::move_assign(imported_class<T>& lhs) { this->call<T&(T&&)>("operator=")(static_cast<T&&>(*lhs._data)); } /*! * Returns an instance of \ref imported_class which allows to call or import more functions. * It takes a copy of the smart_libray, so no added type_aliases will be visible, * for the object. * * Few compilers do implement an allocating constructor, which allows the construction * of the class without knowing the size. That is not portable, so the actual size of the class * shall always be provided. * * \b Example: * * \code * auto import_class<class type_alias, const std::string&, std::size_t>(lib, "class_name", 20, "param1", 42); * \endcode * * In this example we construct an instance of the class "class_name" with the size 20, which has "type_alias" as an alias, * through a constructor which takes a const-ref of std::string and an std::size_t parameter. * * \tparam T Class type or alias * \tparam Args Constructor argument list. * \param lib Path to shared library or shared library to load function from. * \param name Null-terminated C or C++ mangled name of the function to import. Can handle std::string, char*, const char*. * \param mode An mode that will be used on library load. * * \return class object. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. * Overload that accepts path also throws std::bad_alloc in case of insufficient memory. */ template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib_, std::size_t size, Args...args) { smart_library lib(lib_); return imported_class<T>::template make<Args...>(boost::move(lib), size, static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib_, Args...args) { smart_library lib(lib_); return imported_class<T>::template make<Args...>(boost::move(lib), static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib_, const std::string & alias_name, Args...args) { smart_library lib(lib_); lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(boost::move(lib), static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib_, std::size_t size, const std::string & alias_name, Args...args) { smart_library lib(lib_); lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(boost::move(lib), size, static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(const smart_library& lib_, const std::string & alias_name, std::size_t size, Args...args) { smart_library lib(lib_); lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(boost::move(lib), size, static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(smart_library && lib, Args...args) { return imported_class<T>::template make<Args...>(boost::move(lib), static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(smart_library && lib, const std::string & alias_name, Args...args) { lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(boost::move(lib), static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(smart_library && lib, std::size_t size, Args...args) { return imported_class<T>::template make<Args...>(boost::move(lib), size, static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(smart_library && lib, std::size_t size, const std::string & alias_name, Args...args) { lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(boost::move(lib), size, static_cast<Args>(args)...); } //! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) template<typename T, typename ... Args> imported_class<T> import_class(smart_library && lib, const std::string & alias_name, std::size_t size, Args...args) { lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(boost::move(lib), size, static_cast<Args>(args)...); } /*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. */ template<typename T, typename ... Args> imported_class<T> import_class(smart_library & lib, Args...args) { return imported_class<T>::template make<Args...>(lib, static_cast<Args>(args)...); } /*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. */ template<typename T, typename ... Args> imported_class<T> import_class(smart_library & lib, const std::string & alias_name, Args...args) { lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(lib, static_cast<Args>(args)...); } /*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. */ template<typename T, typename ... Args> imported_class<T> import_class(smart_library & lib, std::size_t size, Args...args) { return imported_class<T>::template make<Args...>(lib, size, static_cast<Args>(args)...); } /*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. */ template<typename T, typename ... Args> imported_class<T> import_class(smart_library & lib, std::size_t size, const std::string & alias_name, Args...args) { lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(lib, size, static_cast<Args>(args)...); } /*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. */ template<typename T, typename ... Args> imported_class<T> import_class(smart_library & lib, const std::string & alias_name, std::size_t size, Args...args) { lib.add_type_alias<T>(alias_name); return imported_class<T>::template make<Args...>(lib, size, static_cast<Args>(args)...); } } } } #endif /* BOOST_DLL_IMPORT_CLASS_HPP_ */ import.hpp 0000644 00000025026 15125237303 0006575 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_IMPORT_HPP #define BOOST_DLL_IMPORT_HPP #include <boost/dll/config.hpp> #include <boost/core/addressof.hpp> #include <boost/core/enable_if.hpp> #include <boost/type_traits/is_object.hpp> #include <boost/make_shared.hpp> #include <boost/dll/shared_library.hpp> #include <boost/move/move.hpp> #if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) # include <boost/function.hpp> #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif /// \file boost/dll/import.hpp /// \brief Contains all the boost::dll::import* reference counting /// functions that hold a shared pointer to the instance of /// boost::dll::shared_library. namespace boost { namespace dll { namespace detail { template <class T> class library_function { // Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster. boost::shared_ptr<T> f_; public: inline library_function(const boost::shared_ptr<shared_library>& lib, T* func_ptr) BOOST_NOEXCEPT : f_(lib, func_ptr) {} #if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) operator T*() const BOOST_NOEXCEPT { return f_.get(); } #else // Compilation error at this point means that imported function // was called with unmatching parameters. // // Example: // auto f = dll::import<void(int)>("function", "lib.so"); // f("Hello"); // error: invalid conversion from 'const char*' to 'int' // f(1, 2); // error: too many arguments to function // f(); // error: too few arguments to function template <class... Args> inline auto operator()(Args&&... args) const -> decltype( (*f_)(static_cast<Args&&>(args)...) ) { return (*f_)(static_cast<Args&&>(args)...); } #endif }; template <class T, class = void> struct import_type; template <class T> struct import_type<T, typename boost::disable_if<boost::is_object<T> >::type> { typedef boost::dll::detail::library_function<T> base_type; #if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) typedef boost::function<T> type; #else typedef boost::dll::detail::library_function<T> type; #endif }; template <class T> struct import_type<T, typename boost::enable_if<boost::is_object<T> >::type> { typedef boost::shared_ptr<T> base_type; typedef boost::shared_ptr<T> type; }; } // namespace detail #ifndef BOOST_DLL_DOXYGEN # define BOOST_DLL_IMPORT_RESULT_TYPE inline typename boost::dll::detail::import_type<T>::type #endif /*! * Returns callable object or boost::shared_ptr<T> that holds the symbol imported * from the loaded library. Returned value refcounts usage * of the loaded shared library, so that it won't get unload until all copies of return value * are not destroyed. * * This call will succeed if call to \forcedlink{shared_library}`::has(const char* )` * function with the same symbol name returned `true`. * * For importing symbols by \b alias names use \forcedlink{import_alias} method. * * \b Examples: * * \code * boost::function<int(int)> f = import<int(int)>("test_lib.so", "integer_func_name"); * * auto f_cpp11 = import<int(int)>("test_lib.so", "integer_func_name"); * \endcode * * \code * boost::shared_ptr<int> i = import<int>("test_lib.so", "integer_name"); * \endcode * * \b Template \b parameter \b T: Type of the symbol that we are going to import. Must be explicitly specified. * * \param lib Path to shared library or shared library to load function from. * \param name Null-terminated C or C++ mangled name of the function to import. Can handle std::string, char*, const char*. * \param mode An mode that will be used on library load. * * \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. * Overload that accepts path also throws std::bad_alloc in case of insufficient memory. */ template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode = load_mode::default_mode) { typedef typename boost::dll::detail::import_type<T>::base_type type; boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib, mode); return type(p, boost::addressof(p->get<T>(name))); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import(const boost::dll::fs::path& lib, const std::string& name, load_mode::type mode = load_mode::default_mode) { return import<T>(lib, name.c_str(), mode); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import(const shared_library& lib, const char* name) { typedef typename boost::dll::detail::import_type<T>::base_type type; boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib); return type(p, boost::addressof(p->get<T>(name))); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import(const shared_library& lib, const std::string& name) { return import<T>(lib, name.c_str()); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import(BOOST_RV_REF(shared_library) lib, const char* name) { typedef typename boost::dll::detail::import_type<T>::base_type type; boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>( boost::move(lib) ); return type(p, boost::addressof(p->get<T>(name))); } //! \overload boost::dll::import(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import(BOOST_RV_REF(shared_library) lib, const std::string& name) { return import<T>(boost::move(lib), name.c_str()); } /*! * Returns callable object or boost::shared_ptr<T> that holds the symbol imported * from the loaded library. Returned value refcounts usage * of the loaded shared library, so that it won't get unload until all copies of return value * are not destroyed. * * This call will succeed if call to \forcedlink{shared_library}`::has(const char* )` * function with the same symbol name returned `true`. * * For importing symbols by \b non \b alias names use \forcedlink{import} method. * * \b Examples: * * \code * boost::function<int(int)> f = import_alias<int(int)>("test_lib.so", "integer_func_alias_name"); * * auto f_cpp11 = import_alias<int(int)>("test_lib.so", "integer_func_alias_name"); * \endcode * * \code * boost::shared_ptr<int> i = import_alias<int>("test_lib.so", "integer_alias_name"); * \endcode * * \code * \endcode * * \b Template \b parameter \b T: Type of the symbol alias that we are going to import. Must be explicitly specified. * * \param lib Path to shared library or shared library to load function from. * \param name Null-terminated C or C++ mangled name of the function or variable to import. Can handle std::string, char*, const char*. * \param mode An mode that will be used on library load. * * \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. * Overload that accepts path also throws std::bad_alloc in case of insufficient memory. */ template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode = load_mode::default_mode) { typedef typename boost::dll::detail::import_type<T>::base_type type; boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib, mode); return type(p, p->get<T*>(name)); } //! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::dll::fs::path& lib, const std::string& name, load_mode::type mode = load_mode::default_mode) { return import_alias<T>(lib, name.c_str(), mode); } //! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const shared_library& lib, const char* name) { typedef typename boost::dll::detail::import_type<T>::base_type type; boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib); return type(p, p->get<T*>(name)); } //! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const shared_library& lib, const std::string& name) { return import_alias<T>(lib, name.c_str()); } //! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import_alias(BOOST_RV_REF(shared_library) lib, const char* name) { typedef typename boost::dll::detail::import_type<T>::base_type type; boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>( boost::move(lib) ); return type(p, p->get<T*>(name)); } //! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode) template <class T> BOOST_DLL_IMPORT_RESULT_TYPE import_alias(BOOST_RV_REF(shared_library) lib, const std::string& name) { return import_alias<T>(boost::move(lib), name.c_str()); } #undef BOOST_DLL_IMPORT_RESULT_TYPE }} // boost::dll #endif // BOOST_DLL_IMPORT_HPP library_info.hpp 0000644 00000020465 15125237303 0007744 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_LIBRARY_INFO_HPP #define BOOST_DLL_LIBRARY_INFO_HPP #include <boost/dll/config.hpp> #include <boost/assert.hpp> #include <boost/noncopyable.hpp> #include <boost/predef/os.h> #include <boost/predef/architecture.h> #include <boost/throw_exception.hpp> #include <boost/type_traits/integral_constant.hpp> #include <fstream> #include <boost/dll/detail/pe_info.hpp> #include <boost/dll/detail/elf_info.hpp> #include <boost/dll/detail/macho_info.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif /// \file boost/dll/library_info.hpp /// \brief Contains only the boost::dll::library_info class that is capable of /// extracting different information from binaries. namespace boost { namespace dll { /*! * \brief Class that is capable of extracting different information from a library or binary file. * Currently understands ELF, MACH-O and PE formats on all the platforms. */ class library_info: private boost::noncopyable { private: std::ifstream f_; enum { fmt_elf_info32, fmt_elf_info64, fmt_pe_info32, fmt_pe_info64, fmt_macho_info32, fmt_macho_info64 } fmt_; /// @cond inline static void throw_if_in_32bit_impl(boost::true_type /* is_32bit_platform */) { boost::throw_exception(std::runtime_error("Not native format: 64bit binary")); } inline static void throw_if_in_32bit_impl(boost::false_type /* is_32bit_platform */) BOOST_NOEXCEPT {} inline static void throw_if_in_32bit() { throw_if_in_32bit_impl( boost::integral_constant<bool, (sizeof(void*) == 4)>() ); } static void throw_if_in_windows() { #if BOOST_OS_WINDOWS boost::throw_exception(std::runtime_error("Not native format: not a PE binary")); #endif } static void throw_if_in_linux() { #if !BOOST_OS_WINDOWS && !BOOST_OS_MACOS && !BOOST_OS_IOS boost::throw_exception(std::runtime_error("Not native format: not an ELF binary")); #endif } static void throw_if_in_macos() { #if BOOST_OS_MACOS || BOOST_OS_IOS boost::throw_exception(std::runtime_error("Not native format: not an Mach-O binary")); #endif } void init(bool throw_if_not_native) { if (boost::dll::detail::elf_info32::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); } fmt_ = fmt_elf_info32; } else if (boost::dll::detail::elf_info64::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); throw_if_in_32bit(); } fmt_ = fmt_elf_info64; } else if (boost::dll::detail::pe_info32::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); } fmt_ = fmt_pe_info32; } else if (boost::dll::detail::pe_info64::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); throw_if_in_32bit(); } fmt_ = fmt_pe_info64; } else if (boost::dll::detail::macho_info32::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); } fmt_ = fmt_macho_info32; } else if (boost::dll::detail::macho_info64::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); throw_if_in_32bit(); } fmt_ = fmt_macho_info64; } else { boost::throw_exception(std::runtime_error("Unsupported binary format")); } } /// @endcond public: /*! * Opens file with specified path and prepares for information extraction. * \param library_path Path to the binary file from which the info must be extracted. * \param throw_if_not_native_format Throw an exception if this file format is not * supported by OS. */ explicit library_info(const boost::dll::fs::path& library_path, bool throw_if_not_native_format = true) : f_( #ifdef BOOST_DLL_USE_STD_FS library_path, // Copied from boost/filesystem/fstream.hpp #elif defined(BOOST_WINDOWS_API) && (!defined(_CPPLIB_VER) || _CPPLIB_VER < 405 || defined(_STLPORT_VERSION)) // !Dinkumware || early Dinkumware || STLPort masquerading as Dinkumware library_path.string().c_str(), // use narrow, since wide not available #else // use the native c_str, which will be narrow on POSIX, wide on Windows library_path.c_str(), #endif std::ios_base::in | std::ios_base::binary ) { f_.exceptions( std::ios_base::failbit | std::ifstream::badbit | std::ifstream::eofbit ); init(throw_if_not_native_format); } /*! * \return List of sections that exist in binary file. */ std::vector<std::string> sections() { switch (fmt_) { case fmt_elf_info32: return boost::dll::detail::elf_info32::sections(f_); case fmt_elf_info64: return boost::dll::detail::elf_info64::sections(f_); case fmt_pe_info32: return boost::dll::detail::pe_info32::sections(f_); case fmt_pe_info64: return boost::dll::detail::pe_info64::sections(f_); case fmt_macho_info32: return boost::dll::detail::macho_info32::sections(f_); case fmt_macho_info64: return boost::dll::detail::macho_info64::sections(f_); }; BOOST_ASSERT(false); BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) } /*! * \return List of all the exportable symbols from all the sections that exist in binary file. */ std::vector<std::string> symbols() { switch (fmt_) { case fmt_elf_info32: return boost::dll::detail::elf_info32::symbols(f_); case fmt_elf_info64: return boost::dll::detail::elf_info64::symbols(f_); case fmt_pe_info32: return boost::dll::detail::pe_info32::symbols(f_); case fmt_pe_info64: return boost::dll::detail::pe_info64::symbols(f_); case fmt_macho_info32: return boost::dll::detail::macho_info32::symbols(f_); case fmt_macho_info64: return boost::dll::detail::macho_info64::symbols(f_); }; BOOST_ASSERT(false); BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) } /*! * \param section_name Name of the section from which symbol names must be returned. * \return List of symbols from the specified section. */ std::vector<std::string> symbols(const char* section_name) { switch (fmt_) { case fmt_elf_info32: return boost::dll::detail::elf_info32::symbols(f_, section_name); case fmt_elf_info64: return boost::dll::detail::elf_info64::symbols(f_, section_name); case fmt_pe_info32: return boost::dll::detail::pe_info32::symbols(f_, section_name); case fmt_pe_info64: return boost::dll::detail::pe_info64::symbols(f_, section_name); case fmt_macho_info32: return boost::dll::detail::macho_info32::symbols(f_, section_name); case fmt_macho_info64: return boost::dll::detail::macho_info64::symbols(f_, section_name); }; BOOST_ASSERT(false); BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) } //! \overload std::vector<std::string> symbols(const char* section_name) std::vector<std::string> symbols(const std::string& section_name) { switch (fmt_) { case fmt_elf_info32: return boost::dll::detail::elf_info32::symbols(f_, section_name.c_str()); case fmt_elf_info64: return boost::dll::detail::elf_info64::symbols(f_, section_name.c_str()); case fmt_pe_info32: return boost::dll::detail::pe_info32::symbols(f_, section_name.c_str()); case fmt_pe_info64: return boost::dll::detail::pe_info64::symbols(f_, section_name.c_str()); case fmt_macho_info32: return boost::dll::detail::macho_info32::symbols(f_, section_name.c_str()); case fmt_macho_info64: return boost::dll::detail::macho_info64::symbols(f_, section_name.c_str()); }; BOOST_ASSERT(false); BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) } }; }} // namespace boost::dll #endif // BOOST_DLL_LIBRARY_INFO_HPP smart_library.hpp 0000644 00000040556 15125237303 0010142 0 ustar 00 // Copyright 2016 Klemens Morgenstern // Copyright 2019-2020 Antony Polukhin // // 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_DLL_SMART_LIBRARY_HPP_ #define BOOST_DLL_SMART_LIBRARY_HPP_ /// \file boost/dll/smart_library.hpp /// \warning Extremely experimental! Requires C++11! Will change in next version of Boost! boost/dll/smart_library.hpp is not included in boost/dll.hpp /// \brief Contains the boost::dll::experimental::smart_library class for loading mangled symbols. #include <boost/dll/config.hpp> #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows # include <boost/dll/detail/demangling/msvc.hpp> #else # include <boost/dll/detail/demangling/itanium.hpp> #endif #if (__cplusplus < 201103L) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201103L) # error This file requires C++11 at least! #endif #include <boost/dll/shared_library.hpp> #include <boost/dll/detail/get_mem_fn_type.hpp> #include <boost/dll/detail/ctor_dtor.hpp> #include <boost/dll/detail/type_info.hpp> #include <boost/type_traits/is_object.hpp> #include <boost/type_traits/is_void.hpp> #include <boost/type_traits/is_function.hpp> namespace boost { namespace dll { namespace experimental { using boost::dll::detail::constructor; using boost::dll::detail::destructor; /*! * \brief This class is an extension of \ref shared_library, which allows to load C++ symbols. * * This class allows type safe loading of overloaded functions, member-functions, constructors and variables. * It also allows to overwrite classes so they can be loaded, while being declared with different names. * * \warning Is still very experimental. * * Currently known limitations: * * Member functions must be defined outside of the class to be exported. That is: * \code * //not exported: * struct BOOST_SYMBOL_EXPORT my_class { void func() {}}; * //exported * struct BOOST_SYMBOL_EXPORT my_class { void func();}; * void my_class::func() {}; * \endcode * * With the current analysis, the first version does get exported in MSVC. * MinGW also does export it, BOOST_SYMBOL_EXPORT is written before it. To allow this on windows one can use * BOOST_DLL_MEMBER_EXPORT for this, so that MinGW and MSVC can provide those functions. This does however not work with gcc on linux. * * Direct initialization of members. * On linux the following member variable i will not be initialized when using the allocating constructor: * \code * struct BOOST_SYMBOL_EXPORT my_class { int i; my_class() : i(42) {} }; * \endcode * * This does however not happen when the value is set inside the constructor function. */ class smart_library { shared_library _lib; detail::mangled_storage_impl _storage; public: /*! * Get the underlying shared_library */ const shared_library &shared_lib() const {return _lib;} using mangled_storage = detail::mangled_storage_impl; /*! * Access to the mangled storage, which is created on construction. * * \throw Nothing. */ const mangled_storage &symbol_storage() const {return _storage;} ///Overload, for current development. mangled_storage &symbol_storage() {return _storage;} //! \copydoc shared_library::shared_library() smart_library() BOOST_NOEXCEPT {}; //! \copydoc shared_library::shared_library(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) smart_library(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) { _lib.load(lib_path, mode); _storage.load(lib_path); } //! \copydoc shared_library::shared_library(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) smart_library(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) { load(lib_path, mode, ec); } //! \copydoc shared_library::shared_library(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) smart_library(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) { load(lib_path, mode, ec); } /*! * copy a smart_library object. * * \param lib A smart_library to move from. * * \throw Nothing. */ smart_library(const smart_library & lib) BOOST_NOEXCEPT : _lib(lib._lib), _storage(lib._storage) {} /*! * Move a smart_library object. * * \param lib A smart_library to move from. * * \throw Nothing. */ smart_library(BOOST_RV_REF(smart_library) lib) BOOST_NOEXCEPT : _lib(boost::move(lib._lib)), _storage(boost::move(lib._storage)) {} /*! * Construct from a shared_library object. * * \param lib A shared_library to move from. * * \throw Nothing. */ explicit smart_library(const shared_library & lib) BOOST_NOEXCEPT : _lib(lib) { _storage.load(lib.location()); } /*! * Construct from a shared_library object. * * \param lib A shared_library to move from. * * \throw Nothing. */ explicit smart_library(BOOST_RV_REF(shared_library) lib) BOOST_NOEXCEPT : _lib(boost::move(static_cast<shared_library&>(lib))) { _storage.load(lib.location()); } /*! * Destroys the smart_library. * `unload()` is called if the DLL/DSO was loaded. If library was loaded multiple times * by different instances of shared_library, the actual DLL/DSO won't be unloaded until * there is at least one instance of shared_library. * * \throw Nothing. */ ~smart_library() BOOST_NOEXCEPT {}; //! \copydoc shared_library::load(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) void load(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) { boost::dll::fs::error_code ec; _storage.load(lib_path); _lib.load(lib_path, mode, ec); if (ec) { boost::dll::detail::report_error(ec, "load() failed"); } } //! \copydoc shared_library::load(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) void load(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) { ec.clear(); _storage.load(lib_path); _lib.load(lib_path, mode, ec); } //! \copydoc shared_library::load(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) void load(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) { ec.clear(); _storage.load(lib_path); _lib.load(lib_path, mode, ec); } /*! * Load a variable from the referenced library. * * Unlinke shared_library::get this function will also load scoped variables, which also includes static class members. * * \note When mangled, MSVC will also check the type. * * \param name Name of the variable * \tparam T Type of the variable * \return A reference to the variable of type T. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. */ template<typename T> T& get_variable(const std::string &name) const { return _lib.get<T>(_storage.get_variable<T>(name)); } /*! * Load a function from the referenced library. * * \b Example: * * \code * smart_library lib("test_lib.so"); * typedef int (&add_ints)(int, int); * typedef double (&add_doubles)(double, double); * add_ints f1 = lib.get_function<int(int, int)> ("func_name"); * add_doubles f2 = lib.get_function<double(double, double)>("func_name"); * \endcode * * \note When mangled, MSVC will also check the return type. * * \param name Name of the function. * \tparam Func Type of the function, required for determining the overload * \return A reference to the function of type F. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. */ template<typename Func> Func& get_function(const std::string &name) const { return _lib.get<Func>(_storage.get_function<Func>(name)); } /*! * Load a member-function from the referenced library. * * \b Example (import class is MyClass, which is available inside the library and the host): * * \code * smart_library lib("test_lib.so"); * * typedef int MyClass(*func)(int); * typedef int MyClass(*func_const)(int) const; * * add_ints f1 = lib.get_mem_fn<MyClass, int(int)> ("MyClass::function"); * add_doubles f2 = lib.get_mem_fn<const MyClass, double(double)>("MyClass::function"); * \endcode * * \note When mangled, MSVC will also check the return type. * * \param name Name of the function. * \tparam Class The class the function is a member of. If Class is const, the function will be assumed as taking a const this-pointer. The same applies for volatile. * \tparam Func Signature of the function, required for determining the overload * \return A pointer to the member-function with the signature provided * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. */ template<typename Class, typename Func> typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn get_mem_fn(const std::string& name) const { return _lib.get<typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn>( _storage.get_mem_fn<Class, Func>(name) ); } /*! * Load a constructor from the referenced library. * * \b Example (import class is MyClass, which is available inside the library and the host): * * \code * smart_library lib("test_lib.so"); * * constructor<MyClass(int) f1 = lib.get_mem_fn<MyClass(int)>(); * \endcode * * \tparam Signature Signature of the function, required for determining the overload. The return type is the class which this is the constructor of. * \return A constructor object. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. */ template<typename Signature> constructor<Signature> get_constructor() const { return boost::dll::detail::load_ctor<Signature>(_lib, _storage.get_constructor<Signature>()); } /*! * Load a destructor from the referenced library. * * \b Example (import class is MyClass, which is available inside the library and the host): * * \code * smart_library lib("test_lib.so"); * * destructor<MyClass> f1 = lib.get_mem_fn<MyClass>(); * \endcode * * \tparam Class The class whose destructor shall be loaded * \return A destructor object. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. * */ template<typename Class> destructor<Class> get_destructor() const { return boost::dll::detail::load_dtor<Class>(_lib, _storage.get_destructor<Class>()); } /*! * Load the typeinfo of the given type. * * \b Example (import class is MyClass, which is available inside the library and the host): * * \code * smart_library lib("test_lib.so"); * * std::type_info &ti = lib.get_Type_info<MyClass>(); * \endcode * * \tparam Class The class whose typeinfo shall be loaded * \return A reference to a type_info object. * * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. * */ template<typename Class> const std::type_info& get_type_info() const { return boost::dll::detail::load_type_info<Class>(_lib, _storage); } /** * This function can be used to add a type alias. * * This is to be used, when a class shall be imported, which is not declared on the host side. * * Example: * \code * smart_library lib("test_lib.so"); * * lib.add_type_alias<MyAlias>("MyClass"); //when using MyAlias, the library will look for MyClass * * //get the destructor of MyClass * destructor<MyAlias> dtor = lib.get_destructor<MyAlias>(); * \endcode * * * \param name Name of the class the alias is for. * * \attention If the alias-type is not large enough for the imported class, it will result in undefined behaviour. * \warning The alias will only be applied for the type signature, it will not replace the token in the scoped name. */ template<typename Alias> void add_type_alias(const std::string& name) { this->_storage.add_alias<Alias>(name); } //! \copydoc shared_library::unload() void unload() BOOST_NOEXCEPT { _storage.clear(); _lib.unload(); } //! \copydoc shared_library::is_loaded() const bool is_loaded() const BOOST_NOEXCEPT { return _lib.is_loaded(); } //! \copydoc shared_library::operator!() const bool operator!() const BOOST_NOEXCEPT { return !is_loaded(); } //! \copydoc shared_library::operator bool() const BOOST_EXPLICIT_OPERATOR_BOOL() //! \copydoc shared_library::has(const char* symbol_name) const bool has(const char* symbol_name) const BOOST_NOEXCEPT { return _lib.has(symbol_name); } //! \copydoc shared_library::has(const std::string& symbol_name) const bool has(const std::string& symbol_name) const BOOST_NOEXCEPT { return _lib.has(symbol_name); } //! \copydoc shared_library::assign(const shared_library& lib) smart_library& assign(const smart_library& lib) { _lib.assign(lib._lib); _storage.assign(lib._storage); return *this; } //! \copydoc shared_library::swap(shared_library& rhs) void swap(smart_library& rhs) BOOST_NOEXCEPT { _lib.swap(rhs._lib); _storage.swap(rhs._storage); } }; /// Very fast equality check that compares the actual DLL/DSO objects. Throws nothing. inline bool operator==(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT { return lhs.shared_lib().native() == rhs.shared_lib().native(); } /// Very fast inequality check that compares the actual DLL/DSO objects. Throws nothing. inline bool operator!=(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT { return lhs.shared_lib().native() != rhs.shared_lib().native(); } /// Compare the actual DLL/DSO objects without any guarantee to be stable between runs. Throws nothing. inline bool operator<(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT { return lhs.shared_lib().native() < rhs.shared_lib().native(); } /// Swaps two shared libraries. Does not invalidate symbols and functions loaded from libraries. Throws nothing. inline void swap(smart_library& lhs, smart_library& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } #ifdef BOOST_DLL_DOXYGEN /** Helper functions for overloads. * * Gets either a variable, function or member-function, depending on the signature. * * @code * smart_library sm("lib.so"); * get<int>(sm, "space::value"); //import a variable * get<void(int)>(sm, "space::func"); //import a function * get<some_class, void(int)>(sm, "space::class_::mem_fn"); //import a member function * @endcode * * @param sm A reference to the @ref smart_library * @param name The name of the entity to import */ template<class T, class T2> void get(const smart_library& sm, const std::string &name); #endif template<class T> typename boost::enable_if<boost::is_object<T>, T&>::type get(const smart_library& sm, const std::string &name) { return sm.get_variable<T>(name); } template<class T> typename boost::enable_if<boost::is_function<T>, T&>::type get(const smart_library& sm, const std::string &name) { return sm.get_function<T>(name); } template<class Class, class Signature> auto get(const smart_library& sm, const std::string &name) -> typename detail::get_mem_fn_type<Class, Signature>::mem_fn { return sm.get_mem_fn<Class, Signature>(name); } } /* namespace experimental */ } /* namespace dll */ } /* namespace boost */ #endif /* BOOST_DLL_SMART_LIBRARY_HPP_ */ shared_library.hpp 0000644 00000046741 15125237303 0010264 0 ustar 00 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. // Copyright 2015-2019 Antony Polukhin. // // 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_DLL_SHARED_LIBRARY_HPP #define BOOST_DLL_SHARED_LIBRARY_HPP /// \file boost/dll/shared_library.hpp /// \brief Contains the boost::dll::shared_library class, core class for all the /// DLL/DSO operations. #include <boost/dll/config.hpp> #include <boost/predef/os.h> #include <boost/core/enable_if.hpp> #include <boost/core/explicit_operator_bool.hpp> #include <boost/type_traits/is_member_pointer.hpp> #include <boost/dll/detail/system_error.hpp> #include <boost/dll/detail/aggressive_ptr_cast.hpp> #if BOOST_OS_WINDOWS # include <boost/dll/detail/windows/shared_library_impl.hpp> #else # include <boost/dll/detail/posix/shared_library_impl.hpp> #endif #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif namespace boost { namespace dll { /*! * \brief This class can be used to load a * Dynamic link libraries (DLL's) or Shared Libraries, also know * as dynamic shared objects (DSO's) and get their exported * symbols (functions and variables). * * shared_library instances share reference count to an actual loaded DLL/DSO, so it * is safe and memory efficient to have multiple instances of shared_library referencing the same DLL/DSO * even if those instances were loaded using different paths (relative + absolute) referencing the same object. * * On Linux/POSIX link with library "dl". "-fvisibility=hidden" flag is also recommended for use on Linux/POSIX. */ class shared_library /// @cond : private boost::dll::detail::shared_library_impl /// @endcond { typedef boost::dll::detail::shared_library_impl base_t; BOOST_COPYABLE_AND_MOVABLE(shared_library) public: #ifdef BOOST_DLL_DOXYGEN typedef platform_specific native_handle_t; #else typedef shared_library_impl::native_handle_t native_handle_t; #endif /*! * Creates in anstance that does not reference any DLL/DSO. * * \post this->is_loaded() returns false. * \throw Nothing. */ shared_library() BOOST_NOEXCEPT {} /*! * Copy constructor that increments the reference count of an underlying shared library. * Same as calling constructor with `lib.location()` parameter. * * \param lib A library to copy. * \post lib == *this * \throw \forcedlinkfs{system_error}, std::bad_alloc in case of insufficient memory. */ shared_library(const shared_library& lib) : base_t() { assign(lib); } /*! * Copy constructor that increments the reference count of an underlying shared library. * Same as calling constructor with `lib.location(), ec` parameters. * * \param lib A shared library to copy. * \param ec Variable that will be set to the result of the operation. * \post lib == *this * \throw std::bad_alloc in case of insufficient memory. */ shared_library(const shared_library& lib, boost::dll::fs::error_code& ec) : base_t() { assign(lib, ec); } /*! * Move constructor. Does not invalidate existing symbols and functions loaded from lib. * * \param lib A shared library to move from. * \post lib.is_loaded() returns false, this->is_loaded() return true. * \throw Nothing. */ shared_library(BOOST_RV_REF(shared_library) lib) BOOST_NOEXCEPT : base_t(boost::move(static_cast<base_t&>(lib))) {} /*! * Loads a library by specified path with a specified mode. * * \param lib_path Library file name. Can handle std::string, const char*, std::wstring, * const wchar_t* or \forcedlinkfs{path}. * \param mode A mode that will be used on library load. * \throw \forcedlinkfs{system_error}, std::bad_alloc in case of insufficient memory. */ explicit shared_library(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) { shared_library::load(lib_path, mode); } /*! * Loads a library by specified path with a specified mode. * * \param lib_path Library file name. Can handle std::string, const char*, std::wstring, * const wchar_t* or \forcedlinkfs{path}. * \param mode A mode that will be used on library load. * \param ec Variable that will be set to the result of the operation. * \throw std::bad_alloc in case of insufficient memory. */ shared_library(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) { shared_library::load(lib_path, mode, ec); } //! \overload shared_library(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) shared_library(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) { shared_library::load(lib_path, mode, ec); } /*! * Assignment operator. If this->is_loaded() then calls this->unload(). Does not invalidate existing symbols and functions loaded from lib. * * \param lib A shared library to assign from. * \post lib == *this * \throw \forcedlinkfs{system_error}, std::bad_alloc in case of insufficient memory. */ shared_library& operator=(BOOST_COPY_ASSIGN_REF(shared_library) lib) { boost::dll::fs::error_code ec; assign(lib, ec); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::shared_library::operator= failed"); } return *this; } /*! * Move assignment operator. If this->is_loaded() then calls this->unload(). Does not invalidate existing symbols and functions loaded from lib. * * \param lib A library to move from. * \post lib.is_loaded() returns false. * \throw Nothing. */ shared_library& operator=(BOOST_RV_REF(shared_library) lib) BOOST_NOEXCEPT { if (lib.native() != native()) { swap(lib); } return *this; } /*! * Destroys the object by calling `unload()`. If library was loaded multiple times * by different instances, the actual DLL/DSO won't be unloaded until * there is at least one instance that references the DLL/DSO. * * \throw Nothing. */ ~shared_library() BOOST_NOEXCEPT {} /*! * Makes *this share the same shared object as lib. If *this is loaded, then unloads it. * * \post lib.location() == this->location(), lib == *this * \param lib A library to copy. * \param ec Variable that will be set to the result of the operation. * \throw std::bad_alloc in case of insufficient memory. */ shared_library& assign(const shared_library& lib, boost::dll::fs::error_code& ec) { ec.clear(); if (native() == lib.native()) { return *this; } if (!lib) { unload(); return *this; } boost::dll::fs::path loc = lib.location(ec); if (ec) { return *this; } shared_library copy(loc, ec); if (ec) { return *this; } swap(copy); return *this; } /*! * Makes *this share the same shared object as lib. If *this is loaded, then unloads it. * * \param lib A library instance to assign from. * \post lib.location() == this->location() * \throw \forcedlinkfs{system_error}, std::bad_alloc in case of insufficient memory. */ shared_library& assign(const shared_library& lib) { boost::dll::fs::error_code ec; assign(lib, ec); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::shared_library::assign() failed"); } return *this; } /*! * Loads a library by specified path with a specified mode. * * Note that if some library is already loaded in this instance, load will * call unload() and then load the new provided library. * * \param lib_path Library file name. Can handle std::string, const char*, std::wstring, * const wchar_t* or \forcedlinkfs{path}. * \param mode A mode that will be used on library load. * \throw \forcedlinkfs{system_error}, std::bad_alloc in case of insufficient memory. * */ void load(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) { boost::dll::fs::error_code ec; base_t::load(lib_path, mode, ec); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::shared_library::load() failed"); } } /*! * Loads a library by specified path with a specified mode. * * Note that if some library is already loaded in this instance, load will * call unload() and then load the new provided library. * * \param lib_path Library file name. Can handle std::string, const char*, std::wstring, * const wchar_t* or \forcedlinkfs{path}. * \param ec Variable that will be set to the result of the operation. * \param mode A mode that will be used on library load. * \throw std::bad_alloc in case of insufficient memory. */ void load(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) { ec.clear(); base_t::load(lib_path, mode, ec); } //! \overload void load(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) void load(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) { ec.clear(); base_t::load(lib_path, mode, ec); } /*! * Unloads a shared library. If library was loaded multiple times * by different instances, the actual DLL/DSO won't be unloaded until * there is at least one instance that references the DLL/DSO. * * \post this->is_loaded() returns false. * \throw Nothing. */ void unload() BOOST_NOEXCEPT { base_t::unload(); } /*! * Check if an library is loaded. * * \return true if a library has been loaded. * \throw Nothing. */ bool is_loaded() const BOOST_NOEXCEPT { return base_t::is_loaded(); } /*! * Check if an library is not loaded. * * \return true if a library has not been loaded. * \throw Nothing. */ bool operator!() const BOOST_NOEXCEPT { return !is_loaded(); } /*! * Check if an library is loaded. * * \return true if a library has been loaded. * \throw Nothing. */ BOOST_EXPLICIT_OPERATOR_BOOL() /*! * Search for a given symbol on loaded library. Works for all symbols, including alias names. * * \param symbol_name Null-terminated symbol name. Can handle std::string, char*, const char*. * \return `true` if the loaded library contains a symbol with a given name. * \throw Nothing. */ bool has(const char* symbol_name) const BOOST_NOEXCEPT { boost::dll::fs::error_code ec; return is_loaded() && !!base_t::symbol_addr(symbol_name, ec) && !ec; } //! \overload bool has(const char* symbol_name) const bool has(const std::string& symbol_name) const BOOST_NOEXCEPT { return has(symbol_name.c_str()); } /*! * Returns reference to the symbol (function or variable) with the given name from the loaded library. * This call will always succeed and throw nothing if call to `has(const char* )` * member function with the same symbol name returned `true`. * * \b Example: * \code * int& i0 = lib.get<int>("integer_name"); * int& i1 = *lib.get<int*>("integer_alias_name"); * \endcode * * \tparam T Type of the symbol that we are going to import. Must be explicitly specified. * \param symbol_name Null-terminated symbol name. Can handle std::string, char*, const char*. * \return Reference to the symbol. * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. */ template <typename T> inline typename boost::enable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T>::type get(const std::string& symbol_name) const { return get<T>(symbol_name.c_str()); } //! \overload T& get(const std::string& symbol_name) const template <typename T> inline typename boost::disable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T&>::type get(const std::string& symbol_name) const { return get<T>(symbol_name.c_str()); } //! \overload T& get(const std::string& symbol_name) const template <typename T> inline typename boost::enable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T>::type get(const char* symbol_name) const { return boost::dll::detail::aggressive_ptr_cast<T>( get_void(symbol_name) ); } //! \overload T& get(const std::string& symbol_name) const template <typename T> inline typename boost::disable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T&>::type get(const char* symbol_name) const { return *boost::dll::detail::aggressive_ptr_cast<T*>( get_void(symbol_name) ); } /*! * Returns a symbol (function or variable) from a shared library by alias name of the symbol. * * \b Example: * \code * int& i = lib.get_alias<int>("integer_alias_name"); * \endcode * * \tparam T Type of the symbol that we are going to import. Must be explicitly specified.. * \param alias_name Null-terminated alias symbol name. Can handle std::string, char*, const char*. * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. */ template <typename T> inline T& get_alias(const char* alias_name) const { return *get<T*>(alias_name); } //! \overload T& get_alias(const char* alias_name) const template <typename T> inline T& get_alias(const std::string& alias_name) const { return *get<T*>(alias_name.c_str()); } private: /// @cond // get_void is required to reduce binary size: it does not depend on a template // parameter and will be instantiated only once. void* get_void(const char* sb) const { boost::dll::fs::error_code ec; if (!is_loaded()) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); // report_error() calls dlsym, do not use it here! boost::throw_exception( boost::dll::fs::system_error( ec, "boost::dll::shared_library::get() failed: no library was loaded" ) ); } void* const ret = base_t::symbol_addr(sb, ec); if (ec || !ret) { boost::dll::detail::report_error(ec, "boost::dll::shared_library::get() failed"); } return ret; } /// @endcond public: /*! * Returns the native handler of the loaded library. * * \return Platform-specific handle. */ native_handle_t native() const BOOST_NOEXCEPT { return base_t::native(); } /*! * Returns full path and name of this shared object. * * \b Example: * \code * shared_library lib("test_lib.dll"); * filesystem::path full_path = lib.location(); // C:\Windows\System32\test_lib.dll * \endcode * * \return Full path to the shared library. * \throw \forcedlinkfs{system_error}, std::bad_alloc. */ boost::dll::fs::path location() const { boost::dll::fs::error_code ec; if (!is_loaded()) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); boost::throw_exception( boost::dll::fs::system_error( ec, "boost::dll::shared_library::location() failed (no library was loaded)" ) ); } boost::dll::fs::path full_path = base_t::full_module_path(ec); if (ec) { boost::dll::detail::report_error(ec, "boost::dll::shared_library::location() failed"); } return full_path; } /*! * Returns full path and name of shared module. * * \b Example: * \code * shared_library lib("test_lib.dll"); * filesystem::path full_path = lib.location(); // C:\Windows\System32\test_lib.dll * \endcode * * \param ec Variable that will be set to the result of the operation. * \return Full path to the shared library. * \throw std::bad_alloc. */ boost::dll::fs::path location(boost::dll::fs::error_code& ec) const { if (!is_loaded()) { ec = boost::dll::fs::make_error_code( boost::dll::fs::errc::bad_file_descriptor ); return boost::dll::fs::path(); } ec.clear(); return base_t::full_module_path(ec); } /*! * Returns suffix of shared module: * in a call to load() or the constructor/load. * * \return The suffix od shared module: ".dll" (Windows), ".so" (Unix/Linux/BSD), ".dylib" (MacOS/IOS) */ static boost::dll::fs::path suffix() { return base_t::suffix(); } /*! * Returns the decorated path to a shared module name, i.e. with needed prefix/suffix added. * * \b Recommendations: Use `load` with `load_mode::append_decorations` instead of constructing the decorated path via `decorate()` and loading by it. * * For instance, for a path like "path/to/boost" it returns : * - path/to/libboost.so on posix platforms * - path/to/libboost.dylib on OSX * - path/to/boost.dll on Windows * * Method handles both relative and absolute paths. * * - Windows note: `decorate()` does not prepend "lib" to the decorated path. Use `load` with `load_mode::append_decorations` for MinGW compatibility purpose. * - Posix note: if the initial module name is already prepended with lib, only the suffix() is appended to the path * * \param sl the module name and path to decorate - for instance : /usr/lib/boost * * \return The decorated unportable path that may not exists in the filesystem or could be wrong due to platform specifics. */ static boost::dll::fs::path decorate(const boost::dll::fs::path& sl) { return base_t::decorate(sl); } /*! * Swaps two libraries. Does not invalidate existing symbols and functions loaded from libraries. * * \param rhs Library to swap with. * \throw Nothing. */ void swap(shared_library& rhs) BOOST_NOEXCEPT { base_t::swap(rhs); } }; /// Very fast equality check that compares the actual DLL/DSO objects. Throws nothing. inline bool operator==(const shared_library& lhs, const shared_library& rhs) BOOST_NOEXCEPT { return lhs.native() == rhs.native(); } /// Very fast inequality check that compares the actual DLL/DSO objects. Throws nothing. inline bool operator!=(const shared_library& lhs, const shared_library& rhs) BOOST_NOEXCEPT { return lhs.native() != rhs.native(); } /// Compare the actual DLL/DSO objects without any guarantee to be stable between runs. Throws nothing. inline bool operator<(const shared_library& lhs, const shared_library& rhs) BOOST_NOEXCEPT { return lhs.native() < rhs.native(); } /// Swaps two shared libraries. Does not invalidate symbols and functions loaded from libraries. Throws nothing. inline void swap(shared_library& lhs, shared_library& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } }} // boost::dll #endif // BOOST_DLL_SHARED_LIBRARY_HPP
| ver. 1.6 |
Github
|
.
| PHP 8.2.30 | ??????????? ?????????: 0.04 |
proxy
|
phpinfo
|
???????????