]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright 2014 Renato Tegon Forti, Antony Polukhin. |
2 | // Copyright 2015 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/config.hpp> | |
12 | #include <boost/mpl/max_element.hpp> | |
13 | #include <boost/mpl/vector_c.hpp> | |
14 | #include <boost/aligned_storage.hpp> | |
15 | #include <boost/noncopyable.hpp> | |
16 | #include <boost/predef/os.h> | |
17 | #include <boost/predef/architecture.h> | |
18 | #include <boost/type_traits/integral_constant.hpp> | |
19 | ||
20 | #include <boost/dll/detail/pe_info.hpp> | |
21 | #include <boost/dll/detail/elf_info.hpp> | |
22 | #include <boost/dll/detail/macho_info.hpp> | |
23 | ||
24 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
25 | # pragma once | |
26 | #endif | |
27 | ||
28 | /// \file boost/dll/library_info.hpp | |
29 | /// \brief Contains only the boost::dll::library_info class that is capable of | |
30 | /// extracting different information from binaries. | |
31 | ||
32 | namespace boost { namespace dll { | |
33 | ||
34 | /*! | |
35 | * \brief Class that is capable of extracting different information from a library or binary file. | |
36 | * Currently understands ELF, MACH-O and PE formats on all the platforms. | |
37 | */ | |
38 | class library_info: private boost::noncopyable { | |
39 | private: | |
40 | boost::filesystem::ifstream f_; | |
41 | ||
42 | boost::aligned_storage< // making my own std::aligned_union from scratch. TODO: move to TypeTraits | |
43 | boost::mpl::deref< | |
44 | boost::mpl::max_element< | |
45 | boost::mpl::vector_c<std::size_t, | |
46 | sizeof(boost::dll::detail::elf_info32), | |
47 | sizeof(boost::dll::detail::elf_info64), | |
48 | sizeof(boost::dll::detail::pe_info32), | |
49 | sizeof(boost::dll::detail::pe_info64), | |
50 | sizeof(boost::dll::detail::macho_info32), | |
51 | sizeof(boost::dll::detail::macho_info64) | |
52 | > | |
53 | >::type | |
54 | >::type::value | |
55 | >::type impl_; | |
56 | ||
57 | /// @cond | |
58 | boost::dll::detail::x_info_interface& impl() BOOST_NOEXCEPT { | |
59 | return *reinterpret_cast<boost::dll::detail::x_info_interface*>(impl_.address()); | |
60 | } | |
61 | ||
62 | inline static void throw_if_in_32bit_impl(boost::true_type /* is_32bit_platform */) { | |
63 | boost::throw_exception(std::runtime_error("Not native format: 64bit binary")); | |
64 | } | |
65 | ||
66 | inline static void throw_if_in_32bit_impl(boost::false_type /* is_32bit_platform */) BOOST_NOEXCEPT {} | |
67 | ||
68 | ||
69 | inline static void throw_if_in_32bit() { | |
70 | throw_if_in_32bit_impl( boost::integral_constant<bool, (sizeof(void*) == 4)>() ); | |
71 | } | |
72 | ||
73 | static void throw_if_in_windows() { | |
74 | #if BOOST_OS_WINDOWS | |
75 | boost::throw_exception(std::runtime_error("Not native format: not a PE binary")); | |
76 | #endif | |
77 | } | |
78 | ||
79 | static void throw_if_in_linux() { | |
80 | #if !BOOST_OS_WINDOWS && !BOOST_OS_MACOS && !BOOST_OS_IOS | |
81 | boost::throw_exception(std::runtime_error("Not native format: not an ELF binary")); | |
82 | #endif | |
83 | } | |
84 | ||
85 | static void throw_if_in_macos() { | |
86 | #if BOOST_OS_MACOS || BOOST_OS_IOS | |
87 | boost::throw_exception(std::runtime_error("Not native format: not an Mach-O binary")); | |
88 | #endif | |
89 | } | |
90 | ||
91 | void init(bool throw_if_not_native) { | |
92 | ||
93 | if (boost::dll::detail::elf_info32::parsing_supported(f_)) { | |
94 | if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); } | |
95 | ||
96 | new (impl_.address()) boost::dll::detail::elf_info32(f_); | |
97 | } else if (boost::dll::detail::elf_info64::parsing_supported(f_)) { | |
98 | if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); throw_if_in_32bit(); } | |
99 | ||
100 | new (impl_.address()) boost::dll::detail::elf_info64(f_); | |
101 | } else if (boost::dll::detail::pe_info32::parsing_supported(f_)) { | |
102 | if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); } | |
103 | ||
104 | new (impl_.address()) boost::dll::detail::pe_info32(f_); | |
105 | } else if (boost::dll::detail::pe_info64::parsing_supported(f_)) { | |
106 | if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); throw_if_in_32bit(); } | |
107 | ||
108 | new (impl_.address()) boost::dll::detail::pe_info64(f_); | |
109 | } else if (boost::dll::detail::macho_info32::parsing_supported(f_)) { | |
110 | if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); } | |
111 | ||
112 | new (impl_.address()) boost::dll::detail::macho_info32(f_); | |
113 | } else if (boost::dll::detail::macho_info64::parsing_supported(f_)) { | |
114 | if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); throw_if_in_32bit(); } | |
115 | ||
116 | new (impl_.address()) boost::dll::detail::macho_info64(f_); | |
117 | } else { | |
118 | boost::throw_exception(std::runtime_error("Unsupported binary format")); | |
119 | } | |
120 | } | |
121 | /// @endcond | |
122 | ||
123 | public: | |
124 | /*! | |
125 | * Opens file with specified path and prepares for information extraction. | |
126 | * \param library_path Path to the binary file from which the info must be extracted. | |
127 | * \param throw_if_not_native_format Throw an exception if this file format is not | |
128 | * supported by OS. | |
129 | */ | |
130 | explicit library_info(const boost::filesystem::path& library_path, bool throw_if_not_native_format = true) | |
131 | : f_(library_path, std::ios_base::in | std::ios_base::binary) | |
132 | , impl_() | |
133 | { | |
134 | f_.exceptions( | |
135 | boost::filesystem::ifstream::failbit | |
136 | | boost::filesystem::ifstream::badbit | |
137 | | boost::filesystem::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 | */ | |
146 | std::vector<std::string> sections() { | |
147 | return impl().sections(); | |
148 | } | |
149 | ||
150 | /*! | |
151 | * \return List of all the exportable symbols from all the sections that exist in binary file. | |
152 | */ | |
153 | std::vector<std::string> symbols() { | |
154 | return impl().symbols(); | |
155 | } | |
156 | ||
157 | /*! | |
158 | * \param section_name Name of the section from which symbol names must be returned. | |
159 | * \return List of symbols from the specified section. | |
160 | */ | |
161 | std::vector<std::string> symbols(const char* section_name) { | |
162 | return impl().symbols(section_name); | |
163 | } | |
164 | ||
165 | ||
166 | //! \overload std::vector<std::string> symbols(const char* section_name) | |
167 | std::vector<std::string> symbols(const std::string& section_name) { | |
168 | return impl().symbols(section_name.c_str()); | |
169 | } | |
170 | ||
171 | /*! | |
172 | * \throw Nothing. | |
173 | */ | |
174 | ~library_info() BOOST_NOEXCEPT { | |
175 | typedef boost::dll::detail::x_info_interface T; | |
176 | impl().~T(); | |
177 | } | |
178 | }; | |
179 | ||
180 | }} // namespace boost::dll | |
181 | #endif // BOOST_DLL_LIBRARY_INFO_HPP |