--- glibc-2.21/elf/dl-deps.c.dsodeps~ 2015-02-06 07:40:18.000000000 +0100 +++ glibc-2.21/elf/dl-deps.c 2015-02-07 14:32:43.667285775 +0100 @@ -152,6 +152,56 @@ preload (struct list *known, unsigned in map->l_reserved = 1; } +static int compare (struct link_map *a, struct link_map *b) +{ + struct link_map **r, **s; + /* Check if must swap */ + if ((r = b->l_initfini)) + { + while (*r) + if (*r++ == a) + return 1; + } + /* Check if must *not* swap */ + if ((r = a->l_initfini)) + { + while (*r) + if (*r++ == b) + return -1; + } + /* No direct dependency information */ + return 0; +} + + +static void +sort (struct link_map **maps, size_t nmaps) +{ + unsigned int i, k; + struct link_map *t; + + /* We can skip looking for the binary itself which is at the front + of the search list for the main namespace. */ + for (i = 1; i < nmaps; ++i) + { + /* 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. */ + for (k = i + 1; k < nmaps; ++k) + { + if (compare(maps[i], maps[k]) > 0) + { + /* Move the current object to the back past the last + object with it as the dependency. */ + t = maps[i]; + maps[i] = maps[k]; + maps[k] = t; + } + } + } +} + + void internal_function _dl_map_object_deps (struct link_map *map, @@ -611,61 +661,7 @@ Filters not supported with LD_TRACE_PREL memcpy (l_initfini, map->l_searchlist.r_list, nlist * sizeof (struct link_map *)); if (__glibc_likely (nlist > 1)) - { - /* We can skip looking for the binary itself which is at the front - of the search list. */ - i = 1; - uint16_t seen[nlist]; - memset (seen, 0, nlist * sizeof (seen[0])); - while (1) - { - /* Keep track of which object we looked at this round. */ - ++seen[i]; - struct link_map *thisp = l_initfini[i]; - - /* 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 = nlist - 1; - while (k > i) - { - struct link_map **runp = l_initfini[k]->l_initfini; - if (runp != NULL) - /* Look through the dependencies of the object. */ - while (*runp != NULL) - if (__glibc_unlikely (*runp++ == thisp)) - { - /* Move the current object to the back past the last - object with it as the dependency. */ - memmove (&l_initfini[i], &l_initfini[i + 1], - (k - i) * sizeof (l_initfini[0])); - l_initfini[k] = thisp; - - if (seen[i + 1] > nlist - 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; - } - - --k; - } - - if (++i == nlist) - break; - next_clear: - memset (&seen[i], 0, (nlist - i) * sizeof (seen[0])); - - next:; - } - } + sort (l_initfini, nlist); /* Terminate the list of dependencies. */ l_initfini[nlist] = NULL; --- glibc-2.21/elf/dl-fini.c.dsodeps~ 2015-02-06 07:40:18.000000000 +0100 +++ glibc-2.21/elf/dl-fini.c 2015-02-07 14:31:26.369897612 +0100 @@ -26,101 +26,83 @@ typedef void (*fini_t) (void); +static int compare (struct link_map *a, struct link_map *b) +{ + struct link_map **r; + /* Check if must swap */ + if ((r = b->l_initfini)) + { + while (*r) + if (*r++ == a) + return 1; + } + /* Check if must *not* swap */ + if ((r = a->l_initfini)) + { + while (*r) + if (*r++ == b) + return -1; + } + if (b->l_reldeps && a->l_initfini) + { + unsigned int m = b->l_reldeps->act; + struct link_map **relmaps = &b->l_reldeps->list[0]; + + /* Look through the relocation dependencies of the object. */ + while (m--) + if (relmaps[m] == a) + { + /* If a cycle exists with a link time dependency, + preserve the latter. */ + for (r = a->l_initfini; *r; ++r) + if (*r == b) + return -1; + return 1; + } + } + /* No direct dependency information */ + return 0; +} + + void internal_function _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) + unsigned int i, k; + struct link_map *t; + + /* We can skip looking for the binary itself which is at the front + of the search list for the main namespace. */ + for (i = ns == LM_ID_BASE; i < nmaps; ++i) { - /* Keep track of which object we looked at this round. */ - ++seen[i]; - struct link_map *thisp = maps[i]; + t = 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; + if (t != t->l_real || t->l_idx == -1) + continue; /* 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)) + for (k = i + 1; k < nmaps; ++k) + { + if (compare(maps[i], maps[k]) > 0) { - 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; + /* Move the current object to the back past the last + object with it as the dependency. */ + t = maps[i]; + maps[i] = maps[k]; + maps[k] = t; + if (used) + { + char c = used[i]; + used[i] = used[k]; + used[k] = c; + } + } } - - skip: - if (++i == nmaps) - break; - next_clear: - memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0])); - - next:; } }