mirror of
https://abf.rosa.ru/djam/glibc40.git
synced 2025-02-23 07:42:54 +00:00
Restore fixed dso_deps patch (as it greatly improves performance of dynamic loader for deeply nested DSO dependencies)
This commit is contained in:
parent
f48bbb687f
commit
095256e47b
2 changed files with 304 additions and 131 deletions
|
@ -1,63 +1,118 @@
|
|||
--- 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;
|
||||
}
|
||||
@@ -, +, @@
|
||||
17645)
|
||||
---
|
||||
elf/Makefile | 1 +
|
||||
elf/dl-deps.c | 143 +++++++++++++++++++++++++++++------------------
|
||||
elf/dl-fini.c | 176 +++++++++++++++++++++++++++++++---------------------------
|
||||
elf/dl-open.c | 74 ++++++++++++++++++++++++
|
||||
4 files changed, 256 insertions(+), 138 deletions(-)
|
||||
--- a/elf/Makefile
|
||||
+++ a/elf/Makefile
|
||||
@@ -513,6 +513,7 @@ $(objpfx)unload8mod1.so: $(objpfx)unload8mod2.so
|
||||
$(objpfx)unload8mod2.so: $(objpfx)unload8mod3.so
|
||||
$(objpfx)unload8mod3.so: $(libdl)
|
||||
$(objpfx)tst-initordera2.so: $(objpfx)tst-initordera1.so
|
||||
+$(objpfx)tst-initorderb1.so: $(objpfx)tst-initordera2.so
|
||||
$(objpfx)tst-initorderb2.so: $(objpfx)tst-initorderb1.so $(objpfx)tst-initordera2.so
|
||||
$(objpfx)tst-initordera3.so: $(objpfx)tst-initorderb2.so $(objpfx)tst-initorderb1.so
|
||||
$(objpfx)tst-initordera4.so: $(objpfx)tst-initordera3.so
|
||||
--- a/elf/dl-deps.c
|
||||
+++ a/elf/dl-deps.c
|
||||
@@ -139,6 +139,93 @@ cannot load auxiliary `%s' because of empty dynamic string token " \
|
||||
__result; })
|
||||
|
||||
+static int compare (struct link_map *a, struct link_map *b)
|
||||
static void
|
||||
+weight (struct link_map **maps, size_t nmaps, char *seen, unsigned int *w)
|
||||
+{
|
||||
+ struct link_map **r, **s;
|
||||
+ /* Check if must swap */
|
||||
+ if ((r = b->l_initfini))
|
||||
+ int i, c;
|
||||
+ struct link_map *m, **r;
|
||||
+
|
||||
+ /* Start at 1 because the first entry is the binary itself. */
|
||||
+ for (i = 1; i < nmaps; ++i)
|
||||
+ {
|
||||
+ m = maps[i];
|
||||
+ if ((r = m->l_initfini))
|
||||
+ {
|
||||
+ c = 0;
|
||||
+ 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;
|
||||
+
|
||||
+ /* If not a self reference, not being unloaded, and not
|
||||
+ already removed from the list, increment the reference
|
||||
+ counter. */
|
||||
+ if (*r != m && (*r)->l_idx >= 0 && !seen[(*r)->l_idx])
|
||||
+ ++c;
|
||||
+ ++r;
|
||||
+ }
|
||||
+
|
||||
+ /* Update the {w}eight vector with {c}ount map(s) dependency */
|
||||
+ w[i] = c;
|
||||
+ }
|
||||
+ else
|
||||
+ w[i] = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sort (struct link_map **maps, size_t nmaps)
|
||||
+{
|
||||
+ unsigned int i, k;
|
||||
+ int c, i, k;
|
||||
+ unsigned int w[nmaps];
|
||||
+ char seen[nmaps];
|
||||
+ struct link_map *t;
|
||||
+ memset(seen, 0, nmaps);
|
||||
+
|
||||
+ /* Use the l_idx field as an unique identifier. */
|
||||
+ for (i = 0; i < nmaps; ++i)
|
||||
+ {
|
||||
+ /* Ensure to not touch a link_map with l_idx < 0 as it is
|
||||
+ used to flag a dso is being unloaded. */
|
||||
+ if (maps[i]->l_idx >= 0)
|
||||
+ maps[i]->l_idx = i;
|
||||
+ }
|
||||
+
|
||||
+ /* 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)
|
||||
+ of the search list. */
|
||||
+ w[0] = 0;
|
||||
+ seen[0] = 1;
|
||||
+
|
||||
+ /* The list is sorted in place, with entries added from end to start. */
|
||||
+ weight(maps, k = nmaps, seen, w);
|
||||
+ c = 0;
|
||||
+ while (c < k)
|
||||
+ {
|
||||
+ /* 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)
|
||||
+ for (i = k - 1; i >= 1; --i)
|
||||
+ {
|
||||
+ if (compare(maps[i], maps[k]) > 0)
|
||||
+ if (w[i] == c && maps[i]->l_idx >= 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;
|
||||
+ }
|
||||
+ seen[maps[i]->l_idx] = 1;
|
||||
+
|
||||
+ /* Reducing the number of entries or swaping entries
|
||||
+ require remaking the {w}eight map. */
|
||||
+ if (--k != i)
|
||||
+ {
|
||||
+ t = maps[k];
|
||||
+ maps[k] = maps[i];
|
||||
+ maps[i] = t;
|
||||
+ }
|
||||
+ weight(maps, k, seen, w);
|
||||
+ c = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If c != 0, there are cycles, and the first entry in the map,
|
||||
+ with the lowest reference {c}ount is removed attempting to
|
||||
+ to break the cycle. */
|
||||
+ ++c;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void
|
||||
internal_function
|
||||
_dl_map_object_deps (struct link_map *map,
|
||||
@@ -611,61 +661,7 @@ Filters not supported with LD_TRACE_PREL
|
||||
+static void
|
||||
preload (struct list *known, unsigned int *nlist, struct link_map *map)
|
||||
{
|
||||
known[*nlist].done = 0;
|
||||
@@ -611,61 +698,7 @@ Filters not supported with LD_TRACE_PRELINKING"));
|
||||
memcpy (l_initfini, map->l_searchlist.r_list,
|
||||
nlist * sizeof (struct link_map *));
|
||||
if (__glibc_likely (nlist > 1))
|
||||
|
@ -120,87 +175,88 @@
|
|||
|
||||
/* 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 @@
|
||||
--- a/elf/dl-fini.c
|
||||
+++ a/elf/dl-fini.c
|
||||
@@ -26,102 +26,112 @@
|
||||
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)
|
||||
-void
|
||||
-internal_function
|
||||
-_dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
|
||||
+static void
|
||||
+weight (struct link_map **maps, size_t nmaps, char *seen, unsigned int *w, int from)
|
||||
{
|
||||
- /* 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. */
|
||||
+ int i, c;
|
||||
+ struct link_map *m, **r;
|
||||
+ for (i = from; i < nmaps; ++i)
|
||||
+ {
|
||||
+ m = maps[i];
|
||||
+ if ((r = m->l_initfini))
|
||||
+ {
|
||||
+ c = 0;
|
||||
+ while (*r)
|
||||
+ {
|
||||
+ /* If not a self reference, not being unloaded, and not
|
||||
+ already removed from the list, increment the reference
|
||||
+ counter. */
|
||||
+ if (*r != m && (*r)->l_idx >= 0 && !seen[(*r)->l_idx])
|
||||
+ ++c;
|
||||
+ ++r;
|
||||
+ }
|
||||
+ /* Update the {w}eight vector with {c}ount map(s) dependency */
|
||||
+ w[i] = c;
|
||||
+ }
|
||||
+ else
|
||||
+ w[i] = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void
|
||||
+sort (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
|
||||
+{
|
||||
+ int from;
|
||||
+ int c, i, k;
|
||||
+ unsigned int w[nmaps];
|
||||
+ char seen[nmaps];
|
||||
+ struct link_map *t;
|
||||
+
|
||||
+ memset(seen, 0, nmaps);
|
||||
+
|
||||
+ /* Use the l_idx field as an unique identifier. */
|
||||
+ for (i = 0; i < nmaps; ++i)
|
||||
+ {
|
||||
+ /* Ensure to not touch a link_map with l_idx < 0 as it is
|
||||
+ used to flag a dso is being unloaded. */
|
||||
+ if (maps[i]->l_idx >= 0)
|
||||
+ maps[i]->l_idx = i;
|
||||
+ }
|
||||
|
||||
/* 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)
|
||||
+ from = ns == LM_ID_BASE;
|
||||
+ if (from)
|
||||
{
|
||||
- /* 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. */
|
||||
-
|
||||
- /* 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. */
|
||||
-
|
||||
- /* 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)
|
||||
- {
|
||||
|
@ -224,25 +280,48 @@
|
|||
- (k - i) * sizeof (used[0]));
|
||||
- used[k] = here_used;
|
||||
- }
|
||||
-
|
||||
+ w[0] = 0;
|
||||
+ seen[0] = 1;
|
||||
+ }
|
||||
|
||||
- if (seen[i + 1] > nmaps - i)
|
||||
- {
|
||||
+ /* The list is sorted in place, with entries added from end to start. */
|
||||
+ weight(maps, k = nmaps, seen, w, from);
|
||||
+ c = 0;
|
||||
+ while (c < k)
|
||||
+ {
|
||||
+ for (i = k - 1; i >= from; --i)
|
||||
+ {
|
||||
+ t = maps[i];
|
||||
+ /* Do not handle ld.so in secondary namespaces and object which
|
||||
+ are not removed. */
|
||||
+ if (w[i] == c && maps[i]->l_idx >= 0 && t->l_real == t)
|
||||
+ {
|
||||
+ seen[maps[i]->l_idx] = 1;
|
||||
+ /* Reducing the number of entries or swaping entries
|
||||
+ require remaking the {w}eight map. */
|
||||
+ if (--k != i)
|
||||
+ {
|
||||
+ maps[i] = maps[k];
|
||||
+ maps[k] = t;
|
||||
+ if (used)
|
||||
{
|
||||
- ++i;
|
||||
- goto next_clear;
|
||||
- }
|
||||
+ char c = used[i];
|
||||
+ used[i] = used[k];
|
||||
+ used[k] = c;
|
||||
}
|
||||
-
|
||||
- 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];
|
||||
-
|
||||
|
@ -260,30 +339,121 @@
|
|||
- 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;
|
||||
+ }
|
||||
+ }
|
||||
+ weight(maps, k, seen, w, from);
|
||||
+ c = -1;
|
||||
+ break;
|
||||
}
|
||||
-
|
||||
- --k;
|
||||
}
|
||||
+ /* If c != 0, there are cycles, and the first entry in the map,
|
||||
+ with the lowest reference {c}ount is removed attempting to
|
||||
+ to break the cycle. */
|
||||
+ ++c;
|
||||
+ }
|
||||
+}
|
||||
|
||||
- skip:
|
||||
- if (++i == nmaps)
|
||||
- break;
|
||||
- next_clear:
|
||||
- memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0]));
|
||||
-
|
||||
|
||||
- next:;
|
||||
}
|
||||
- }
|
||||
+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;
|
||||
+
|
||||
+ sort (maps, nmaps, used, ns);
|
||||
}
|
||||
|
||||
|
||||
--- a/elf/dl-open.c
|
||||
+++ a/elf/dl-open.c
|
||||
@@ -182,6 +182,80 @@ _dl_find_dso_for_object (const ElfW(Addr) addr)
|
||||
rtld_hidden_def (_dl_find_dso_for_object);
|
||||
|
||||
static void
|
||||
+weight (struct link_map **maps, size_t nmaps, char *seen, unsigned int *w)
|
||||
+{
|
||||
+ int i, c;
|
||||
+ struct link_map *m, **r;
|
||||
+ for (i = 0; i < nmaps; ++i)
|
||||
+ {
|
||||
+ m = maps[i];
|
||||
+ if ((r = m->l_initfini))
|
||||
+ {
|
||||
+ c = 0;
|
||||
+ while (*r)
|
||||
+ {
|
||||
+ /* If not a self reference, not being unloaded, and not
|
||||
+ already removed from the list, increment the reference
|
||||
+ counter. */
|
||||
+ if (*r != m && (*r)->l_idx >= 0 && !seen[(*r)->l_idx])
|
||||
+ ++c;
|
||||
+ ++r;
|
||||
+ }
|
||||
+ /* Update the {w}eight vector with {c}ount map(s) dependency */
|
||||
+ w[i] = c;
|
||||
+ }
|
||||
+ else
|
||||
+ w[i] = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sort (struct link_map **maps, size_t nmaps)
|
||||
+{
|
||||
+ int c, i, k;
|
||||
+ unsigned int w[nmaps];
|
||||
+ char seen[nmaps];
|
||||
+ struct link_map *t;
|
||||
+ memset(seen, 0, nmaps);
|
||||
+ /* Use the l_idx field as an unique identifier. */
|
||||
+ for (i = 0; i < nmaps; ++i)
|
||||
+ {
|
||||
+ /* Ensure to not touch a link_map with l_idx < 0 as it is
|
||||
+ used to flag a dso is being unloaded. */
|
||||
+ if (maps[i]->l_idx >= 0)
|
||||
+ maps[i]->l_idx = i;
|
||||
+ }
|
||||
+ /* The list is sorted in place, with entries added from end to start. */
|
||||
+ weight(maps, k = nmaps, seen, w);
|
||||
+ c = 0;
|
||||
+ while (c < k)
|
||||
+ {
|
||||
+ for (i = k - 1; i >= 0; --i)
|
||||
+ {
|
||||
+ if (w[i] == c && maps[i]->l_idx >= 0)
|
||||
+ {
|
||||
+ seen[maps[i]->l_idx] = 1;
|
||||
+ /* Reducing the number of entries or swaping entries
|
||||
+ require remaking the {w}eight map. */
|
||||
+ if (--k != i)
|
||||
+ {
|
||||
+ t = maps[k];
|
||||
+ maps[k] = maps[i];
|
||||
+ maps[i] = t;
|
||||
+ }
|
||||
+ weight(maps, k, seen, w);
|
||||
+ c = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ /* If c != 0, there are cycles, and the first entry in the map,
|
||||
+ with the lowest reference {c}ount is removed attempting to
|
||||
+ to break the cycle. */
|
||||
+ ++c;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
dl_open_worker (void *a)
|
||||
{
|
||||
struct dl_open_args *args = a;
|
||||
--
|
||||
|
|
|
@ -57,7 +57,7 @@ Summary: The GNU libc libraries
|
|||
Name: glibc
|
||||
Epoch: 6
|
||||
Version: 2.24
|
||||
Release: 7
|
||||
Release: 8
|
||||
License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+
|
||||
Group: System/Libraries
|
||||
Url: http://www.eglibc.org/
|
||||
|
@ -130,6 +130,8 @@ Patch27: glibc-2.22-blacklist-CPUs-from-lock-elision.patch
|
|||
Patch28: glibc-bug-regex-gcc5.patch
|
||||
Patch29: glibc-c-utf8-locale.patch
|
||||
Patch30: glibc-dns-host-gcc5.patch
|
||||
# https://sourceware.org/bugzilla/show_bug.cgi?id=17645
|
||||
Patch31: glibc-dso_deps.patch
|
||||
Patch32: glibc-gcc-PR69537.patch
|
||||
Patch33: glibc-gethnamaddr-gcc5.patch
|
||||
Patch34: glibc-ld-ctype-gcc5.patch
|
||||
|
@ -823,6 +825,7 @@ their ~/.profile configuration file.
|
|||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
%patch34 -p1
|
||||
|
|
Loading…
Add table
Reference in a new issue