?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/dll.zip
???????
PK H\�[��b- - import_mangled.hppnu �[��� // 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_ */ PK H\�[����0 �0 alias.hppnu �[��� // 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 PK H\�[��q� � config.hppnu �[��� // 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 PK H\�[?f~i�# �# runtime_symbol_info.hppnu �[��� // 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 PK H\�[L~��� � shared_library_load_mode.hppnu �[��� // 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 PK H\�[$�H�I+ I+ detail/elf_info.hppnu �[��� // 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 PK H\�[���Y� � detail/ctor_dtor.hppnu �[��� // 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_ */ PK H\�[�r�A �A detail/pe_info.hppnu �[��� // 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 PK H\�[����7 �7 detail/macho_info.hppnu �[��� // 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 PK H\�[��2�1 1 $ detail/posix/shared_library_impl.hppnu �[��� // 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 PK H\�[��j, , &