// 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 #include #include #include #include #include #include #include #include #include #include #include #include #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_; boost::aligned_storage< // making my own std::aligned_union from scratch. TODO: move to TypeTraits boost::mpl::deref< boost::mpl::max_element< boost::mpl::vector_c >::type >::type::value >::type impl_; /// @cond boost::dll::detail::x_info_interface& impl() BOOST_NOEXCEPT { return *reinterpret_cast(impl_.address()); } 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() ); } 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(); } new (impl_.address()) boost::dll::detail::elf_info32(f_); } 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(); } new (impl_.address()) boost::dll::detail::elf_info64(f_); } else if (boost::dll::detail::pe_info32::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); } new (impl_.address()) boost::dll::detail::pe_info32(f_); } 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(); } new (impl_.address()) boost::dll::detail::pe_info64(f_); } else if (boost::dll::detail::macho_info32::parsing_supported(f_)) { if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); } new (impl_.address()) boost::dll::detail::macho_info32(f_); } 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(); } new (impl_.address()) boost::dll::detail::macho_info64(f_); } 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 ) , impl_() { 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 sections() { return impl().sections(); } /*! * \return List of all the exportable symbols from all the sections that exist in binary file. */ std::vector symbols() { return impl().symbols(); } /*! * \param section_name Name of the section from which symbol names must be returned. * \return List of symbols from the specified section. */ std::vector symbols(const char* section_name) { return impl().symbols(section_name); } //! \overload std::vector symbols(const char* section_name) std::vector symbols(const std::string& section_name) { return impl().symbols(section_name.c_str()); } /*! * \throw Nothing. */ ~library_info() BOOST_NOEXCEPT { typedef boost::dll::detail::x_info_interface T; impl().~T(); } }; }} // namespace boost::dll #endif // BOOST_DLL_LIBRARY_INFO_HPP