alias.hpp 12 KB

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