1// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
2// Copyright Antony Polukhin, 2015-2024.
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/dll/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/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.
29namespace boost { namespace dll {
30
31#if BOOST_OS_WINDOWS
32namespace detail {
33 inline boost::dll::fs::path program_location_impl(boost::dll::fs::error_code& ec) {
34 return boost::dll::detail::path_from_handle(NULL, ec);
35 }
36} // namespace detail
37#endif
38
39 /*!
40 * On success returns full path and name to the binary object that holds symbol pointed by ptr_to_symbol.
41 *
42 * \param ptr_to_symbol Pointer to symbol which location is to be determined.
43 * \param ec Variable that will be set to the result of the operation.
44 * \return Path to the binary object that holds symbol or empty path in case error.
45 * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}.
46 *
47 * \b Examples:
48 * \code
49 * int main() {
50 * dll::symbol_location_ptr(std::set_terminate(0)); // returns "/some/path/libmy_terminate_handler.so"
51 * dll::symbol_location_ptr(::signal(SIGSEGV, SIG_DFL)); // returns "/some/path/libmy_symbol_handler.so"
52 * }
53 * \endcode
54 */
55 template <class T>
56 inline boost::dll::fs::path symbol_location_ptr(T ptr_to_symbol, boost::dll::fs::error_code& ec) {
57 static_assert(boost::is_pointer<T>::value, "boost::dll::symbol_location_ptr works only with pointers! `ptr_to_symbol` must be a pointer");
58 boost::dll::fs::path ret;
59 if (!ptr_to_symbol) {
60 ec = boost::dll::fs::make_error_code(
61 e: boost::dll::fs::errc::bad_address
62 );
63
64 return ret;
65 }
66 ec.clear();
67
68 const void* ptr = boost::dll::detail::aggressive_ptr_cast<const void*>(ptr_to_symbol);
69
70#if BOOST_OS_WINDOWS
71 boost::winapi::MEMORY_BASIC_INFORMATION_ mbi;
72 if (!boost::winapi::VirtualQuery(ptr, &mbi, sizeof(mbi))) {
73 ec = boost::dll::detail::last_error_code();
74 return ret;
75 }
76
77 return boost::dll::detail::path_from_handle(reinterpret_cast<boost::winapi::HMODULE_>(mbi.AllocationBase), ec);
78#else
79 Dl_info info;
80
81 // Some of the libc headers miss `const` in `dladdr(const void*, Dl_info*)`
82 const int res = dladdr(address: const_cast<void*>(ptr), info: &info);
83
84 if (res) {
85 ret = info.dli_fname;
86 } else {
87 boost::dll::detail::reset_dlerror();
88 ec = boost::dll::fs::make_error_code(
89 e: boost::dll::fs::errc::bad_address
90 );
91 }
92
93 return ret;
94#endif
95 }
96
97 //! \overload symbol_location_ptr(const void* ptr_to_symbol, boost::dll::fs::error_code& ec)
98 template <class T>
99 inline boost::dll::fs::path symbol_location_ptr(T ptr_to_symbol) {
100 boost::dll::fs::path ret;
101 boost::dll::fs::error_code ec;
102 ret = boost::dll::symbol_location_ptr(ptr_to_symbol, ec);
103
104 if (ec) {
105 boost::dll::detail::report_error(ec, message: "boost::dll::symbol_location_ptr(T ptr_to_symbol) failed");
106 }
107
108 return ret;
109 }
110
111 /*!
112 * On success returns full path and name of the binary object that holds symbol.
113 *
114 * \tparam T Type of the symbol, must not be explicitly specified.
115 * \param symbol Symbol which location is to be determined.
116 * \param ec Variable that will be set to the result of the operation.
117 * \return Path to the binary object that holds symbol or empty path in case error.
118 * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}.
119 *
120 * \b Examples:
121 * \code
122 * int var;
123 * void foo() {}
124 *
125 * int main() {
126 * dll::symbol_location(var); // returns program location
127 * dll::symbol_location(foo); // returns program location
128 * dll::symbol_location(std::cerr); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6"
129 * dll::symbol_location(std::placeholders::_1); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6"
130 * dll::symbol_location(std::puts); // returns location of libc: "/lib/x86_64-linux-gnu/libc.so.6"
131 * }
132 * \endcode
133 */
134 template <class T>
135 inline boost::dll::fs::path symbol_location(const T& symbol, boost::dll::fs::error_code& ec) {
136 ec.clear();
137 return boost::dll::symbol_location_ptr(
138 boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)),
139 ec
140 );
141 }
142
143#if BOOST_COMP_MSVC < BOOST_VERSION_NUMBER(14,0,0)
144 // Without this MSVC 7.1 fails with:
145 // ..\boost\dll\runtime_symbol_info.hpp(133) : error C2780: 'filesystem::path dll::symbol_location(const T &)' : expects 1 arguments - 2 provided
146 template <class T>
147 inline boost::dll::fs::path symbol_location(const T& symbol, const char* /*workaround*/ = 0)
148#else
149 //! \overload symbol_location(const T& symbol, boost::dll::fs::error_code& ec)
150 template <class T>
151 inline boost::dll::fs::path symbol_location(const T& symbol)
152#endif
153 {
154 boost::dll::fs::path ret;
155 boost::dll::fs::error_code ec;
156 ret = boost::dll::symbol_location_ptr(
157 boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)),
158 ec
159 );
160
161 if (ec) {
162 boost::dll::detail::report_error(ec, message: "boost::dll::symbol_location(const T& symbol) failed");
163 }
164
165 return ret;
166 }
167
168 /// @cond
169 // We have anonymous namespace here to make sure that `this_line_location()` method is instantiated in
170 // current translation unit and is not shadowed by instantiations from other units.
171 //
172 // boost-no-inspect
173 namespace {
174 /// @endcond
175
176 /*!
177 * On success returns full path and name of the binary object that holds the current line of code
178 * (the line in which the `this_line_location()` method was called).
179 *
180 * \param ec Variable that will be set to the result of the operation.
181 * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}.
182 */
183 static inline boost::dll::fs::path this_line_location(boost::dll::fs::error_code& ec) {
184 typedef boost::dll::fs::path(func_t)(boost::dll::fs::error_code& );
185 func_t& f = this_line_location;
186 return boost::dll::symbol_location(symbol&: f, ec);
187 }
188
189 //! \overload this_line_location(boost::dll::fs::error_code& ec)
190 static inline boost::dll::fs::path this_line_location() {
191 boost::dll::fs::path ret;
192 boost::dll::fs::error_code ec;
193 ret = this_line_location(ec);
194
195 if (ec) {
196 boost::dll::detail::report_error(ec, message: "boost::dll::this_line_location() failed");
197 }
198
199 return ret;
200 }
201
202 /// @cond
203 } // anonymous namespace
204 /// @endcond
205
206 /*!
207 * On success returns full path and name of the currently running program (the one which contains the `main()` function).
208 *
209 * Return value can be used as a parameter for shared_library. See Tutorial "Linking plugin into the executable"
210 * for usage example. Flag '-rdynamic' must be used when linking the plugin into the executable
211 * on Linux OS.
212 *
213 * \param ec Variable that will be set to the result of the operation.
214 * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept \forcedlinkfs{error_code} also throws \forcedlinkfs{system_error}.
215 */
216 inline boost::dll::fs::path program_location(boost::dll::fs::error_code& ec) {
217 ec.clear();
218 return boost::dll::detail::program_location_impl(ec);
219 }
220
221 //! \overload program_location(boost::dll::fs::error_code& ec) {
222 inline boost::dll::fs::path program_location() {
223 boost::dll::fs::path ret;
224 boost::dll::fs::error_code ec;
225 ret = boost::dll::detail::program_location_impl(ec);
226
227 if (ec) {
228 boost::dll::detail::report_error(ec, message: "boost::dll::program_location() failed");
229 }
230
231 return ret;
232 }
233
234}} // namespace boost::dll
235
236#endif // BOOST_DLL_RUNTIME_SYMBOL_INFO_HPP
237
238

source code of boost/libs/dll/include/boost/dll/runtime_symbol_info.hpp