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_ALIAS_HPP
9 #define BOOST_DLL_ALIAS_HPP
10 
11 #include <boost/dll/config.hpp>
12 #include <boost/static_assert.hpp>
13 #include <boost/predef/compiler.h>
14 #include <boost/predef/os.h>
15 #include <boost/dll/detail/aggressive_ptr_cast.hpp>
16 
17 #if BOOST_COMP_GNUC // MSVC does not have <stdint.h> and defines it in some other header, MinGW requires that header.
18 #include <stdint.h> // intptr_t
19 #endif
20 
21 #ifdef BOOST_HAS_PRAGMA_ONCE
22 # pragma once
23 #endif
24 
25 /// \file boost/dll/alias.hpp
26 /// \brief Includes alias methods and macro. You can include this header or
27 /// boost/dll/shared_library.hpp to reduce dependencies
28 /// in case you do not use the refcountable functions.
29 
30 namespace boost { namespace dll {
31 
32 #ifdef BOOST_DLL_DOXYGEN
33 /// Define this macro to explicitly specify translation unit in which alias must be instantiated.
34 /// See section 'Limitations' for more info. You may find usage examples in source codes of almost each tutorial.
35 /// Must be used in code, when \forcedmacrolink{BOOST_DLL_FORCE_NO_WEAK_EXPORTS} is defined
36 #define BOOST_DLL_FORCE_ALIAS_INSTANTIATION
37 
38 /// Define this macro to disable exporting weak symbols and start using the \forcedmacrolink{BOOST_DLL_FORCE_ALIAS_INSTANTIATION}.
39 /// This may be useful for working around linker problems or to test your program for compatibility with linkers that do not support export of weak symbols.
40 #define BOOST_DLL_FORCE_NO_WEAK_EXPORTS
41 #endif
42 
43 #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
44 
45 #define BOOST_DLL_SELECTANY __declspec(selectany)
46 
47 #define BOOST_DLL_SECTION(SectionName, Permissions)                                             \
48     BOOST_STATIC_ASSERT_MSG(                                                                    \
49         sizeof(#SectionName) < 10,                                                              \
50         "Some platforms require section names to be at most 8 bytes"                            \
51     );                                                                                          \
52     __pragma(section(#SectionName, Permissions)) __declspec(allocate(#SectionName))             \
53     /**/
54 
55 #else // #if BOOST_COMP_MSVC
56 
57 
58 #if BOOST_OS_WINDOWS || BOOST_OS_ANDROID || BOOST_COMP_IBM
59 // There are some problems with mixing `__dllexport__` and `weak` using MinGW
60 // See https://sourceware.org/bugzilla/show_bug.cgi?id=17480
61 //
62 // Android had an issue with exporting weak symbols
63 // https://code.google.com/p/android/issues/detail?id=70206
64 #define BOOST_DLL_SELECTANY
65 #else // #if BOOST_OS_WINDOWS
66 /*!
67 * \brief Macro that allows linker to select any occurrence of this symbol instead of
68 * failing with 'multiple definitions' error at linktime.
69 *
70 * This macro does not work on Android, IBM XL C/C++ and MinGW+Windows
71 * because of linker problems with exporting weak symbols
72 * (See https://code.google.com/p/android/issues/detail?id=70206, https://sourceware.org/bugzilla/show_bug.cgi?id=17480)
73 */
74 #define BOOST_DLL_SELECTANY __attribute__((weak))
75 #endif // #if BOOST_OS_WINDOWS
76 
77 // TODO: improve section permissions using following info:
78 // http://stackoverflow.com/questions/6252812/what-does-the-aw-flag-in-the-section-attribute-mean
79 
80 #if !BOOST_OS_MACOS && !BOOST_OS_IOS
81 /*!
82 * \brief Macro that puts symbol to a specific section. On MacOS all the sections are put into "__DATA" segment.
83 * \param SectionName Name of the section. Must be a valid C identifier without quotes not longer than 8 bytes.
84 * \param Permissions Can be "read" or "write" (without quotes!).
85 */
86 #define BOOST_DLL_SECTION(SectionName, Permissions)                                             \
87     BOOST_STATIC_ASSERT_MSG(                                                                    \
88         sizeof(#SectionName) < 10,                                                              \
89         "Some platforms require section names to be at most 8 bytes"                            \
90     );                                                                                          \
91     __attribute__ ((section (#SectionName)))                                                    \
92     /**/
93 #else // #if !BOOST_OS_MACOS && !BOOST_OS_IOS
94 
95 #define BOOST_DLL_SECTION(SectionName, Permissions)                                             \
96     BOOST_STATIC_ASSERT_MSG(                                                                    \
97         sizeof(#SectionName) < 10,                                                              \
98         "Some platforms require section names to be at most 8 bytes"                            \
99     );                                                                                          \
100     __attribute__ ((section ( "__DATA," #SectionName)))                                         \
101     /**/
102 
103 #endif // #if #if !BOOST_OS_MACOS && !BOOST_OS_IOS
104 
105 #endif // #if BOOST_COMP_MSVC
106 
107 
108 // Alias - is just a variable that pointers to original data
109 //
110 // A few attempts were made to avoid additional indirection:
111 // 1)
112 //          // Does not work on Windows, work on Linux
113 //          extern "C" BOOST_SYMBOL_EXPORT void AliasName() {
114 //              reinterpret_cast<void (*)()>(Function)();
115 //          }
116 //
117 // 2)
118 //          // Does not work on Linux (changes permissions of .text section and produces incorrect DSO)
119 //          extern "C" BOOST_SYMBOL_EXPORT void* __attribute__ ((section(".text#")))
120 //                  func_ptr = *reinterpret_cast<std::ptrdiff_t**>(&foo::bar);
121 //
122 // 3)       // requires mangled name of `Function`
123 //          //  AliasName() __attribute__ ((weak, alias ("Function")))
124 //
125 //          // hard to use
126 //          `#pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue")`
127 
128 /*!
129 * \brief Makes an alias name for exported function or variable.
130 *
131 * This macro is useful in cases of long mangled C++ names. For example some `void boost::foo(std::string)`
132 * function name will change to something like `N5boostN3foosE` after mangling.
133 * Importing function by `N5boostN3foosE` name does not looks user friendly, especially assuming the fact
134 * that different compilers have different mangling schemes. AliasName is the name that won't be mangled
135 * and can be used as a portable import name.
136 *
137 *
138 * Can be used in any namespace, including global. FunctionOrVar must be fully qualified,
139 * so that address of it could be taken. Multiple different aliases for a single variable/function
140 * are allowed.
141 *
142 * Make sure that AliasNames are unique per library/executable. Functions or variables
143 * in global namespace must not have names same as AliasNames.
144 *
145 * Same AliasName in different translation units must point to the same FunctionOrVar.
146 *
147 * Puts all the aliases into the \b "boostdll" read only section of the binary. Equal to
148 * \forcedmacrolink{BOOST_DLL_ALIAS_SECTIONED}(FunctionOrVar, AliasName, boostdll).
149 *
150 * \param FunctionOrVar Function or variable for which an alias must be made.
151 * \param AliasName Name of the alias. Must be a valid C identifier.
152 *
153 * \b Example:
154 * \code
155 * namespace foo {
156 *   void bar(std::string&);
157 *
158 *   BOOST_DLL_ALIAS(foo::bar, foo_bar)
159 * }
160 *
161 * BOOST_DLL_ALIAS(foo::bar, foo_bar_another_alias_name)
162 * \endcode
163 *
164 * \b See: \forcedmacrolink{BOOST_DLL_ALIAS_SECTIONED} for making alias in a specific section.
165 */
166 #define BOOST_DLL_ALIAS(FunctionOrVar, AliasName)                       \
167     BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, boostdll)       \
168     /**/
169 
170 
171 #if ((BOOST_COMP_GNUC && BOOST_OS_WINDOWS) || BOOST_OS_ANDROID || BOOST_COMP_IBM || defined(BOOST_DLL_FORCE_NO_WEAK_EXPORTS)) \
172     && !defined(BOOST_DLL_FORCE_ALIAS_INSTANTIATION) && !defined(BOOST_DLL_DOXYGEN)
173 
174 #define BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, SectionName)                        \
175     namespace _autoaliases {                                                                    \
176         extern "C" BOOST_SYMBOL_EXPORT const void *AliasName;                                   \
177     } /* namespace _autoaliases */                                                              \
178     /**/
179 
180 #define BOOST_DLL_AUTO_ALIAS(FunctionOrVar)                                                     \
181     namespace _autoaliases {                                                                    \
182         extern "C" BOOST_SYMBOL_EXPORT const void *FunctionOrVar;                               \
183     } /* namespace _autoaliases */                                                              \
184     /**/
185 #else
186 // Note: we can not use `aggressive_ptr_cast` here, because in that case GCC applies
187 // different permissions to the section and it causes Segmentation fault.
188 // Note: we can not use `boost::addressof()` here, because in that case GCC
189 // may optimize away the FunctionOrVar instance and we'll get a pointer to unexisting symbol.
190 /*!
191 * \brief Same as \forcedmacrolink{BOOST_DLL_ALIAS} but puts alias name into the user specified section.
192 *
193 * \param FunctionOrVar Function or variable for which an alias must be made.
194 * \param AliasName Name of the alias. Must be a valid C identifier.
195 * \param SectionName Name of the section. Must be a valid C identifier without quotes not longer than 8 bytes.
196 *
197 * \b Example:
198 * \code
199 * namespace foo {
200 *   void bar(std::string&);
201 *
202 *   BOOST_DLL_ALIAS_SECTIONED(foo::bar, foo_bar, sect_1) // section "sect_1" now exports "foo_bar"
203 * }
204 * \endcode
205 *
206 */
207 #define BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, SectionName)                        \
208     namespace _autoaliases {                                                                    \
209         extern "C" BOOST_SYMBOL_EXPORT const void *AliasName;                                   \
210         BOOST_DLL_SECTION(SectionName, read) BOOST_DLL_SELECTANY                                \
211         const void * AliasName = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(      \
212             &FunctionOrVar                                                                      \
213         ));                                                                                     \
214     } /* namespace _autoaliases */                                                              \
215     /**/
216 
217 /*!
218 * \brief Exports variable or function with unmangled alias name.
219 *
220 * This macro is useful in cases of long mangled C++ names. For example some `void boost::foo(std::string)`
221 * function name will change to something like `N5boostN3foosE` after mangling.
222 * Importing function by `N5boostN3foosE` name does not looks user friendly, especially assuming the fact
223 * that different compilers have different mangling schemes.*
224 *
225 * Must be used in scope where FunctionOrVar declared. FunctionOrVar must be a valid C name, which means that
226 * it must not contain `::`.
227 *
228 * Functions or variables
229 * in global namespace must not have names same as FunctionOrVar.
230 *
231 * Puts all the aliases into the \b "boostdll" read only section of the binary. Almost same as
232 * \forcedmacrolink{BOOST_DLL_ALIAS}(FunctionOrVar, FunctionOrVar).
233 *
234 * \param FunctionOrVar Function or variable for which an unmangled alias must be made.
235 *
236 * \b Example:
237 * \code
238 * namespace foo {
239 *   void bar(std::string&);
240 *   BOOST_DLL_AUTO_ALIAS(bar)
241 * }
242 *
243 * \endcode
244 *
245 * \b See: \forcedmacrolink{BOOST_DLL_ALIAS} for making an alias with different names.
246 */
247 
248 #define BOOST_DLL_AUTO_ALIAS(FunctionOrVar)                                                     \
249     namespace _autoaliases {                                                                    \
250         BOOST_DLL_SELECTANY const void * dummy_ ## FunctionOrVar                                \
251             = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(                         \
252                 &FunctionOrVar                                                                  \
253             ));                                                                                 \
254         extern "C" BOOST_SYMBOL_EXPORT const void *FunctionOrVar;                               \
255         BOOST_DLL_SECTION(boostdll, read) BOOST_DLL_SELECTANY                                   \
256         const void * FunctionOrVar = dummy_ ## FunctionOrVar;                                   \
257     } /* namespace _autoaliases */                                                              \
258     /**/
259 
260 
261 #endif
262 
263 
264 }} // namespace boost::dll
265 
266 
267 #endif // BOOST_DLL_ALIAS_HPP
268 
269