]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright 2014 Renato Tegon Forti, Antony Polukhin. |
2 | // Copyright 2015-2016 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_RUNTIME_SYMBOL_INFO_HPP | |
9 | #define BOOST_DLL_RUNTIME_SYMBOL_INFO_HPP | |
10 | ||
11 | #include <boost/config.hpp> | |
12 | #include <boost/predef/os.h> | |
13 | #include <boost/predef/compiler/visualc.h> | |
14 | #include <boost/dll/detail/aggressive_ptr_cast.hpp> | |
15 | #if BOOST_OS_WINDOWS | |
16 | # include <boost/detail/winapi/dll.hpp> | |
17 | # include <boost/dll/detail/windows/path_from_handle.hpp> | |
18 | #else | |
19 | # include <dlfcn.h> | |
20 | # include <boost/dll/detail/posix/program_location_impl.hpp> | |
21 | #endif | |
22 | ||
23 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
24 | # pragma once | |
25 | #endif | |
26 | ||
27 | /// \file boost/dll/runtime_symbol_info.hpp | |
28 | /// \brief Provides methods for getting acceptable by boost::dll::shared_library location of symbol, source line or program. | |
29 | namespace boost { namespace dll { | |
30 | ||
31 | namespace detail { | |
32 | #if BOOST_OS_WINDOWS | |
33 | inline boost::filesystem::path symbol_location_impl(const void* symbol, boost::system::error_code& ec) { | |
34 | boost::filesystem::path ret; | |
35 | ||
36 | boost::detail::winapi::MEMORY_BASIC_INFORMATION_ mbi; | |
37 | if (!boost::detail::winapi::VirtualQuery(symbol, &mbi, sizeof(mbi))) { | |
38 | ec = boost::dll::detail::last_error_code(); | |
39 | return ret; | |
40 | } | |
41 | ||
42 | return boost::dll::detail::path_from_handle(reinterpret_cast<boost::detail::winapi::HMODULE_>(mbi.AllocationBase), ec); | |
43 | } | |
44 | ||
45 | inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) { | |
46 | return boost::dll::detail::path_from_handle(NULL, ec); | |
47 | } | |
48 | #else | |
49 | inline boost::filesystem::path symbol_location_impl(const void* symbol, boost::system::error_code& ec) { | |
50 | boost::filesystem::path ret; | |
51 | Dl_info info; | |
52 | ||
53 | // Some of the libc headers miss `const` in `dladdr(const void*, Dl_info*)` | |
54 | const int res = dladdr(const_cast<void*>(symbol), &info); | |
55 | ||
56 | if (res) { | |
57 | ret = info.dli_fname; | |
58 | } else { | |
59 | boost::dll::detail::reset_dlerror(); | |
60 | ec = boost::system::error_code( | |
61 | boost::system::errc::bad_address, | |
62 | boost::system::generic_category() | |
63 | ); | |
64 | } | |
65 | ||
66 | return ret; | |
67 | } | |
68 | #endif | |
69 | } // namespace detail | |
70 | ||
71 | /*! | |
72 | * On success returns full path and name of the binary object that holds symbol. | |
73 | * \tparam T Type of the symbol, must not be explicitly specified. | |
74 | * \param symbol Symbol which location is to be determined. | |
75 | * \param ec Variable that will be set to the result of the operation. | |
76 | * \return Path to the binary object that holds symbol or empty path in case error. | |
77 | * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept boost::system::error_code also throws boost::system::system_error. | |
78 | * | |
79 | * \b Examples: | |
80 | * \code | |
81 | * int var; | |
82 | * void foo() {} | |
83 | * | |
84 | * int main() { | |
85 | * dll::symbol_location(var); // returns program location | |
86 | * dll::symbol_location(foo); // returns program location | |
87 | * dll::symbol_location(std::cerr); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" | |
88 | * dll::symbol_location(std::placeholders::_1); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" | |
89 | * dll::symbol_location(std::puts); // returns location of libc: "/lib/x86_64-linux-gnu/libc.so.6" | |
90 | * } | |
91 | * \endcode | |
92 | */ | |
93 | template <class T> | |
94 | inline boost::filesystem::path symbol_location(const T& symbol, boost::system::error_code& ec) { | |
95 | ec.clear(); | |
96 | return boost::dll::detail::symbol_location_impl( | |
97 | boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)), | |
98 | ec | |
99 | ); | |
100 | } | |
101 | ||
102 | #if BOOST_COMP_MSVC < BOOST_VERSION_NUMBER(14,0,0) | |
103 | // Without this MSVC 7.1 fails with: | |
104 | // ..\boost\dll\runtime_symbol_info.hpp(133) : error C2780: 'filesystem::path dll::symbol_location(const T &)' : expects 1 arguments - 2 provided | |
105 | template <class T> | |
106 | inline boost::filesystem::path symbol_location(const T& symbol, const char* /*workaround*/ = 0) | |
107 | #else | |
108 | //! \overload symbol_location(const T& symbol, boost::system::error_code& ec) | |
109 | template <class T> | |
110 | inline boost::filesystem::path symbol_location(const T& symbol) | |
111 | #endif | |
112 | { | |
113 | boost::filesystem::path ret; | |
114 | boost::system::error_code ec; | |
115 | ret = boost::dll::detail::symbol_location_impl( | |
116 | boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)), | |
117 | ec | |
118 | ); | |
119 | ||
120 | if (ec) { | |
121 | boost::dll::detail::report_error(ec, "boost::dll::symbol_location(const T& symbol) failed"); | |
122 | } | |
123 | ||
124 | return ret; | |
125 | } | |
126 | ||
127 | /// @cond | |
128 | // We have anonymous namespace here to make sure that `this_line_location()` method is instantiated in | |
129 | // current translation module and is not shadowed by instantiations from other modules. | |
130 | namespace { | |
131 | /// @endcond | |
132 | ||
133 | /*! | |
134 | * On success returns full path and name of the binary object that holds the current line of code | |
135 | * (the line in which the `this_line_location()` method was called). | |
136 | * | |
137 | * \param ec Variable that will be set to the result of the operation. | |
138 | * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept boost::system::error_code also throws boost::system::system_error. | |
139 | */ | |
140 | static inline boost::filesystem::path this_line_location(boost::system::error_code& ec) { | |
141 | typedef boost::filesystem::path(func_t)(boost::system::error_code& ); | |
142 | func_t& f = this_line_location; | |
143 | return boost::dll::symbol_location(f, ec); | |
144 | } | |
145 | ||
146 | //! \overload this_line_location(boost::system::error_code& ec) | |
147 | static inline boost::filesystem::path this_line_location() { | |
148 | boost::filesystem::path ret; | |
149 | boost::system::error_code ec; | |
150 | ret = this_line_location(ec); | |
151 | ||
152 | if (ec) { | |
153 | boost::dll::detail::report_error(ec, "boost::dll::this_line_location() failed"); | |
154 | } | |
155 | ||
156 | return ret; | |
157 | } | |
158 | ||
159 | /// @cond | |
160 | } // anonymous namespace | |
161 | /// @endcond | |
162 | ||
163 | /*! | |
164 | * On success returns full path and name of the currently running program (the one which contains the `main()` function). | |
165 | * | |
166 | * Return value can be used as a parameter for shared_library. See Tutorial "Linking plugin into the executable" | |
167 | * for usage example. Flag '-rdynamic' must be used when linking the plugin into the executable | |
168 | * on Linux OS. | |
169 | * | |
170 | * \param ec Variable that will be set to the result of the operation. | |
171 | * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept boost::system::error_code also throws boost::system::system_error. | |
172 | */ | |
173 | inline boost::filesystem::path program_location(boost::system::error_code& ec) { | |
174 | ec.clear(); | |
175 | return boost::dll::detail::program_location_impl(ec); | |
176 | } | |
177 | ||
178 | //! \overload program_location(boost::system::error_code& ec) { | |
179 | inline boost::filesystem::path program_location() { | |
180 | boost::filesystem::path ret; | |
181 | boost::system::error_code ec; | |
182 | ret = boost::dll::detail::program_location_impl(ec); | |
183 | ||
184 | if (ec) { | |
185 | boost::dll::detail::report_error(ec, "boost::dll::program_location() failed"); | |
186 | } | |
187 | ||
188 | return ret; | |
189 | } | |
190 | ||
191 | }} // namespace boost::dll | |
192 | ||
193 | #endif // BOOST_DLL_RUNTIME_SYMBOL_INFO_HPP | |
194 |