diff options
author | Andreas Schwab <schwab@suse.de> | 2017-11-07 15:24:19 +0100 |
---|---|---|
committer | Andreas Schwab <schwab@suse.de> | 2017-11-27 11:37:19 +0100 |
commit | c2c299fd24e87b83c63191ff979d41a86b37d714 (patch) | |
tree | 47b1dcdd9bd9348b5a15f93b376a8e7d275a324b /elf/dl-fini.c | |
parent | de61465c04d36dadce2f4e7f78ebbe50bae6a21e (diff) | |
download | glibc-c2c299fd24e87b83c63191ff979d41a86b37d714.zip glibc-c2c299fd24e87b83c63191ff979d41a86b37d714.tar.gz glibc-c2c299fd24e87b83c63191ff979d41a86b37d714.tar.bz2 |
Consolidate link map sorting
Combine the four places where link maps are sorted into a single function.
This also moves the logic to skip the first map (representing the main
binary) to the callers.
Diffstat (limited to 'elf/dl-fini.c')
-rw-r--r-- | elf/dl-fini.c | 105 |
1 files changed, 5 insertions, 100 deletions
diff --git a/elf/dl-fini.c b/elf/dl-fini.c index 71c06fc..8421c4f 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -26,104 +26,6 @@ typedef void (*fini_t) (void); void -_dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns) -{ - /* A list of one element need not be sorted. */ - if (nmaps == 1) - return; - - /* We can skip looking for the binary itself which is at the front - of the search list for the main namespace. */ - unsigned int i = ns == LM_ID_BASE; - uint16_t seen[nmaps]; - memset (seen, 0, nmaps * sizeof (seen[0])); - while (1) - { - /* Keep track of which object we looked at this round. */ - ++seen[i]; - struct link_map *thisp = maps[i]; - - /* Do not handle ld.so in secondary namespaces and object which - are not removed. */ - if (thisp != thisp->l_real || thisp->l_idx == -1) - goto skip; - - /* Find the last object in the list for which the current one is - a dependency and move the current object behind the object - with the dependency. */ - unsigned int k = nmaps - 1; - while (k > i) - { - struct link_map **runp = maps[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - move: - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&maps[i], &maps[i + 1], - (k - i) * sizeof (maps[0])); - maps[k] = thisp; - - if (used != NULL) - { - char here_used = used[i]; - memmove (&used[i], &used[i + 1], - (k - i) * sizeof (used[0])); - used[k] = here_used; - } - - if (seen[i + 1] > nmaps - i) - { - ++i; - goto next_clear; - } - - uint16_t this_seen = seen[i]; - memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0])); - seen[k] = this_seen; - - goto next; - } - - if (__glibc_unlikely (maps[k]->l_reldeps != NULL)) - { - unsigned int m = maps[k]->l_reldeps->act; - struct link_map **relmaps = &maps[k]->l_reldeps->list[0]; - - /* Look through the relocation dependencies of the object. */ - while (m-- > 0) - if (__glibc_unlikely (relmaps[m] == thisp)) - { - /* If a cycle exists with a link time dependency, - preserve the latter. */ - struct link_map **runp = thisp->l_initfini; - if (runp != NULL) - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == maps[k])) - goto ignore; - goto move; - } - ignore:; - } - - --k; - } - - skip: - if (++i == nmaps) - break; - next_clear: - memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); - - next:; - } -} - - -void _dl_fini (void) { /* Lots of fun ahead. We have to call the destructors for all still @@ -186,8 +88,11 @@ _dl_fini (void) assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1); unsigned int nmaps = i; - /* Now we have to do the sorting. */ - _dl_sort_fini (maps, nmaps, NULL, ns); + /* Now we have to do the sorting. We can skip looking for the + binary itself which is at the front of the search list for + the main namespace. */ + _dl_sort_maps (maps + (ns == LM_ID_BASE), nmaps - (ns == LM_ID_BASE), + NULL, true); /* We do not rely on the linked list of loaded object anymore from this point on. We have our own list here (maps). The |