summaryrefslogtreecommitdiff
path: root/sys-apps/attr/files/attr-2.5.1-r2-fix-symver.patch
blob: ee25b13166ff0215da3cc4d5239097b27de5433b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
https://lists.nongnu.org/archive/html/acl-devel/2022-05/msg00000.html
Bug: https://bugs.gentoo.org/644048
Bug: https://bugs.gentoo.org/700116

From a9ca51afd2b9f68f57de3a4c3d962d1d763572ca Mon Sep 17 00:00:00 2001
From: Alexander Miller <alex.miller@gmx.de>
Date: Thu, 28 Nov 2019 22:17:24 +0100
Subject: [PATCH] Better supported way to set symbol versions for legacy
 syscalls

Using a linker script to set a 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.

The result may be a library where the code has been discarded and
the versioned symbols are unusable, e.g.
    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
symver attribute if available (in gcc >= 10, but not in clang),
otherwise use the traditional global asm solution with a .symver
directive.
Those are the documented ways to do it and well supported by (almost)
all configurations. (The exception is old gcc with LTO; a workaround
is included, but some versions may still need -flto-partition=none).

Signed-off-by: Alexander Miller <alex.miller@gmx.de>

--- 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

--- a/Makefile.in
+++ b/Makefile.in
@@ -647,9 +647,8 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 ACLOCAL_AMFLAGS = -I m4
-EXTRA_DIST = exports examples/copyattr.c examples/Makefile \
-	libattr/libattr.lds test/README test/run \
-	test/sort-getfattr-output $(TESTS)
+EXTRA_DIST = exports examples/copyattr.c examples/Makefile test/README \
+	test/run test/sort-getfattr-output $(TESTS)
 SUBDIRS = po
 AM_CPPFLAGS = \
 	-I$(top_builddir)/include \
@@ -689,7 +688,7 @@ LT_CURRENT = 2
 #LT_REVISION =
 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 \
@@ -702,7 +701,6 @@ 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)
 
 libmisc_la_SOURCES = \
--- 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;
--- 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