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