alias.hpp 14 KB

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