summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/fix-pr16476.patch
blob: 65d62bcde4422d1ffeb1ee045ff5973d3f58dfd8 (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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
From: H.J. Lu <hjl.tools@gmail.com>
Date: Tue, 21 Jan 2014 23:42:43 +0000 (-0800)
Subject: Check incompatible existing default symbol definition
X-Git-Tag: hjl/linux/release/2.24.51.0.3~1^2~8^2~16
X-Git-Url: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff_plain;h=4584ec12076e088cf36965b88ef8710ca85491f9

Check incompatible existing default symbol definition

After resolving a versioned reference, foo@VER1, to a default versioned
definition, foo@@VER1, from a shared object, we also merge it with
the existing regular default symbol definition, foo.  When foo is IFUNC
and foo@@VER1 aren't, we will merge 2 incompatible definitions.  This
patch avoids merging foo@@VER1 definition with foo definition if
one is IFUNC and the other isn't.

Upstream-Status: Backport
---

#diff --git a/bfd/ChangeLog b/bfd/ChangeLog
#index 5923bc3..c70a7db 100644
#--- a/bfd/ChangeLog
#+++ b/bfd/ChangeLog
#@@ -1,5 +1,13 @@
# 2014-01-21  H.J. Lu  <hongjiu.lu@intel.com>
# 
#+	PR ld/16467
#+	* elflink.c (_bfd_elf_merge_symbol): When types of the existing
#+	regular default symbol definition and the versioned dynamic
#+	symbol definition mismatch, skip the default symbol definition
#+	if one of them is IFUNC.
#+
#+2014-01-21  H.J. Lu  <hongjiu.lu@intel.com>
#+
# 	PR ld/2404
# 	* elflink.c (_bfd_elf_merge_symbol): Don't check info->shared,
# 	info->export_dynamic nor h->ref_dynamic for type mismatch when
diff --git a/bfd/elflink.c b/bfd/elflink.c
index d0006da..792e14e 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -1092,11 +1092,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && newdyn
       && newdef
       && !olddyn
-      && (olddef || h->root.type == bfd_link_hash_common)
-      && ELF_ST_TYPE (sym->st_info) != h->type
-      && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
-      && h->type != STT_NOTYPE
-      && !(newfunc && oldfunc))
+      && (((olddef || h->root.type == bfd_link_hash_common)
+	   && ELF_ST_TYPE (sym->st_info) != h->type
+	   && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+	   && h->type != STT_NOTYPE
+	   && !(newfunc && oldfunc))
+	  || (olddef
+	      && ((h->type == STT_GNU_IFUNC)
+		  != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))))
     {
       *skip = TRUE;
       return TRUE;
#diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
#index ac65a3a..a092428 100644
#--- a/ld/testsuite/ChangeLog
#+++ b/ld/testsuite/ChangeLog
#@@ -1,5 +1,19 @@
# 2014-01-21  H.J. Lu  <hongjiu.lu@intel.com>
# 
#+	PR ld/16467
#+	* ld-ifunc/dummy.c: New file.
#+	* ld-ifunc/pr16467.out: Likewise.
##+	* ld-ifunc/pr16467a.c: Likewise.
#+	* ld-ifunc/pr16467a.map: Likewise.
#+	* ld-ifunc/pr16467b.c: Likewise.
#+	* ld-ifunc/pr16467b.map: Likewise.
#+	* ld-ifunc/pr16467c.c: Likewise.
#+
#+	* ld-ifunc/ifunc.exp (run_cc_link_tests): New.
#+	(run_ld_link_exec_tests): Run pr16467.
#+
#+2014-01-21  H.J. Lu  <hongjiu.lu@intel.com>
#+
# 	PR ld/2404
# 	* ld-elf/shared.exp: Add a PIE test for PR ld/2404.
# 
diff --git a/ld/testsuite/ld-ifunc/dummy.c b/ld/testsuite/ld-ifunc/dummy.c
new file mode 100644
index 0000000..5c03287
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/dummy.c
@@ -0,0 +1 @@
+/* An empty file.  */
diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp
index fb106c6..d7ff445 100644
--- a/ld/testsuite/ld-ifunc/ifunc.exp
+++ b/ld/testsuite/ld-ifunc/ifunc.exp
@@ -349,6 +349,42 @@ if { $verbose < 1 } {
     remote_file host delete "tmpdir/static_nonifunc_prog"
 }
 
+run_cc_link_tests [list \
+    [list \
+	"Build libpr16467a.so" \
+	"-shared -Wl,--version-script=pr16467a.map" \
+	"-fPIC" \
+	{ pr16467a.c } \
+	{} \
+	"libpr16467a.so" \
+    ] \
+    [list \
+	"Build libpr16467b.a" \
+	"" \
+	"-fPIC" \
+	{ pr16467b.c } \
+	{} \
+	"libpr16467b.a" \
+    ] \
+    [list \
+	"Build libpr16467b.so" \
+	"-shared tmpdir/pr16467b.o tmpdir/libpr16467a.so \
+	 -Wl,--version-script=pr16467b.map" \
+	"-fPIC" \
+	{ dummy.c } \
+	{} \
+	"libpr16467b.so" \
+    ] \
+    [list \
+	"Build libpr16467c.a" \
+	"" \
+	"" \
+	{ pr16467c.c } \
+	{} \
+	"libpr16467c.a" \
+    ] \
+]
+
 run_ld_link_exec_tests [] [list \
     [list \
 	"Common symbol override ifunc test 1a" \
@@ -368,6 +404,15 @@ run_ld_link_exec_tests [] [list \
 	"ifunc-common-1.out" \
 	"-g" \
     ] \
+    [list \
+	"Run pr16467" \
+	"tmpdir/pr16467c.o tmpdir/libpr16467b.so tmpdir/libpr16467a.so" \
+	"" \
+	{ dummy.c } \
+	"pr16467" \
+	"pr16467.out" \
+	"" \
+    ] \
 ]
 
 set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
diff --git a/ld/testsuite/ld-ifunc/pr16467.out b/ld/testsuite/ld-ifunc/pr16467.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/pr16467.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-ifunc/pr16467a.c b/ld/testsuite/ld-ifunc/pr16467a.c
new file mode 100644
index 0000000..ae3f084
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/pr16467a.c
@@ -0,0 +1,5 @@
+const char * 
+sd_get_seats(void)
+{
+  return "OK";
+}
diff --git a/ld/testsuite/ld-ifunc/pr16467a.map b/ld/testsuite/ld-ifunc/pr16467a.map
new file mode 100644
index 0000000..d677f37
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/pr16467a.map
@@ -0,0 +1,4 @@
+LIBSYSTEMD_209 {
+global:
+        sd_get_seats;
+};
diff --git a/ld/testsuite/ld-ifunc/pr16467b.c b/ld/testsuite/ld-ifunc/pr16467b.c
new file mode 100644
index 0000000..264f6cf
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/pr16467b.c
@@ -0,0 +1,7 @@
+void new_sd_get_seats(void);
+__asm__(".symver new_sd_get_seats,sd_get_seats@LIBSYSTEMD_209");
+void (*resolve_sd_get_seats(void)) (void) __asm__ ("sd_get_seats");
+void (*resolve_sd_get_seats(void)) (void) {
+        return new_sd_get_seats;
+}
+__asm__(".type sd_get_seats, %gnu_indirect_function");
diff --git a/ld/testsuite/ld-ifunc/pr16467b.map b/ld/testsuite/ld-ifunc/pr16467b.map
new file mode 100644
index 0000000..1f263de
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/pr16467b.map
@@ -0,0 +1,4 @@
+LIBSYSTEMD_208 {
+global:
+        sd_get_seats;
+};
diff --git a/ld/testsuite/ld-ifunc/pr16467c.c b/ld/testsuite/ld-ifunc/pr16467c.c
new file mode 100644
index 0000000..e2a901c
--- /dev/null
+++ b/ld/testsuite/ld-ifunc/pr16467c.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+const char* sd_get_seats(void);
+
+int
+main (int argc, char **argv)
+{
+  printf("%s\n", sd_get_seats());
+  return 0;
+}