| /* GPLv2 or OpenIB.org BSD (MIT) See COPYING file | |
| These definitions help using the ELF symbol version feature, and must be | |
| used in conjunction with the library's map file. | |
| */ | |
| #ifndef __UTIL_SYMVER_H | |
| #define __UTIL_SYMVER_H | |
| #include <config.h> | |
| #include <ccan/str.h> | |
| /* | |
| These macros should only be used if the library is defining compatibility | |
| symbols, eg: | |
| 213: 000000000000a650 315 FUNC GLOBAL DEFAULT 13 ibv_get_device_list@IBVERBS_1.0 | |
| 214: 000000000000b020 304 FUNC GLOBAL DEFAULT 13 ibv_get_device_list@@IBVERBS_1.1 | |
| Symbols which have only a single implementation should use a normal extern | |
| function and be placed in the correct stanza in the linker map file. | |
| Follow this pattern to use this feature: | |
| public.h: | |
| struct ibv_device **ibv_get_device_list(int *num_devices); | |
| foo.c: | |
| // Implement the latest version | |
| LATEST_SYMVER_FUNC(ibv_get_device_list, 1_1, "IBVERBS_1.1", | |
| struct ibv_device **, | |
| int *num_devices) | |
| { | |
| ... | |
| } | |
| // Implement the compat version | |
| COMPAT_SYMVER_FUNC(ibv_get_device_list, 1_0, "IBVERBS_1.0", | |
| struct ibv_device_1_0 **, | |
| int *num_devices) | |
| { | |
| ... | |
| } | |
| As well as matching information in the map file. | |
| These macros deal with the various uglyness in gcc surrounding symbol | |
| versions | |
| - The internal name __public_1_x is synthesized by the macro | |
| - A prototype for the internal name is created by the macro | |
| - If statically linking the latest symbol expands into a normal function | |
| definition | |
| - If statically linking the compat symbols expand into unused static | |
| functions are are discarded by the compiler. | |
| - The prototype of the latest symbol is checked against the public | |
| prototype (only when compiling statically) | |
| The extra prototypes are included only to avoid -Wmissing-prototypes | |
| warnings. See also Documentation/versioning.md | |
| */ | |
| #if HAVE_FUNC_ATTRIBUTE_SYMVER | |
| #define _MAKE_SYMVER(_local_sym, _public_sym, _ver_str) \ | |
| __attribute__((__symver__(#_public_sym "@" _ver_str))) | |
| #else | |
| #define _MAKE_SYMVER(_local_sym, _public_sym, _ver_str) \ | |
| asm(".symver " #_local_sym "," #_public_sym "@" _ver_str); | |
| #endif | |
| #define _MAKE_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...) \ | |
| _ret __##_public_sym##_##_uniq(__VA_ARGS__); \ | |
| _MAKE_SYMVER(__##_public_sym##_##_uniq, _public_sym, _ver_str) \ | |
| _ret __##_public_sym##_##_uniq(__VA_ARGS__) | |
| #if defined(HAVE_FULL_SYMBOL_VERSIONS) && !defined(_STATIC_LIBRARY_BUILD_) | |
| // Produce all symbol versions for dynamic linking | |
| # define COMPAT_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...) \ | |
| _MAKE_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, __VA_ARGS__) | |
| # define LATEST_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...) \ | |
| _MAKE_SYMVER_FUNC(_public_sym, _uniq, "@" _ver_str, _ret, __VA_ARGS__) | |
| #elif defined(HAVE_LIMITED_SYMBOL_VERSIONS) && !defined(_STATIC_LIBRARY_BUILD_) | |
| /* Produce only implemenations for the latest symbol and tag it with the | |
| * correct symbol versions. This supports dynamic linkers that do not | |
| * understand symbol versions | |
| */ | |
| # define COMPAT_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...) \ | |
| static inline _ret __##_public_sym##_##_uniq(__VA_ARGS__) | |
| # define LATEST_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...) \ | |
| _MAKE_SYMVER_FUNC(_public_sym, _uniq, "@" _ver_str, _ret, __VA_ARGS__) | |
| #else | |
| // Static linking, or linker does not support symbol versions | |
| #define COMPAT_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...) \ | |
| static inline __attribute__((unused)) \ | |
| _ret __##_public_sym##_##_uniq(__VA_ARGS__) | |
| #define LATEST_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...) \ | |
| static __attribute__((unused)) \ | |
| _ret __##_public_sym##_##_uniq(__VA_ARGS__) \ | |
| __attribute__((alias(stringify(_public_sym)))); \ | |
| extern _ret _public_sym(__VA_ARGS__) | |
| #endif | |
| #endif |