alias.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #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. #else
  159. // Note: we can not use `aggressive_ptr_cast` here, because in that case GCC applies
  160. // different permissions to the section and it causes Segmentation fault.
  161. // Note: we can not use `boost::addressof()` here, because in that case GCC
  162. // may optimize away the FunctionOrVar instance and we'll get a pointer to unexisting symbol.
  163. /*!
  164. * \brief Same as \forcedmacrolink{BOOST_DLL_ALIAS} but puts alias name into the user specified section.
  165. *
  166. * \param FunctionOrVar Function or variable for which an alias must be made.
  167. * \param AliasName Name of the alias. Must be a valid C identifier.
  168. * \param SectionName Name of the section. Must be a valid C identifier without quotes not longer than 8 bytes.
  169. *
  170. * \b Example:
  171. * \code
  172. * namespace foo {
  173. * void bar(std::string&);
  174. *
  175. * BOOST_DLL_ALIAS_SECTIONED(foo::bar, foo_bar, sect_1) // section "sect_1" now exports "foo_bar"
  176. * }
  177. * \endcode
  178. *
  179. */
  180. #define BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, SectionName) \
  181. namespace _autoaliases { \
  182. extern "C" BOOST_SYMBOL_EXPORT const void *AliasName; \
  183. BOOST_DLL_SECTION(SectionName, read) BOOST_DLL_SELECTANY \
  184. const void * AliasName = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>( \
  185. &FunctionOrVar \
  186. )); \
  187. } /* namespace _autoaliases */ \
  188. /**/
  189. /*!
  190. * \brief Exports variable or function with unmangled alias name.
  191. *
  192. * This macro is useful in cases of long mangled C++ names. For example some `void boost::foo(std::string)`
  193. * function name will change to something like `N5boostN3foosE` after mangling.
  194. * Importing function by `N5boostN3foosE` name does not looks user friendly, especially assuming the fact
  195. * that different compilers have different mangling schemes.*
  196. *
  197. * Must be used in scope where FunctionOrVar declared. FunctionOrVar must be a valid C name, which means that
  198. * it must not contain `::`.
  199. *
  200. * Functions or variables
  201. * in global namespace must not have names same as FunctionOrVar.
  202. *
  203. * Puts all the aliases into the \b "boostdll" read only section of the binary. Almost same as
  204. * \forcedmacrolink{BOOST_DLL_ALIAS}(FunctionOrVar, FunctionOrVar).
  205. *
  206. * \param FunctionOrVar Function or variable for which an unmangled alias must be made.
  207. *
  208. * \b Example:
  209. * \code
  210. * namespace foo {
  211. * void bar(std::string&);
  212. * BOOST_DLL_AUTO_ALIAS(bar)
  213. * }
  214. *
  215. * \endcode
  216. *
  217. * \b See: \forcedmacrolink{BOOST_DLL_ALIAS} for making an alias with different names.
  218. */
  219. #define BOOST_DLL_AUTO_ALIAS(FunctionOrVar) \
  220. namespace _autoaliases { \
  221. BOOST_DLL_SELECTANY const void * dummy_ ## FunctionOrVar \
  222. = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>( \
  223. &FunctionOrVar \
  224. )); \
  225. extern "C" BOOST_SYMBOL_EXPORT const void *FunctionOrVar; \
  226. BOOST_DLL_SECTION(boostdll, read) BOOST_DLL_SELECTANY \
  227. const void * FunctionOrVar = dummy_ ## FunctionOrVar; \
  228. } /* namespace _autoaliases */ \
  229. /**/
  230. #endif
  231. }} // namespace boost::dll
  232. #endif // BOOST_DLL_ALIAS_HPP