acl-devel
[Top][All Lists]
Advanced

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

[PATCH] Better supported way to set symbol versions for legacy syscalls


From: Alexander Miller
Subject: [PATCH] Better supported way to set symbol versions for legacy syscalls
Date: Sat, 28 May 2022 22:42:56 +0200

Using a linker script to set symbol versions is an undocumented
hack and doesn't work reliably in many cases. It works (to some
degree) with the bfd linker, but fails with gold or lld. And even
with bfd it can break when using --gc-sections or LTO.

For example, the result may be a library where the code has been
discarded and the versioned symbols are unusable, i.e.,
    23: 00000000     0 NOTYPE  GLOBAL DEFAULT  ABS getxattr@ATTR_1.0
instead of
    23: 000033c0     0 FUNC    GLOBAL DEFAULT   11 getxattr@ATTR_1.0

Remove the linker script entirely and set symbol versions with the
__attribute__((symver(...))) if available (in gcc >= 10, but not in
clang), otherwise use the traditional global asm solution with a
.symver directive.
These approaches are well supported by (almost) all configurations.
(The exception is an old gcc with LTO; a workaround is included, but
very old versions may need -flto-partition=none to build with LTO).

Signed-off-by: Alexander Miller <alex.miller@gmx.de>
---
 libattr/Makemodule.am |  5 +----
 libattr/libattr.lds   | 12 ------------
 libattr/syscalls.c    | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 16 deletions(-)
 delete mode 100644 libattr/libattr.lds

diff --git a/libattr/Makemodule.am b/libattr/Makemodule.am
index 4b3720c..e9f5661 100644
--- a/libattr/Makemodule.am
+++ b/libattr/Makemodule.am
@@ -8,7 +8,7 @@ LT_CURRENT = 2
 LT_AGE = 1
 LTVERSION = $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)

-libattr_la_DEPENDENCIES = exports libattr/libattr.lds
+libattr_la_DEPENDENCIES = exports
 libattr_la_SOURCES = \
        libattr/attr_copy_action.c \
        libattr/attr_copy_check.c \
@@ -20,7 +20,4 @@ libattr_la_SOURCES = \
 libattr_la_CFLAGS = -include libattr/libattr.h
 libattr_la_LDFLAGS = \
        -Wl,--version-script,$(top_srcdir)/exports \
-       -Wl,$(top_srcdir)/libattr/libattr.lds \
        -version-info $(LTVERSION)
-
-EXTRA_DIST += libattr/libattr.lds
diff --git a/libattr/libattr.lds b/libattr/libattr.lds
deleted file mode 100644
index 947f15d..0000000
--- a/libattr/libattr.lds
+++ /dev/null
@@ -1,12 +0,0 @@
-"fgetxattr@ATTR_1.0" = libattr_fgetxattr;
-"flistxattr@ATTR_1.0" = libattr_flistxattr;
-"fremovexattr@ATTR_1.0" = libattr_fremovexattr;
-"fsetxattr@ATTR_1.0" = libattr_fsetxattr;
-"getxattr@ATTR_1.0" = libattr_getxattr;
-"lgetxattr@ATTR_1.0" = libattr_lgetxattr;
-"listxattr@ATTR_1.0" = libattr_listxattr;
-"llistxattr@ATTR_1.0" = libattr_llistxattr;
-"lremovexattr@ATTR_1.0" = libattr_lremovexattr;
-"lsetxattr@ATTR_1.0" = libattr_lsetxattr;
-"removexattr@ATTR_1.0" = libattr_removexattr;
-"setxattr@ATTR_1.0" = libattr_setxattr;
diff --git a/libattr/syscalls.c b/libattr/syscalls.c
index 721ad7f..1f5fd7a 100644
--- a/libattr/syscalls.c
+++ b/libattr/syscalls.c
@@ -26,6 +26,27 @@
 #include <sys/syscall.h>
 #include <sys/xattr.h>

+/*
+ * Versioning of compat symbols:
+ * prefer symver attribute if available (since gcc 10),
+ * fall back to traditional .symver asm directive otherwise.
+ */
+#ifdef __has_attribute
+# if __has_attribute(symver)
+#  define SYMVER(cn, vn) __typeof(cn) cn __attribute__((symver(vn)))
+# elif __has_attribute(no_reorder)
+   /*
+    * Avoid wrong partitioning with older gcc and LTO. May not work reliably
+    * with all versions; use -flto-partition=none if you encounter problems.
+    */
+#  define SYMVER(cn, vn) __typeof(cn) cn __attribute__((noreorder)); \
+                        __asm__(".symver " #cn "," vn)
+# endif
+#endif
+#ifndef SYMVER
+#  define SYMVER(cn, vn) __asm__(".symver " #cn "," vn)
+#endif
+
 #ifdef HAVE_VISIBILITY_ATTRIBUTE
 # pragma GCC visibility push(default)
 #endif
@@ -35,66 +56,78 @@ int libattr_setxattr(const char *path, const char *name,
 {
        return syscall(__NR_setxattr, path, name, value, size, flags);
 }
+SYMVER(libattr_setxattr, "setxattr@ATTR_1.0");

 int libattr_lsetxattr(const char *path, const char *name,
                      void *value, size_t size, int flags)
 {
        return syscall(__NR_lsetxattr, path, name, value, size, flags);
 }
+SYMVER(libattr_lsetxattr, "lsetxattr@ATTR_1.0");

 int libattr_fsetxattr(int filedes, const char *name,
                      void *value, size_t size, int flags)
 {
        return syscall(__NR_fsetxattr, filedes, name, value, size, flags);
 }
+SYMVER(libattr_fsetxattr, "fsetxattr@ATTR_1.0");

 ssize_t libattr_getxattr(const char *path, const char *name,
                         void *value, size_t size)
 {
        return syscall(__NR_getxattr, path, name, value, size);
 }
+SYMVER(libattr_getxattr, "getxattr@ATTR_1.0");

 ssize_t libattr_lgetxattr(const char *path, const char *name,
                          void *value, size_t size)
 {
        return syscall(__NR_lgetxattr, path, name, value, size);
 }
+SYMVER(libattr_lgetxattr, "lgetxattr@ATTR_1.0");

 ssize_t libattr_fgetxattr(int filedes, const char *name,
                          void *value, size_t size)
 {
        return syscall(__NR_fgetxattr, filedes, name, value, size);
 }
+SYMVER(libattr_fgetxattr, "fgetxattr@ATTR_1.0");

 ssize_t libattr_listxattr(const char *path, char *list, size_t size)
 {
        return syscall(__NR_listxattr, path, list, size);
 }
+SYMVER(libattr_listxattr, "listxattr@ATTR_1.0");

 ssize_t libattr_llistxattr(const char *path, char *list, size_t size)
 {
        return syscall(__NR_llistxattr, path, list, size);
 }
+SYMVER(libattr_llistxattr, "llistxattr@ATTR_1.0");

 ssize_t libattr_flistxattr(int filedes, char *list, size_t size)
 {
        return syscall(__NR_flistxattr, filedes, list, size);
 }
+SYMVER(libattr_flistxattr, "flistxattr@ATTR_1.0");

 int libattr_removexattr(const char *path, const char *name)
 {
        return syscall(__NR_removexattr, path, name);
 }
+SYMVER(libattr_removexattr, "removexattr@ATTR_1.0");

 int libattr_lremovexattr(const char *path, const char *name)
 {
        return syscall(__NR_lremovexattr, path, name);
 }
+SYMVER(libattr_lremovexattr, "lremovexattr@ATTR_1.0");

 int libattr_fremovexattr(int filedes, const char *name)
 {
        return syscall(__NR_fremovexattr, filedes, name);
 }
+SYMVER(libattr_fremovexattr, "fremovexattr@ATTR_1.0");

 #ifdef HAVE_VISIBILITY_ATTRIBUTE
 # pragma GCC visibility pop
--
2.35.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]