diff options
Diffstat (limited to 'elf/dl-deps.c')
-rw-r--r-- | elf/dl-deps.c | 134 |
1 files changed, 30 insertions, 104 deletions
diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 6a82987799..9d9b1ba7f2 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -1,5 +1,5 @@ /* Load the dependencies of a mapped object. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -27,6 +27,7 @@ #include <unistd.h> #include <sys/param.h> #include <ldsodefs.h> +#include <scratch_buffer.h> #include <dl-dst.h> @@ -68,7 +69,6 @@ openaux (void *a) } static ptrdiff_t -internal_function _dl_build_local_scope (struct link_map **list, struct link_map *map) { struct link_map **p = list; @@ -101,7 +101,7 @@ struct list ({ \ const char *__str = (str); \ const char *__result = __str; \ - size_t __dst_cnt = DL_DST_COUNT (__str, 0); \ + size_t __dst_cnt = _dl_dst_count (__str); \ \ if (__dst_cnt != 0) \ { \ @@ -115,7 +115,7 @@ DST not allowed in SUID/SGID programs")); \ __newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str), \ __dst_cnt)); \ \ - __result = _dl_dst_substitute (l, __str, __newp, 0); \ + __result = _dl_dst_substitute (l, __str, __newp); \ \ if (*__result == '\0') \ { \ @@ -153,7 +153,6 @@ preload (struct list *known, unsigned int *nlist, struct link_map *map) } void -internal_function _dl_map_object_deps (struct link_map *map, struct link_map **preloads, unsigned int npreloads, int trace_mode, int open_mode) @@ -165,8 +164,7 @@ _dl_map_object_deps (struct link_map *map, const char *name; int errno_saved; int errno_reason; - const char *errstring; - const char *objname; + struct dl_exception exception; /* No loaded object so far. */ nlist = 0; @@ -184,9 +182,8 @@ _dl_map_object_deps (struct link_map *map, /* Pointer to last unique object. */ tail = &known[nlist - 1]; - /* No alloca'd space yet. */ - struct link_map **needed_space = NULL; - size_t needed_space_bytes = 0; + struct scratch_buffer needed_space; + scratch_buffer_init (&needed_space); /* Process each element of the search list, loading each of its auxiliary objects and immediate dependencies. Auxiliary objects @@ -200,7 +197,6 @@ _dl_map_object_deps (struct link_map *map, alloca means we cannot use recursive function calls. */ errno_saved = errno; errno_reason = 0; - errstring = NULL; errno = 0; name = NULL; for (runp = known; runp; ) @@ -217,13 +213,12 @@ _dl_map_object_deps (struct link_map *map, if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL && l != map && l->l_ldnum > 0) { - size_t new_size = l->l_ldnum * sizeof (struct link_map *); - - if (new_size > needed_space_bytes) - needed_space - = extend_alloca (needed_space, needed_space_bytes, new_size); - - needed = needed_space; + /* l->l_ldnum includes space for the terminating NULL. */ + if (!scratch_buffer_set_array_size + (&needed_space, l->l_ldnum, sizeof (struct link_map *))) + _dl_signal_error (ENOMEM, map->l_name, NULL, + N_("cannot allocate dependency buffer")); + needed = needed_space.data; } if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG]) @@ -250,17 +245,9 @@ _dl_map_object_deps (struct link_map *map, /* Store the tag in the argument structure. */ args.name = name; - bool malloced; - int err = _dl_catch_error (&objname, &errstring, &malloced, - openaux, &args); - if (__glibc_unlikely (errstring != NULL)) + int err = _dl_catch_exception (&exception, openaux, &args); + if (__glibc_unlikely (exception.errstring != NULL)) { - char *new_errstring = strdupa (errstring); - objname = strdupa (objname); - if (malloced) - free ((char *) errstring); - errstring = new_errstring; - if (err) errno_reason = err; else @@ -313,31 +300,18 @@ _dl_map_object_deps (struct link_map *map, /* We must be prepared that the addressed shared object is not available. For filter objects the dependency must be available. */ - bool malloced; - int err = _dl_catch_error (&objname, &errstring, &malloced, - openaux, &args); - - if (__glibc_unlikely (errstring != NULL)) + int err = _dl_catch_exception (&exception, openaux, &args); + if (__glibc_unlikely (exception.errstring != NULL)) { if (d->d_tag == DT_AUXILIARY) { /* We are not interested in the error message. */ - assert (errstring != NULL); - if (malloced) - free ((char *) errstring); - + _dl_exception_free (&exception); /* Simply ignore this error and continue the work. */ continue; } else { - - char *new_errstring = strdupa (errstring); - objname = strdupa (objname); - if (malloced) - free ((char *) errstring); - errstring = new_errstring; - if (err) errno_reason = err; else @@ -463,8 +437,11 @@ _dl_map_object_deps (struct link_map *map, struct link_map **l_initfini = (struct link_map **) malloc ((2 * nneeded + 1) * sizeof needed[0]); if (l_initfini == NULL) - _dl_signal_error (ENOMEM, map->l_name, NULL, - N_("cannot allocate dependency list")); + { + scratch_buffer_free (&needed_space); + _dl_signal_error (ENOMEM, map->l_name, NULL, + N_("cannot allocate dependency list")); + } l_initfini[0] = l; memcpy (&l_initfini[1], needed, nneeded * sizeof needed[0]); memcpy (&l_initfini[nneeded + 1], l_initfini, @@ -482,6 +459,8 @@ _dl_map_object_deps (struct link_map *map, } out: + scratch_buffer_free (&needed_space); + if (errno == 0 && errno_saved != 0) __set_errno (errno_saved); @@ -610,62 +589,9 @@ Filters not supported with LD_TRACE_PRELINKING")); itself will always be initialize last. */ 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:; - } - } + /* We can skip looking for the binary itself which is at the front of + the search list. */ + _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); /* Terminate the list of dependencies. */ l_initfini[nlist] = NULL; @@ -683,6 +609,6 @@ Filters not supported with LD_TRACE_PRELINKING")); _dl_scope_free (old_l_initfini); if (errno_reason) - _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname, - NULL, errstring); + _dl_signal_exception (errno_reason == -1 ? 0 : errno_reason, + &exception, NULL); } |