summaryrefslogtreecommitdiff
path: root/elf/dl-open.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-open.c')
-rw-r--r--elf/dl-open.c136
1 files changed, 18 insertions, 118 deletions
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 6f178b333d..f6c8ef1043 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -1,5 +1,5 @@
/* Load a shared object at runtime, relocate it, and run its initializer.
- 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
@@ -28,17 +28,16 @@
#include <sys/param.h>
#include <libc-lock.h>
#include <ldsodefs.h>
-#include <caller.h>
#include <sysdep-cancel.h>
#include <tls.h>
#include <stap-probe.h>
#include <atomic.h>
+#include <libc-internal.h>
#include <dl-dst.h>
+#include <dl-prop.h>
-extern int __libc_multiple_libcs; /* Defined in init-first.c. */
-
/* We must be careful not to leave us in an inconsistent state. Thus we
catch any error and re-raise it after cleaning up. */
@@ -48,8 +47,6 @@ struct dl_open_args
int mode;
/* This is the caller of the dlopen() function. */
const void *caller_dlopen;
- /* This is the caller of _dl_open(). */
- const void *caller_dl_open;
struct link_map *map;
/* Namespace ID. */
Lmid_t nsid;
@@ -162,7 +159,6 @@ add_to_global (struct link_map *new)
address ADDR. Returns the pointer to the link map of the matching DSO, or
NULL if a match is not found. */
struct link_map *
-internal_function
_dl_find_dso_for_object (const ElfW(Addr) addr)
{
struct link_map *l;
@@ -189,11 +185,6 @@ dl_open_worker (void *a)
int mode = args->mode;
struct link_map *call_map = NULL;
- /* Check whether _dl_open() has been called from a valid DSO. */
- if (__check_caller (args->caller_dl_open,
- allow_libc|allow_libdl|allow_ldso) != 0)
- _dl_signal_error (0, "dlopen", NULL, N_("invalid caller"));
-
/* Determine the caller's map if necessary. This is needed in case
we have a DST, when we don't know the namespace ID we have to put
the new object in, or when the file name has no path in which
@@ -226,12 +217,6 @@ dl_open_worker (void *a)
args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
mode | __RTLD_CALLMAP, args->nsid);
- /* Mark the object as not deletable if the RTLD_NODELETE flags was passed.
- Do this early so that we don't skip marking the object if it was
- already loaded. */
- if (__glibc_unlikely (mode & RTLD_NODELETE))
- new->l_flags_1 |= DF_1_NODELETE;
-
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
set and the object is not already loaded. */
if (new == NULL)
@@ -240,6 +225,12 @@ dl_open_worker (void *a)
return;
}
+ /* Mark the object as not deletable if the RTLD_NODELETE flags was passed.
+ Do this early so that we don't skip marking the object if it was
+ already loaded. */
+ if (__glibc_unlikely (mode & RTLD_NODELETE))
+ new->l_flags_1 |= DF_1_NODELETE;
+
if (__glibc_unlikely (mode & __RTLD_SPROF))
/* This happens only if we load a DSO for 'sprof'. */
return;
@@ -301,6 +292,8 @@ dl_open_worker (void *a)
_dl_debug_state ();
LIBC_PROBE (map_complete, 3, args->nsid, r, new);
+ _dl_open_check (new);
+
/* Print scope information. */
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
_dl_show_scope (new, 0);
@@ -313,7 +306,7 @@ dl_open_worker (void *a)
/* Sort the objects by dependency for the relocation process. This
allows IFUNC relocations to work and it also means copy
relocation of dependencies are if necessary overwritten. */
- size_t nmaps = 0;
+ unsigned int nmaps = 0;
struct link_map *l = new;
do
{
@@ -332,62 +325,11 @@ dl_open_worker (void *a)
l = l->l_next;
}
while (l != NULL);
- if (nmaps > 1)
- {
- uint16_t seen[nmaps];
- memset (seen, '\0', sizeof (seen));
- size_t i = 0;
- while (1)
- {
- ++seen[i];
- struct link_map *thisp = maps[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. */
- size_t 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 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 (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;
- }
-
- --k;
- }
-
- if (++i == nmaps)
- break;
- next_clear:
- memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0]));
- next:;
- }
- }
+ _dl_sort_maps (maps, nmaps, NULL, false);
int relocation_in_progress = 0;
- for (size_t i = nmaps; i-- > 0; )
+ for (unsigned int i = nmaps; i-- > 0; )
{
l = maps[i];
@@ -636,18 +578,14 @@ no more namespaces available for dlmopen()"));
args.file = file;
args.mode = mode;
args.caller_dlopen = caller_dlopen;
- args.caller_dl_open = RETURN_ADDRESS (0);
args.map = NULL;
args.nsid = nsid;
args.argc = argc;
args.argv = argv;
args.env = env;
- const char *objname;
- const char *errstring;
- bool malloced;
- int errcode = _dl_catch_error (&objname, &errstring, &malloced,
- dl_open_worker, &args);
+ struct dl_exception exception;
+ int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
#if defined USE_LDCONFIG && !defined MAP_COPY
/* We must unmap the cache file. */
@@ -655,7 +593,7 @@ no more namespaces available for dlmopen()"));
#endif
/* See if an error occurred during loading. */
- if (__glibc_unlikely (errstring != NULL))
+ if (__glibc_unlikely (exception.errstring != NULL))
{
/* Remove the object from memory. It may be in an inconsistent
state if relocation failed, for example. */
@@ -679,28 +617,8 @@ no more namespaces available for dlmopen()"));
/* Release the lock. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));
- /* Make a local copy of the error string so that we can release the
- memory allocated for it. */
- size_t len_errstring = strlen (errstring) + 1;
- char *local_errstring;
- if (objname == errstring + len_errstring)
- {
- size_t total_len = len_errstring + strlen (objname) + 1;
- local_errstring = alloca (total_len);
- memcpy (local_errstring, errstring, total_len);
- objname = local_errstring + len_errstring;
- }
- else
- {
- local_errstring = alloca (len_errstring);
- memcpy (local_errstring, errstring, len_errstring);
- }
-
- if (malloced)
- free ((char *) errstring);
-
/* Reraise the error. */
- _dl_signal_error (errcode, objname, NULL, local_errstring);
+ _dl_signal_exception (errcode, &exception, NULL);
}
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
@@ -735,21 +653,3 @@ _dl_show_scope (struct link_map *l, int from)
_dl_debug_printf (" no scope\n");
_dl_debug_printf ("\n");
}
-
-#if IS_IN (rtld)
-/* Return non-zero if ADDR lies within one of L's segments. */
-int
-internal_function
-_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
-{
- int n = l->l_phnum;
- const ElfW(Addr) reladdr = addr - l->l_addr;
-
- while (--n >= 0)
- if (l->l_phdr[n].p_type == PT_LOAD
- && reladdr - l->l_phdr[n].p_vaddr >= 0
- && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
- return 1;
- return 0;
-}
-#endif