[PATCH rdma-core 1/3] Add util/symver.h

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Macros to better support the Linux shared library symbol version mechanism.
These versions of the macros have a way to build with symbol versions
disabled for static linking, and also a way to disable all of the
compat symbols (eg to support uclibc).

The new cmake flag -DNO_COMPAT_SYMS=1 will cause the shared libraries
to be built only with default (@@) symbols.

Signed-off-by: Jason Gunthorpe <jgunthorpe@xxxxxxxxxxxxxxxxxxxx>
---
 CMakeLists.txt                |   9 ++++
 buildlib/config.h.in          |   4 ++
 buildlib/rdma_functions.cmake |   3 ++
 util/CMakeLists.txt           |   1 +
 util/symver.h                 | 100 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+)
 create mode 100644 util/symver.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2324cf49aff5a8..81ec949d6e9f4a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,6 +24,10 @@
 #      Use the historical search path for providers, in the standard system library.
 #  -DKERNEL_DIR='.../linux' (default '')
 #      If set use the kernel UAPI headers from this kernel source tree.
+#  -DNO_COMPAT_SYMS=1 (default disabled)
+#      Do not generate backwards compatibility symbols in the shared
+#      libraries. This may is necessary if using a dynmic linker that does
+#      not support symbol versions, such as uclibc.
 
 cmake_minimum_required(VERSION 2.8.11 FATAL_ERROR)
 project(rdma-core C)
@@ -267,6 +271,11 @@ RDMA_AddOptLDFlag(CMAKE_SHARED_LINKER_FLAGS SUPPORTS_NO_UNDEFINED "-Wl,--no-unde
 
 # Verify that GNU --version-script and asm(".symver") works
 find_package(LDSymVer REQUIRED)
+if (NO_COMPAT_SYMS)
+  set(HAVE_LIMITED_SYMBOL_VERSIONS 1)
+else()
+  set(HAVE_FULL_SYMBOL_VERSIONS 1)
+endif()
 
 #-------------------------
 # Find libraries
diff --git a/buildlib/config.h.in b/buildlib/config.h.in
index b879bc9034d328..81982d89db3d5a 100644
--- a/buildlib/config.h.in
+++ b/buildlib/config.h.in
@@ -33,6 +33,10 @@
 
 #cmakedefine HAVE_WORKING_IF_H 1
 
+// Operating mode for symbol versions
+#cmakedefine HAVE_FULL_SYMBOL_VERSIONS 1
+#cmakedefine HAVE_LIMITED_SYMBOL_VERSIONS 1
+
 @SIZEOF_LONG_CODE@
 
 #if @NL_KIND@ == 3
diff --git a/buildlib/rdma_functions.cmake b/buildlib/rdma_functions.cmake
index ba1bf9c5c5f0c5..d69afd3deb7531 100644
--- a/buildlib/rdma_functions.cmake
+++ b/buildlib/rdma_functions.cmake
@@ -87,6 +87,7 @@ function(rdma_library DEST VERSION_SCRIPT SOVERSION VERSION)
     set_target_properties(${DEST}-static PROPERTIES
       OUTPUT_NAME ${DEST}
       ARCHIVE_OUTPUT_DIRECTORY "${BUILD_LIB}")
+    target_compile_definitions(${DEST}-static PRIVATE _STATIC_LIBRARY_BUILD_=1)
     install(TARGETS ${DEST}-static DESTINATION "${CMAKE_INSTALL_LIBDIR}")
 
     list(APPEND RDMA_STATIC_LIBS ${DEST} ${DEST}-static)
@@ -122,6 +123,7 @@ function(rdma_shared_provider DEST VERSION_SCRIPT SOVERSION VERSION)
     add_library(${DEST}-static STATIC ${ARGN})
     set_target_properties(${DEST}-static PROPERTIES OUTPUT_NAME ${DEST})
     set_target_properties(${DEST}-static PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${BUILD_LIB}")
+    target_compile_definitions(${DEST}-static PRIVATE _STATIC_LIBRARY_BUILD_=1)
     install(TARGETS ${DEST}-static DESTINATION "${CMAKE_INSTALL_LIBDIR}")
 
     list(APPEND RDMA_STATIC_LIBS ${DEST} ${DEST}-static)
@@ -172,6 +174,7 @@ function(rdma_provider DEST)
   if (ENABLE_STATIC)
     add_library(${DEST} STATIC ${ARGN})
     set_target_properties(${DEST} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${BUILD_LIB}")
+    target_compile_definitions(${DEST} PRIVATE _STATIC_LIBRARY_BUILD_=1)
     install(TARGETS ${DEST} DESTINATION "${CMAKE_INSTALL_LIBDIR}")
 
     list(APPEND RDMA_STATIC_LIBS "${DEST}-rdmav${IBVERBS_PABI_VERSION}" ${DEST})
diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt
index 581bf6822ec39f..2ba6a7c79e222c 100644
--- a/util/CMakeLists.txt
+++ b/util/CMakeLists.txt
@@ -1,5 +1,6 @@
 publish_internal_headers(util
   compiler.h
+  symver.h
   util.h
   )
 
diff --git a/util/symver.h b/util/symver.h
new file mode 100644
index 00000000000000..e739b5a11cc2ac
--- /dev/null
+++ b/util/symver.h
@@ -0,0 +1,100 @@
+/* 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
+*/
+
+#define _MAKE_SYMVER(_local_sym, _public_sym, _ver_str)                        \
+	asm(".symver " #_local_sym "," #_public_sym "@" _ver_str)
+#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 _ret __##_public_sym##_##_uniq(__VA_ARGS__)
+#   define LATEST_SYMVER_FUNC(_public_sym, _uniq, _ver_str, _ret, ...)         \
+	static _ret __##_public_sym##_##_uniq(__VA_ARGS__)                     \
+	    __attribute__((alias(stringify(_public_sym))));                    \
+	extern _ret _public_sym(__VA_ARGS__)
+
+#endif
+
+#endif
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux