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