|
@@ -563,7 +563,7 @@ index 0ae0b7f..f883910 100644
|
|
|
static int
|
|
|
check_loaded_objects (const char **loaded)
|
|
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
|
|
-index 6dcbabc..431120a 100644
|
|
|
+index 6dcbabc..82cfb7d 100644
|
|
|
--- a/elf/rtld.c
|
|
|
+++ b/elf/rtld.c
|
|
|
@@ -356,6 +356,23 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
|
@@ -664,7 +664,149 @@ index 6dcbabc..431120a 100644
|
|
|
LIBC_PROBE (init_start, 2, LM_ID_BASE, r);
|
|
|
|
|
|
/* Auditing checkpoint: we are ready to signal that the initial map
|
|
|
-@@ -2301,7 +2350,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
|
|
+@@ -1605,140 +1654,11 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+- /* We have two ways to specify objects to preload: via environment
|
|
|
+- variable and via the file /etc/ld.so.preload. The latter can also
|
|
|
+- be used when security is enabled. */
|
|
|
+- assert (*first_preload == NULL);
|
|
|
+- struct link_map **preloads = NULL;
|
|
|
+- unsigned int npreloads = 0;
|
|
|
+-
|
|
|
+- if (__builtin_expect (preloadlist != NULL, 0))
|
|
|
+- {
|
|
|
+- /* The LD_PRELOAD environment variable gives list of libraries
|
|
|
+- separated by white space or colons that are loaded before the
|
|
|
+- executable's dependencies and prepended to the global scope
|
|
|
+- list. If the binary is running setuid all elements
|
|
|
+- containing a '/' are ignored since it is insecure. */
|
|
|
+- char *list = strdupa (preloadlist);
|
|
|
+- char *p;
|
|
|
+-
|
|
|
+- HP_TIMING_NOW (start);
|
|
|
+-
|
|
|
+- /* Prevent optimizing strsep. Speed is not important here. */
|
|
|
+- while ((p = (strsep) (&list, " :")) != NULL)
|
|
|
+- if (p[0] != '\0'
|
|
|
+- && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
|
|
|
+- || strchr (p, '/') == NULL))
|
|
|
+- npreloads += do_preload (p, main_map, "LD_PRELOAD");
|
|
|
+-
|
|
|
+- HP_TIMING_NOW (stop);
|
|
|
+- HP_TIMING_DIFF (diff, start, stop);
|
|
|
+- HP_TIMING_ACCUM_NT (load_time, diff);
|
|
|
+- }
|
|
|
+-
|
|
|
+- /* There usually is no ld.so.preload file, it should only be used
|
|
|
+- for emergencies and testing. So the open call etc should usually
|
|
|
+- fail. Using access() on a non-existing file is faster than using
|
|
|
+- open(). So we do this first. If it succeeds we do almost twice
|
|
|
+- the work but this does not matter, since it is not for production
|
|
|
+- use. */
|
|
|
+- static const char preload_file[] = "/etc/ld.so.preload";
|
|
|
+- if (__builtin_expect (__access (preload_file, R_OK) == 0, 0))
|
|
|
+- {
|
|
|
+- /* Read the contents of the file. */
|
|
|
+- file = _dl_sysdep_read_whole_file (preload_file, &file_size,
|
|
|
+- PROT_READ | PROT_WRITE);
|
|
|
+- if (__builtin_expect (file != MAP_FAILED, 0))
|
|
|
+- {
|
|
|
+- /* Parse the file. It contains names of libraries to be loaded,
|
|
|
+- separated by white spaces or `:'. It may also contain
|
|
|
+- comments introduced by `#'. */
|
|
|
+- char *problem;
|
|
|
+- char *runp;
|
|
|
+- size_t rest;
|
|
|
+-
|
|
|
+- /* Eliminate comments. */
|
|
|
+- runp = file;
|
|
|
+- rest = file_size;
|
|
|
+- while (rest > 0)
|
|
|
+- {
|
|
|
+- char *comment = memchr (runp, '#', rest);
|
|
|
+- if (comment == NULL)
|
|
|
+- break;
|
|
|
+-
|
|
|
+- rest -= comment - runp;
|
|
|
+- do
|
|
|
+- *comment = ' ';
|
|
|
+- while (--rest > 0 && *++comment != '\n');
|
|
|
+- }
|
|
|
+-
|
|
|
+- /* We have one problematic case: if we have a name at the end of
|
|
|
+- the file without a trailing terminating characters, we cannot
|
|
|
+- place the \0. Handle the case separately. */
|
|
|
+- if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t'
|
|
|
+- && file[file_size - 1] != '\n' && file[file_size - 1] != ':')
|
|
|
+- {
|
|
|
+- problem = &file[file_size];
|
|
|
+- while (problem > file && problem[-1] != ' '
|
|
|
+- && problem[-1] != '\t'
|
|
|
+- && problem[-1] != '\n' && problem[-1] != ':')
|
|
|
+- --problem;
|
|
|
+-
|
|
|
+- if (problem > file)
|
|
|
+- problem[-1] = '\0';
|
|
|
+- }
|
|
|
+- else
|
|
|
+- {
|
|
|
+- problem = NULL;
|
|
|
+- file[file_size - 1] = '\0';
|
|
|
+- }
|
|
|
+-
|
|
|
+- HP_TIMING_NOW (start);
|
|
|
+-
|
|
|
+- if (file != problem)
|
|
|
+- {
|
|
|
+- char *p;
|
|
|
+- runp = file;
|
|
|
+- while ((p = strsep (&runp, ": \t\n")) != NULL)
|
|
|
+- if (p[0] != '\0')
|
|
|
+- npreloads += do_preload (p, main_map, preload_file);
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (problem != NULL)
|
|
|
+- {
|
|
|
+- char *p = strndupa (problem, file_size - (problem - file));
|
|
|
+-
|
|
|
+- npreloads += do_preload (p, main_map, preload_file);
|
|
|
+- }
|
|
|
+-
|
|
|
+- HP_TIMING_NOW (stop);
|
|
|
+- HP_TIMING_DIFF (diff, start, stop);
|
|
|
+- HP_TIMING_ACCUM_NT (load_time, diff);
|
|
|
+-
|
|
|
+- /* We don't need the file anymore. */
|
|
|
+- __munmap (file, file_size);
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (__builtin_expect (*first_preload != NULL, 0))
|
|
|
+- {
|
|
|
+- /* Set up PRELOADS with a vector of the preloaded libraries. */
|
|
|
+- struct link_map *l = *first_preload;
|
|
|
+- preloads = __alloca (npreloads * sizeof preloads[0]);
|
|
|
+- i = 0;
|
|
|
+- do
|
|
|
+- {
|
|
|
+- preloads[i++] = l;
|
|
|
+- l = l->l_next;
|
|
|
+- } while (l);
|
|
|
+- assert (i == npreloads);
|
|
|
+- }
|
|
|
+-
|
|
|
+ /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
|
|
|
+ specified some libraries to load, these are inserted before the actual
|
|
|
+ dependencies in the executable's searchlist for symbol resolution. */
|
|
|
+ HP_TIMING_NOW (start);
|
|
|
+- _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
|
|
|
++ _dl_map_object_deps (main_map, NULL, 0, mode == trace, 0);
|
|
|
+ HP_TIMING_NOW (stop);
|
|
|
+ HP_TIMING_DIFF (diff, start, stop);
|
|
|
+ HP_TIMING_ACCUM_NT (load_time, diff);
|
|
|
+@@ -2301,7 +2221,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
|
|
the address since by now the variable might be in another object. */
|
|
|
r = _dl_debug_initialize (0, LM_ID_BASE);
|
|
|
r->r_state = RT_CONSISTENT;
|
|
@@ -1902,3 +2044,32 @@ index 504c95f..dcfc259 100644
|
|
|
_dl_reloc_bad_type (map, r_type, 1);
|
|
|
}
|
|
|
|
|
|
+diff --git a/sysdeps/x86_64/hp-timing.h b/sysdeps/x86_64/hp-timing.h
|
|
|
+index d88206c..886c500 100644
|
|
|
+--- a/sysdeps/x86_64/hp-timing.h
|
|
|
|
|
|
+@@ -18,23 +18,6 @@
|
|
|
+
|
|
|
+ #ifndef _HP_TIMING_H
|
|
|
+
|
|
|
+-/* We can use some of the i686 implementation without changes. */
|
|
|
+-# include <sysdeps/i386/i686/hp-timing.h>
|
|
|
+-
|
|
|
+-/* The "=A" constraint used in 32-bit mode does not work in 64-bit mode. */
|
|
|
+-# undef HP_TIMING_NOW
|
|
|
+-# define HP_TIMING_NOW(Var) \
|
|
|
+- ({ unsigned int _hi, _lo; \
|
|
|
+- asm volatile ("rdtsc" : "=a" (_lo), "=d" (_hi)); \
|
|
|
+- (Var) = ((unsigned long long int) _hi << 32) | _lo; })
|
|
|
+-
|
|
|
+-/* The funny business for 32-bit mode is not required here. */
|
|
|
+-# undef HP_TIMING_ACCUM
|
|
|
+-# define HP_TIMING_ACCUM(Sum, Diff) \
|
|
|
+- do { \
|
|
|
+- hp_timing_t __diff = (Diff) - GLRO(dl_hp_timing_overhead); \
|
|
|
+- __asm__ __volatile__ ("lock; addq %1, %0" \
|
|
|
+- : "=m" (Sum) : "r" (__diff), "m" (Sum)); \
|
|
|
+- } while (0)
|
|
|
++# include <sysdeps/generic/hp-timing.h>
|
|
|
+
|
|
|
+ #endif /* hp-timing.h */
|