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