library_info.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. #ifndef BOOST_DLL_LIBRARY_INFO_HPP
  8. #define BOOST_DLL_LIBRARY_INFO_HPP
  9. #include <boost/dll/config.hpp>
  10. #include <boost/mpl/max_element.hpp>
  11. #include <boost/mpl/vector_c.hpp>
  12. #include <boost/aligned_storage.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. #include <fstream>
  19. #include <boost/dll/detail/pe_info.hpp>
  20. #include <boost/dll/detail/elf_info.hpp>
  21. #include <boost/dll/detail/macho_info.hpp>
  22. #ifdef BOOST_HAS_PRAGMA_ONCE
  23. # pragma once
  24. #endif
  25. /// \file boost/dll/library_info.hpp
  26. /// \brief Contains only the boost::dll::library_info class that is capable of
  27. /// extracting different information from binaries.
  28. namespace boost { namespace dll {
  29. /*!
  30. * \brief Class that is capable of extracting different information from a library or binary file.
  31. * Currently understands ELF, MACH-O and PE formats on all the platforms.
  32. */
  33. class library_info: private boost::noncopyable {
  34. private:
  35. std::ifstream f_;
  36. boost::aligned_storage< // making my own std::aligned_union from scratch. TODO: move to TypeTraits
  37. boost::mpl::deref<
  38. boost::mpl::max_element<
  39. boost::mpl::vector_c<std::size_t,
  40. sizeof(boost::dll::detail::elf_info32),
  41. sizeof(boost::dll::detail::elf_info64),
  42. sizeof(boost::dll::detail::pe_info32),
  43. sizeof(boost::dll::detail::pe_info64),
  44. sizeof(boost::dll::detail::macho_info32),
  45. sizeof(boost::dll::detail::macho_info64)
  46. >
  47. >::type
  48. >::type::value
  49. >::type impl_;
  50. /// @cond
  51. boost::dll::detail::x_info_interface& impl() BOOST_NOEXCEPT {
  52. return *reinterpret_cast<boost::dll::detail::x_info_interface*>(impl_.address());
  53. }
  54. inline static void throw_if_in_32bit_impl(boost::true_type /* is_32bit_platform */) {
  55. boost::throw_exception(std::runtime_error("Not native format: 64bit binary"));
  56. }
  57. inline static void throw_if_in_32bit_impl(boost::false_type /* is_32bit_platform */) BOOST_NOEXCEPT {}
  58. inline static void throw_if_in_32bit() {
  59. throw_if_in_32bit_impl( boost::integral_constant<bool, (sizeof(void*) == 4)>() );
  60. }
  61. static void throw_if_in_windows() {
  62. #if BOOST_OS_WINDOWS
  63. boost::throw_exception(std::runtime_error("Not native format: not a PE binary"));
  64. #endif
  65. }
  66. static void throw_if_in_linux() {
  67. #if !BOOST_OS_WINDOWS && !BOOST_OS_MACOS && !BOOST_OS_IOS
  68. boost::throw_exception(std::runtime_error("Not native format: not an ELF binary"));
  69. #endif
  70. }
  71. static void throw_if_in_macos() {
  72. #if BOOST_OS_MACOS || BOOST_OS_IOS
  73. boost::throw_exception(std::runtime_error("Not native format: not an Mach-O binary"));
  74. #endif
  75. }
  76. void init(bool throw_if_not_native) {
  77. if (boost::dll::detail::elf_info32::parsing_supported(f_)) {
  78. if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); }
  79. new (impl_.address()) boost::dll::detail::elf_info32(f_);
  80. } else if (boost::dll::detail::elf_info64::parsing_supported(f_)) {
  81. if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); throw_if_in_32bit(); }
  82. new (impl_.address()) boost::dll::detail::elf_info64(f_);
  83. } else if (boost::dll::detail::pe_info32::parsing_supported(f_)) {
  84. if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); }
  85. new (impl_.address()) boost::dll::detail::pe_info32(f_);
  86. } else if (boost::dll::detail::pe_info64::parsing_supported(f_)) {
  87. if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); throw_if_in_32bit(); }
  88. new (impl_.address()) boost::dll::detail::pe_info64(f_);
  89. } else if (boost::dll::detail::macho_info32::parsing_supported(f_)) {
  90. if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); }
  91. new (impl_.address()) boost::dll::detail::macho_info32(f_);
  92. } else if (boost::dll::detail::macho_info64::parsing_supported(f_)) {
  93. if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); throw_if_in_32bit(); }
  94. new (impl_.address()) boost::dll::detail::macho_info64(f_);
  95. } else {
  96. boost::throw_exception(std::runtime_error("Unsupported binary format"));
  97. }
  98. }
  99. /// @endcond
  100. public:
  101. /*!
  102. * Opens file with specified path and prepares for information extraction.
  103. * \param library_path Path to the binary file from which the info must be extracted.
  104. * \param throw_if_not_native_format Throw an exception if this file format is not
  105. * supported by OS.
  106. */
  107. explicit library_info(const boost::dll::fs::path& library_path, bool throw_if_not_native_format = true)
  108. : f_(
  109. #ifdef BOOST_DLL_USE_STD_FS
  110. library_path,
  111. // Copied from boost/filesystem/fstream.hpp
  112. #elif defined(BOOST_WINDOWS_API) && (!defined(_CPPLIB_VER) || _CPPLIB_VER < 405 || defined(_STLPORT_VERSION))
  113. // !Dinkumware || early Dinkumware || STLPort masquerading as Dinkumware
  114. library_path.string().c_str(), // use narrow, since wide not available
  115. #else // use the native c_str, which will be narrow on POSIX, wide on Windows
  116. library_path.c_str(),
  117. #endif
  118. std::ios_base::in | std::ios_base::binary
  119. )
  120. , impl_()
  121. {
  122. f_.exceptions(
  123. std::ios_base::failbit
  124. | std::ifstream::badbit
  125. | std::ifstream::eofbit
  126. );
  127. init(throw_if_not_native_format);
  128. }
  129. /*!
  130. * \return List of sections that exist in binary file.
  131. */
  132. std::vector<std::string> sections() {
  133. return impl().sections();
  134. }
  135. /*!
  136. * \return List of all the exportable symbols from all the sections that exist in binary file.
  137. */
  138. std::vector<std::string> symbols() {
  139. return impl().symbols();
  140. }
  141. /*!
  142. * \param section_name Name of the section from which symbol names must be returned.
  143. * \return List of symbols from the specified section.
  144. */
  145. std::vector<std::string> symbols(const char* section_name) {
  146. return impl().symbols(section_name);
  147. }
  148. //! \overload std::vector<std::string> symbols(const char* section_name)
  149. std::vector<std::string> symbols(const std::string& section_name) {
  150. return impl().symbols(section_name.c_str());
  151. }
  152. /*!
  153. * \throw Nothing.
  154. */
  155. ~library_info() BOOST_NOEXCEPT {
  156. typedef boost::dll::detail::x_info_interface T;
  157. impl().~T();
  158. }
  159. };
  160. }} // namespace boost::dll
  161. #endif // BOOST_DLL_LIBRARY_INFO_HPP