Contents of /trunk/glibc/patches/glibc-2.15-ifunc.patch
Parent Directory | Revision Log
Revision 1806 -
(show annotations)
(download)
Tue Jun 12 12:33:27 2012 UTC (12 years, 3 months ago) by niro
File size: 7640 byte(s)
Tue Jun 12 12:33:27 2012 UTC (12 years, 3 months ago) by niro
File size: 7640 byte(s)
-added patches for 2.15-r1
1 | diff --git a/Makeconfig b/Makeconfig |
2 | index 2db2821..68547b2 100644 |
3 | --- a/Makeconfig |
4 | +++ b/Makeconfig |
5 | @@ -900,6 +900,12 @@ else |
6 | libdl = $(common-objpfx)dlfcn/libdl.a |
7 | endif |
8 | |
9 | +ifeq ($(build-shared),yes) |
10 | +libm = $(common-objpfx)math/libm.so$(libm.so-version) |
11 | +else |
12 | +libm = $(common-objpfx)math/libm.a |
13 | +endif |
14 | + |
15 | # These are the subdirectories containing the library source. The order |
16 | # is more or less arbitrary. The sorting step will take care of the |
17 | # dependencies. |
18 | diff --git a/elf/Makefile b/elf/Makefile |
19 | index 052e763..3f1772a 100644 |
20 | --- a/elf/Makefile |
21 | +++ b/elf/Makefile |
22 | @@ -124,7 +124,8 @@ distribute := rtld-Rules \ |
23 | tst-initordera1.c tst-initordera2.c tst-initorderb1.c \ |
24 | tst-initorderb2.c tst-initordera3.c tst-initordera4.c \ |
25 | tst-initorder.c \ |
26 | - tst-initorder2.c |
27 | + tst-initorder2.c \ |
28 | + tst-relsort1.c tst-relsort1mod1.c tst-relsort1mod2.c |
29 | |
30 | CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables |
31 | CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables |
32 | @@ -227,7 +228,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ |
33 | tst-audit1 tst-audit2 \ |
34 | tst-stackguard1 tst-addr1 tst-thrlock \ |
35 | tst-unique1 tst-unique2 tst-unique3 tst-unique4 \ |
36 | - tst-initorder tst-initorder2 |
37 | + tst-initorder tst-initorder2 tst-relsort1 |
38 | # reldep9 |
39 | test-srcs = tst-pathopt |
40 | selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null) |
41 | @@ -290,7 +291,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ |
42 | tst-initordera1 tst-initorderb1 \ |
43 | tst-initordera2 tst-initorderb2 \ |
44 | tst-initordera3 tst-initordera4 \ |
45 | - tst-initorder2a tst-initorder2b tst-initorder2c tst-initorder2d |
46 | + tst-initorder2a tst-initorder2b tst-initorder2c \ |
47 | + tst-initorder2d \ |
48 | + tst-relsort1mod1 tst-relsort1mod2 |
49 | ifeq (yes,$(have-initfini-array)) |
50 | modules-names += tst-array2dep tst-array5dep |
51 | endif |
52 | @@ -1195,3 +1198,9 @@ CFLAGS-tst-auditmod6b.c += $(AVX-CFLAGS) |
53 | CFLAGS-tst-auditmod6c.c += $(AVX-CFLAGS) |
54 | CFLAGS-tst-auditmod7b.c += $(AVX-CFLAGS) |
55 | endif |
56 | + |
57 | +$(objpfx)tst-relsort1: $(libdl) |
58 | +$(objpfx)tst-relsort1mod1.so: $(libm) $(objpfx)tst-relsort1mod2.so |
59 | +$(objpfx)tst-relsort1mod2.so: $(libm) |
60 | +$(objpfx)tst-relsort1.out: $(objpfx)tst-relsort1mod1.so \ |
61 | + $(objpfx)tst-relsort1mod2.so |
62 | diff --git a/elf/dl-open.c b/elf/dl-open.c |
63 | index a0b5c50..a56bdc1 100644 |
64 | --- a/elf/dl-open.c |
65 | +++ b/elf/dl-open.c |
66 | @@ -1,5 +1,5 @@ |
67 | /* Load a shared object at runtime, relocate it, and run its initializer. |
68 | - Copyright (C) 1996-2007, 2009, 2010, 2011 Free Software Foundation, Inc. |
69 | + Copyright (C) 1996-2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. |
70 | This file is part of the GNU C Library. |
71 | |
72 | The GNU C Library is free software; you can redistribute it and/or |
73 | @@ -302,45 +302,109 @@ dl_open_worker (void *a) |
74 | if (GLRO(dl_lazy)) |
75 | reloc_mode |= mode & RTLD_LAZY; |
76 | |
77 | - /* Relocate the objects loaded. We do this in reverse order so that copy |
78 | - relocs of earlier objects overwrite the data written by later objects. */ |
79 | - |
80 | + /* Sort the objects by dependency for the relocation process. This |
81 | + allows IFUNC relocations to work and it also means copy |
82 | + relocation of dependencies are if necessary overwritten. */ |
83 | + size_t nmaps = 0; |
84 | struct link_map *l = new; |
85 | - while (l->l_next) |
86 | - l = l->l_next; |
87 | - while (1) |
88 | + do |
89 | + { |
90 | + if (! l->l_real->l_relocated) |
91 | + ++nmaps; |
92 | + l = l->l_next; |
93 | + } |
94 | + while (l != NULL); |
95 | + struct link_map *maps[nmaps]; |
96 | + nmaps = 0; |
97 | + l = new; |
98 | + do |
99 | { |
100 | if (! l->l_real->l_relocated) |
101 | + maps[nmaps++] = l; |
102 | + l = l->l_next; |
103 | + } |
104 | + while (l != NULL); |
105 | + if (nmaps > 1) |
106 | + { |
107 | + char seen[nmaps]; |
108 | + memset (seen, '\0', nmaps); |
109 | + size_t i = 0; |
110 | + while (1) |
111 | { |
112 | -#ifdef SHARED |
113 | - if (__builtin_expect (GLRO(dl_profile) != NULL, 0)) |
114 | + ++seen[i]; |
115 | + struct link_map *thisp = maps[i]; |
116 | + |
117 | + /* Find the last object in the list for which the current one is |
118 | + a dependency and move the current object behind the object |
119 | + with the dependency. */ |
120 | + size_t k = nmaps - 1; |
121 | + while (k > i) |
122 | { |
123 | - /* If this here is the shared object which we want to profile |
124 | - make sure the profile is started. We can find out whether |
125 | - this is necessary or not by observing the `_dl_profile_map' |
126 | - variable. If was NULL but is not NULL afterwars we must |
127 | - start the profiling. */ |
128 | - struct link_map *old_profile_map = GL(dl_profile_map); |
129 | + struct link_map **runp = maps[k]->l_initfini; |
130 | + if (runp != NULL) |
131 | + /* Look through the dependencies of the object. */ |
132 | + while (*runp != NULL) |
133 | + if (__builtin_expect (*runp++ == thisp, 0)) |
134 | + { |
135 | + /* Move the current object to the back past the last |
136 | + object with it as the dependency. */ |
137 | + memmove (&maps[i], &maps[i + 1], |
138 | + (k - i) * sizeof (maps[0])); |
139 | + maps[k] = thisp; |
140 | + |
141 | + if (seen[i + 1] > 1) |
142 | + { |
143 | + ++i; |
144 | + goto next_clear; |
145 | + } |
146 | + |
147 | + char this_seen = seen[i]; |
148 | + memmove (&seen[i], &seen[i + 1], |
149 | + (k - i) * sizeof (seen[0])); |
150 | + seen[k] = this_seen; |
151 | + |
152 | + goto next; |
153 | + } |
154 | + |
155 | + --k; |
156 | + } |
157 | |
158 | - _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1); |
159 | + if (++i == nmaps) |
160 | + break; |
161 | + next_clear: |
162 | + memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); |
163 | + next:; |
164 | + } |
165 | + } |
166 | |
167 | - if (old_profile_map == NULL && GL(dl_profile_map) != NULL) |
168 | - { |
169 | - /* We must prepare the profiling. */ |
170 | - _dl_start_profile (); |
171 | + for (size_t i = nmaps; i-- > 0; ) |
172 | + { |
173 | + l = maps[i]; |
174 | |
175 | - /* Prevent unloading the object. */ |
176 | - GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE; |
177 | - } |
178 | +#ifdef SHARED |
179 | + if (__builtin_expect (GLRO(dl_profile) != NULL, 0)) |
180 | + { |
181 | + /* If this here is the shared object which we want to profile |
182 | + make sure the profile is started. We can find out whether |
183 | + this is necessary or not by observing the `_dl_profile_map' |
184 | + variable. If it was NULL but is not NULL afterwars we must |
185 | + start the profiling. */ |
186 | + struct link_map *old_profile_map = GL(dl_profile_map); |
187 | + |
188 | + _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1); |
189 | + |
190 | + if (old_profile_map == NULL && GL(dl_profile_map) != NULL) |
191 | + { |
192 | + /* We must prepare the profiling. */ |
193 | + _dl_start_profile (); |
194 | + |
195 | + /* Prevent unloading the object. */ |
196 | + GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE; |
197 | } |
198 | - else |
199 | -#endif |
200 | - _dl_relocate_object (l, l->l_scope, reloc_mode, 0); |
201 | } |
202 | - |
203 | - if (l == new) |
204 | - break; |
205 | - l = l->l_prev; |
206 | + else |
207 | +#endif |
208 | + _dl_relocate_object (l, l->l_scope, reloc_mode, 0); |
209 | } |
210 | |
211 | /* If the file is not loaded now as a dependency, add the search |
212 | diff --git a/elf/tst-relsort1.c b/elf/tst-relsort1.c |
213 | new file mode 100644 |
214 | index 0000000..972100c |
215 | --- /dev/null |
216 | +++ b/elf/tst-relsort1.c |
217 | @@ -0,0 +1,19 @@ |
218 | +#include <dlfcn.h> |
219 | +#include <stdio.h> |
220 | + |
221 | + |
222 | +static int |
223 | +do_test () |
224 | +{ |
225 | + const char lib[] = "$ORIGIN/tst-relsort1mod1.so"; |
226 | + void *h = dlopen (lib, RTLD_NOW); |
227 | + if (h == NULL) |
228 | + { |
229 | + puts (dlerror ()); |
230 | + return 1; |
231 | + } |
232 | + return 0; |
233 | +} |
234 | + |
235 | +#define TEST_FUNCTION do_test () |
236 | +#include "../test-skeleton.c" |
237 | diff --git a/elf/tst-relsort1mod1.c b/elf/tst-relsort1mod1.c |
238 | new file mode 100644 |
239 | index 0000000..9e4a943 |
240 | --- /dev/null |
241 | +++ b/elf/tst-relsort1mod1.c |
242 | @@ -0,0 +1,7 @@ |
243 | +extern int foo (double); |
244 | + |
245 | +int |
246 | +bar (void) |
247 | +{ |
248 | + return foo (1.2); |
249 | +} |
250 | diff --git a/elf/tst-relsort1mod2.c b/elf/tst-relsort1mod2.c |
251 | new file mode 100644 |
252 | index 0000000..a2c3e55 |
253 | --- /dev/null |
254 | +++ b/elf/tst-relsort1mod2.c |
255 | @@ -0,0 +1,7 @@ |
256 | +#include <math.h> |
257 | + |
258 | +int |
259 | +foo (double d) |
260 | +{ |
261 | + return floor (d) != 0.0; |
262 | +} |