/* 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 #include /* 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