1
2012-01-27 Ulrich Drepper <drepper@gmail.com>
4
* elf/dl-open.c (dl_open_worker): Sort objects by dependency before
7
diff --git a/elf/dl-open.c b/elf/dl-open.c
8
index a0b5c50..a56bdc1 100644
11
@@ -302,45 +302,109 @@ dl_open_worker (void *a)
13
reloc_mode |= mode & RTLD_LAZY;
15
- /* Relocate the objects loaded. We do this in reverse order so that copy
16
- relocs of earlier objects overwrite the data written by later objects. */
18
+ /* Sort the objects by dependency for the relocation process. This
19
+ allows IFUNC relocations to work and it also means copy
20
+ relocation of dependencies are if necessary overwritten. */
22
struct link_map *l = new;
28
+ if (! l->l_real->l_relocated)
33
+ struct link_map *maps[nmaps];
38
if (! l->l_real->l_relocated)
46
+ memset (seen, '\0', nmaps);
51
- if (__builtin_expect (GLRO(dl_profile) != NULL, 0))
53
+ struct link_map *thisp = maps[i];
55
+ /* Find the last object in the list for which the current one is
56
+ a dependency and move the current object behind the object
57
+ with the dependency. */
58
+ size_t k = nmaps - 1;
61
- /* If this here is the shared object which we want to profile
62
- make sure the profile is started. We can find out whether
63
- this is necessary or not by observing the `_dl_profile_map'
64
- variable. If was NULL but is not NULL afterwars we must
65
- start the profiling. */
66
- struct link_map *old_profile_map = GL(dl_profile_map);
67
+ struct link_map **runp = maps[k]->l_initfini;
69
+ /* Look through the dependencies of the object. */
70
+ while (*runp != NULL)
71
+ if (__builtin_expect (*runp++ == thisp, 0))
73
+ /* Move the current object to the back past the last
74
+ object with it as the dependency. */
75
+ memmove (&maps[i], &maps[i + 1],
76
+ (k - i) * sizeof (maps[0]));
79
+ if (seen[i + 1] > 1)
85
+ char this_seen = seen[i];
86
+ memmove (&seen[i], &seen[i + 1],
87
+ (k - i) * sizeof (seen[0]));
88
+ seen[k] = this_seen;
96
- _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
100
+ memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0]));
105
- if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
107
- /* We must prepare the profiling. */
108
- _dl_start_profile ();
109
+ for (size_t i = nmaps; i-- > 0; )
113
- /* Prevent unloading the object. */
114
- GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;
117
+ if (__builtin_expect (GLRO(dl_profile) != NULL, 0))
119
+ /* If this here is the shared object which we want to profile
120
+ make sure the profile is started. We can find out whether
121
+ this is necessary or not by observing the `_dl_profile_map'
122
+ variable. If it was NULL but is not NULL afterwars we must
123
+ start the profiling. */
124
+ struct link_map *old_profile_map = GL(dl_profile_map);
126
+ _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
128
+ if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
130
+ /* We must prepare the profiling. */
131
+ _dl_start_profile ();
133
+ /* Prevent unloading the object. */
134
+ GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;
138
- _dl_relocate_object (l, l->l_scope, reloc_mode, 0);
146
+ _dl_relocate_object (l, l->l_scope, reloc_mode, 0);
149
/* If the file is not loaded now as a dependency, add the search