1 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. 2 // Copyright 2015-2019 Antony Polukhin. 3 // 4 // Distributed under the Boost Software License, Version 1.0. 5 // (See accompanying file LICENSE_1_0.txt 6 // or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_DLL_LIBRARY_INFO_HPP 9 #define BOOST_DLL_LIBRARY_INFO_HPP 10 11 #include <boost/dll/config.hpp> 12 #include <boost/assert.hpp> 13 #include <boost/noncopyable.hpp> 14 #include <boost/predef/os.h> 15 #include <boost/predef/architecture.h> 16 #include <boost/throw_exception.hpp> 17 #include <boost/type_traits/integral_constant.hpp> 18 19 #include <fstream> 20 21 #include <boost/dll/detail/pe_info.hpp> 22 #include <boost/dll/detail/elf_info.hpp> 23 #include <boost/dll/detail/macho_info.hpp> 24 25 #ifdef BOOST_HAS_PRAGMA_ONCE 26 # pragma once 27 #endif 28 29 /// \file boost/dll/library_info.hpp 30 /// \brief Contains only the boost::dll::library_info class that is capable of 31 /// extracting different information from binaries. 32 33 namespace boost { namespace dll { 34 35 /*! 36 * \brief Class that is capable of extracting different information from a library or binary file. 37 * Currently understands ELF, MACH-O and PE formats on all the platforms. 38 */ 39 class library_info: private boost::noncopyable { 40 private: 41 std::ifstream f_; 42 43 enum { 44 fmt_elf_info32, 45 fmt_elf_info64, 46 fmt_pe_info32, 47 fmt_pe_info64, 48 fmt_macho_info32, 49 fmt_macho_info64 50 } fmt_; 51 52 /// @cond throw_if_in_32bit_impl(boost::true_type)53 inline static void throw_if_in_32bit_impl(boost::true_type /* is_32bit_platform */) { 54 boost::throw_exception(std::runtime_error("Not native format: 64bit binary")); 55 } 56 throw_if_in_32bit_impl(boost::false_type)57 inline static void throw_if_in_32bit_impl(boost::false_type /* is_32bit_platform */) BOOST_NOEXCEPT {} 58 59 throw_if_in_32bit()60 inline static void throw_if_in_32bit() { 61 throw_if_in_32bit_impl( boost::integral_constant<bool, (sizeof(void*) == 4)>() ); 62 } 63 throw_if_in_windows()64 static void throw_if_in_windows() { 65 #if BOOST_OS_WINDOWS 66 boost::throw_exception(std::runtime_error("Not native format: not a PE binary")); 67 #endif 68 } 69 throw_if_in_linux()70 static void throw_if_in_linux() { 71 #if !BOOST_OS_WINDOWS && !BOOST_OS_MACOS && !BOOST_OS_IOS 72 boost::throw_exception(std::runtime_error("Not native format: not an ELF binary")); 73 #endif 74 } 75 throw_if_in_macos()76 static void throw_if_in_macos() { 77 #if BOOST_OS_MACOS || BOOST_OS_IOS 78 boost::throw_exception(std::runtime_error("Not native format: not an Mach-O binary")); 79 #endif 80 } 81 init(bool throw_if_not_native)82 void init(bool throw_if_not_native) { 83 if (boost::dll::detail::elf_info32::parsing_supported(f_)) { 84 if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); } 85 86 fmt_ = fmt_elf_info32; 87 } else if (boost::dll::detail::elf_info64::parsing_supported(f_)) { 88 if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); throw_if_in_32bit(); } 89 90 fmt_ = fmt_elf_info64; 91 } else if (boost::dll::detail::pe_info32::parsing_supported(f_)) { 92 if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); } 93 94 fmt_ = fmt_pe_info32; 95 } else if (boost::dll::detail::pe_info64::parsing_supported(f_)) { 96 if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); throw_if_in_32bit(); } 97 98 fmt_ = fmt_pe_info64; 99 } else if (boost::dll::detail::macho_info32::parsing_supported(f_)) { 100 if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); } 101 102 fmt_ = fmt_macho_info32; 103 } else if (boost::dll::detail::macho_info64::parsing_supported(f_)) { 104 if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); throw_if_in_32bit(); } 105 106 fmt_ = fmt_macho_info64; 107 } else { 108 boost::throw_exception(std::runtime_error("Unsupported binary format")); 109 } 110 } 111 /// @endcond 112 113 public: 114 /*! 115 * Opens file with specified path and prepares for information extraction. 116 * \param library_path Path to the binary file from which the info must be extracted. 117 * \param throw_if_not_native_format Throw an exception if this file format is not 118 * supported by OS. 119 */ library_info(const boost::dll::fs::path & library_path,bool throw_if_not_native_format=true)120 explicit library_info(const boost::dll::fs::path& library_path, bool throw_if_not_native_format = true) 121 : f_( 122 #ifdef BOOST_DLL_USE_STD_FS 123 library_path, 124 // Copied from boost/filesystem/fstream.hpp 125 #elif defined(BOOST_WINDOWS_API) && (!defined(_CPPLIB_VER) || _CPPLIB_VER < 405 || defined(_STLPORT_VERSION)) 126 // !Dinkumware || early Dinkumware || STLPort masquerading as Dinkumware 127 library_path.string().c_str(), // use narrow, since wide not available 128 #else // use the native c_str, which will be narrow on POSIX, wide on Windows 129 library_path.c_str(), 130 #endif 131 std::ios_base::in | std::ios_base::binary 132 ) 133 { 134 f_.exceptions( 135 std::ios_base::failbit 136 | std::ifstream::badbit 137 | std::ifstream::eofbit 138 ); 139 140 init(throw_if_not_native_format); 141 } 142 143 /*! 144 * \return List of sections that exist in binary file. 145 */ sections()146 std::vector<std::string> sections() { 147 switch (fmt_) { 148 case fmt_elf_info32: return boost::dll::detail::elf_info32::sections(f_); 149 case fmt_elf_info64: return boost::dll::detail::elf_info64::sections(f_); 150 case fmt_pe_info32: return boost::dll::detail::pe_info32::sections(f_); 151 case fmt_pe_info64: return boost::dll::detail::pe_info64::sections(f_); 152 case fmt_macho_info32: return boost::dll::detail::macho_info32::sections(f_); 153 case fmt_macho_info64: return boost::dll::detail::macho_info64::sections(f_); 154 }; 155 BOOST_ASSERT(false); 156 BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) 157 } 158 159 /*! 160 * \return List of all the exportable symbols from all the sections that exist in binary file. 161 */ symbols()162 std::vector<std::string> symbols() { 163 switch (fmt_) { 164 case fmt_elf_info32: return boost::dll::detail::elf_info32::symbols(f_); 165 case fmt_elf_info64: return boost::dll::detail::elf_info64::symbols(f_); 166 case fmt_pe_info32: return boost::dll::detail::pe_info32::symbols(f_); 167 case fmt_pe_info64: return boost::dll::detail::pe_info64::symbols(f_); 168 case fmt_macho_info32: return boost::dll::detail::macho_info32::symbols(f_); 169 case fmt_macho_info64: return boost::dll::detail::macho_info64::symbols(f_); 170 }; 171 BOOST_ASSERT(false); 172 BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) 173 } 174 175 /*! 176 * \param section_name Name of the section from which symbol names must be returned. 177 * \return List of symbols from the specified section. 178 */ symbols(const char * section_name)179 std::vector<std::string> symbols(const char* section_name) { 180 switch (fmt_) { 181 case fmt_elf_info32: return boost::dll::detail::elf_info32::symbols(f_, section_name); 182 case fmt_elf_info64: return boost::dll::detail::elf_info64::symbols(f_, section_name); 183 case fmt_pe_info32: return boost::dll::detail::pe_info32::symbols(f_, section_name); 184 case fmt_pe_info64: return boost::dll::detail::pe_info64::symbols(f_, section_name); 185 case fmt_macho_info32: return boost::dll::detail::macho_info32::symbols(f_, section_name); 186 case fmt_macho_info64: return boost::dll::detail::macho_info64::symbols(f_, section_name); 187 }; 188 BOOST_ASSERT(false); 189 BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) 190 } 191 192 193 //! \overload std::vector<std::string> symbols(const char* section_name) symbols(const std::string & section_name)194 std::vector<std::string> symbols(const std::string& section_name) { 195 switch (fmt_) { 196 case fmt_elf_info32: return boost::dll::detail::elf_info32::symbols(f_, section_name.c_str()); 197 case fmt_elf_info64: return boost::dll::detail::elf_info64::symbols(f_, section_name.c_str()); 198 case fmt_pe_info32: return boost::dll::detail::pe_info32::symbols(f_, section_name.c_str()); 199 case fmt_pe_info64: return boost::dll::detail::pe_info64::symbols(f_, section_name.c_str()); 200 case fmt_macho_info32: return boost::dll::detail::macho_info32::symbols(f_, section_name.c_str()); 201 case fmt_macho_info64: return boost::dll::detail::macho_info64::symbols(f_, section_name.c_str()); 202 }; 203 BOOST_ASSERT(false); 204 BOOST_UNREACHABLE_RETURN(std::vector<std::string>()) 205 } 206 }; 207 208 }} // namespace boost::dll 209 #endif // BOOST_DLL_LIBRARY_INFO_HPP 210