446cf2
commit 2bf9e641fd50ec34b04b70829679abf64fc0ed78
446cf2
Author: Florian Weimer <fweimer@redhat.com>
446cf2
Date:   Thu Oct 8 10:57:09 2020 +0200
446cf2
446cf2
    elf: Extract command-line/environment variables state from rtld.c
446cf2
    
446cf2
    Introduce struct dl_main_state and move it to <dl-main.h>.  Rename
446cf2
    enum mode to enum rtld_mode and add the rtld_mode_ prefix to the enum
446cf2
    constants.
446cf2
    
446cf2
    This avoids the need for putting state that is only needed during
446cf2
    startup into the ld.so data segment.
446cf2
446cf2
Conflicts:
446cf2
	elf/rtld.c
446cf2
	  (Caused by glibc-fedora-__libc_multiple_libcs.patch.)
446cf2
446cf2
diff --git a/elf/dl-main.h b/elf/dl-main.h
446cf2
new file mode 100644
446cf2
index 0000000000000000..bcc9bcf2e8fee6e7
446cf2
--- /dev/null
446cf2
+++ b/elf/dl-main.h
446cf2
@@ -0,0 +1,98 @@
446cf2
+/* Information collection during ld.so startup.
446cf2
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
446cf2
+   This file is part of the GNU C Library.
446cf2
+
446cf2
+   The GNU C Library is free software; you can redistribute it and/or
446cf2
+   modify it under the terms of the GNU Lesser General Public
446cf2
+   License as published by the Free Software Foundation; either
446cf2
+   version 2.1 of the License, or (at your option) any later version.
446cf2
+
446cf2
+   The GNU C Library is distributed in the hope that it will be useful,
446cf2
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
446cf2
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
446cf2
+   Lesser General Public License for more details.
446cf2
+
446cf2
+   You should have received a copy of the GNU Lesser General Public
446cf2
+   License along with the GNU C Library; if not, see
446cf2
+   <https://www.gnu.org/licenses/>.  */
446cf2
+
446cf2
+#ifndef _DL_MAIN
446cf2
+#define _DL_MAIN
446cf2
+
446cf2
+#include <limits.h>
446cf2
+
446cf2
+/* Length limits for names and paths, to protect the dynamic linker,
446cf2
+   particularly when __libc_enable_secure is active.  */
446cf2
+#ifdef NAME_MAX
446cf2
+# define SECURE_NAME_LIMIT NAME_MAX
446cf2
+#else
446cf2
+# define SECURE_NAME_LIMIT 255
446cf2
+#endif
446cf2
+#ifdef PATH_MAX
446cf2
+# define SECURE_PATH_LIMIT PATH_MAX
446cf2
+#else
446cf2
+# define SECURE_PATH_LIMIT 1024
446cf2
+#endif
446cf2
+
446cf2
+/* Strings containing colon-separated lists of audit modules.  */
446cf2
+struct audit_list
446cf2
+{
446cf2
+  /* Array of strings containing colon-separated path lists.  Each
446cf2
+     audit module needs its own namespace, so pre-allocate the largest
446cf2
+     possible list.  */
446cf2
+  const char *audit_strings[DL_NNS];
446cf2
+
446cf2
+  /* Number of entries added to audit_strings.  */
446cf2
+  size_t length;
446cf2
+
446cf2
+  /* Index into the audit_strings array (for the iteration phase).  */
446cf2
+  size_t current_index;
446cf2
+
446cf2
+  /* Tail of audit_strings[current_index] which still needs
446cf2
+     processing.  */
446cf2
+  const char *current_tail;
446cf2
+
446cf2
+  /* Scratch buffer for returning a name which is part of the strings
446cf2
+     in audit_strings.  */
446cf2
+  char fname[SECURE_NAME_LIMIT];
446cf2
+};
446cf2
+
446cf2
+/* This is a list of all the modes the dynamic loader can be in.  */
446cf2
+enum rtld_mode
446cf2
+  {
446cf2
+    rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace,
446cf2
+  };
446cf2
+
446cf2
+/* Aggregated state information extracted from environment variables
446cf2
+   and the ld.so command line.  */
446cf2
+struct dl_main_state
446cf2
+{
446cf2
+  struct audit_list audit_list;
446cf2
+
446cf2
+  /* The library search path.  */
446cf2
+  const char *library_path;
446cf2
+
446cf2
+  /* The list preloaded objects from LD_PRELOAD.  */
446cf2
+  const char *preloadlist;
446cf2
+
446cf2
+  /* The preload list passed as a command argument.  */
446cf2
+  const char *preloadarg;
446cf2
+
446cf2
+  enum rtld_mode mode;
446cf2
+
446cf2
+  /* True if any of the debugging options is enabled.  */
446cf2
+  bool any_debug;
446cf2
+
446cf2
+  /* True if information about versions has to be printed.  */
446cf2
+  bool version_info;
446cf2
+};
446cf2
+
446cf2
+/* Helper function to invoke _dl_init_paths with the right arguments
446cf2
+   from *STATE.  */
446cf2
+static inline void
446cf2
+call_init_paths (const struct dl_main_state *state)
446cf2
+{
446cf2
+  _dl_init_paths (state->library_path);
446cf2
+}
446cf2
+
446cf2
+#endif /* _DL_MAIN */
446cf2
diff --git a/elf/rtld.c b/elf/rtld.c
446cf2
index 4107a215abd554f4..fbfa441bf3b050ff 100644
446cf2
--- a/elf/rtld.c
446cf2
+++ b/elf/rtld.c
446cf2
@@ -45,6 +45,7 @@
446cf2
 #include <not-cancel.h>
446cf2
 #include <array_length.h>
446cf2
 #include <libc-early-init.h>
446cf2
+#include <dl-main.h>
446cf2
 
446cf2
 #include <assert.h>
446cf2
 
446cf2
@@ -109,42 +110,6 @@ static void print_missing_version (int errcode, const char *objname,
446cf2
 /* Print the various times we collected.  */
446cf2
 static void print_statistics (const hp_timing_t *total_timep);
446cf2
 
446cf2
-/* Length limits for names and paths, to protect the dynamic linker,
446cf2
-   particularly when __libc_enable_secure is active.  */
446cf2
-#ifdef NAME_MAX
446cf2
-# define SECURE_NAME_LIMIT NAME_MAX
446cf2
-#else
446cf2
-# define SECURE_NAME_LIMIT 255
446cf2
-#endif
446cf2
-#ifdef PATH_MAX
446cf2
-# define SECURE_PATH_LIMIT PATH_MAX
446cf2
-#else
446cf2
-# define SECURE_PATH_LIMIT 1024
446cf2
-#endif
446cf2
-
446cf2
-/* Strings containing colon-separated lists of audit modules.  */
446cf2
-struct audit_list
446cf2
-{
446cf2
-  /* Array of strings containing colon-separated path lists.  Each
446cf2
-     audit module needs its own namespace, so pre-allocate the largest
446cf2
-     possible list.  */
446cf2
-  const char *audit_strings[DL_NNS];
446cf2
-
446cf2
-  /* Number of entries added to audit_strings.  */
446cf2
-  size_t length;
446cf2
-
446cf2
-  /* Index into the audit_strings array (for the iteration phase).  */
446cf2
-  size_t current_index;
446cf2
-
446cf2
-  /* Tail of audit_strings[current_index] which still needs
446cf2
-     processing.  */
446cf2
-  const char *current_tail;
446cf2
-
446cf2
-  /* Scratch buffer for returning a name which is part of the strings
446cf2
-     in audit_strings.  */
446cf2
-  char fname[SECURE_NAME_LIMIT];
446cf2
-};
446cf2
-
446cf2
 /* Creates an empty audit list.  */
446cf2
 static void audit_list_init (struct audit_list *);
446cf2
 
446cf2
@@ -165,13 +130,13 @@ static void audit_list_add_dynamic_tag (struct audit_list *,
446cf2
    audit_list_add_dynamic_tags calls.  */
446cf2
 static const char *audit_list_next (struct audit_list *);
446cf2
 
446cf2
-/* This is a list of all the modes the dynamic loader can be in.  */
446cf2
-enum mode { normal, list, verify, trace };
446cf2
+/* Initialize *STATE with the defaults.  */
446cf2
+static void dl_main_state_init (struct dl_main_state *state);
446cf2
 
446cf2
 /* Process all environments variables the dynamic linker must recognize.
446cf2
    Since all of them start with `LD_' we are a bit smarter while finding
446cf2
    all the entries.  */
446cf2
-static void process_envvars (enum mode *modep, struct audit_list *);
446cf2
+static void process_envvars (struct dl_main_state *state);
446cf2
 
446cf2
 #ifdef DL_ARGV_NOT_RELRO
446cf2
 int _dl_argc attribute_hidden;
446cf2
@@ -314,6 +279,18 @@ audit_list_count (struct audit_list *list)
446cf2
   return naudit;
446cf2
 }
446cf2
 
446cf2
+static void
446cf2
+dl_main_state_init (struct dl_main_state *state)
446cf2
+{
446cf2
+  audit_list_init (&state->audit_list);
446cf2
+  state->library_path = NULL;
446cf2
+  state->preloadlist = NULL;
446cf2
+  state->preloadarg = NULL;
446cf2
+  state->mode = rtld_mode_normal;
446cf2
+  state->any_debug = false;
446cf2
+  state->version_info = false;
446cf2
+}
446cf2
+
446cf2
 /* Set nonzero during loading and initialization of executable and
446cf2
    libraries, cleared before the executable's entry point runs.  This
446cf2
    must not be initialized to nonzero, because the unused dynamic
446cf2
@@ -896,15 +873,6 @@ security_init (void)
446cf2
 
446cf2
 #include "setup-vdso.h"
446cf2
 
446cf2
-/* The library search path.  */
446cf2
-static const char *library_path attribute_relro;
446cf2
-/* The list preloaded objects.  */
446cf2
-static const char *preloadlist attribute_relro;
446cf2
-/* Nonzero if information about versions has to be printed.  */
446cf2
-static int version_info attribute_relro;
446cf2
-/* The preload list passed as a command argument.  */
446cf2
-static const char *preloadarg attribute_relro;
446cf2
-
446cf2
 /* The LD_PRELOAD environment variable gives list of libraries
446cf2
    separated by white space or colons that are loaded before the
446cf2
    executable's dependencies and prepended to the global scope list.
446cf2
@@ -1146,7 +1114,6 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
 	 ElfW(auxv_t) *auxv)
446cf2
 {
446cf2
   const ElfW(Phdr) *ph;
446cf2
-  enum mode mode;
446cf2
   struct link_map *main_map;
446cf2
   size_t file_size;
446cf2
   char *file;
446cf2
@@ -1156,8 +1123,8 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
   bool rtld_is_main = false;
446cf2
   void *tcbp = NULL;
446cf2
 
446cf2
-  struct audit_list audit_list;
446cf2
-  audit_list_init (&audit_list);
446cf2
+  struct dl_main_state state;
446cf2
+  dl_main_state_init (&state);
446cf2
 
446cf2
   GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
446cf2
 
446cf2
@@ -1172,7 +1139,7 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
   GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable;
446cf2
 
446cf2
   /* Process the environment variable which control the behaviour.  */
446cf2
-  process_envvars (&mode, &audit_list);
446cf2
+  process_envvars (&state);
446cf2
 
446cf2
   /* Set up a flag which tells we are just starting.  */
446cf2
   _dl_starting_up = 1;
446cf2
@@ -1204,7 +1171,7 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
       while (_dl_argc > 1)
446cf2
 	if (! strcmp (_dl_argv[1], "--list"))
446cf2
 	  {
446cf2
-	    mode = list;
446cf2
+	    state.mode = rtld_mode_list;
446cf2
 	    GLRO(dl_lazy) = -1;	/* This means do no dependency analysis.  */
446cf2
 
446cf2
 	    ++_dl_skip_args;
446cf2
@@ -1213,7 +1180,7 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
 	  }
446cf2
 	else if (! strcmp (_dl_argv[1], "--verify"))
446cf2
 	  {
446cf2
-	    mode = verify;
446cf2
+	    state.mode = rtld_mode_verify;
446cf2
 
446cf2
 	    ++_dl_skip_args;
446cf2
 	    --_dl_argc;
446cf2
@@ -1229,7 +1196,7 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
 	else if (! strcmp (_dl_argv[1], "--library-path")
446cf2
 		 && _dl_argc > 2)
446cf2
 	  {
446cf2
-	    library_path = _dl_argv[2];
446cf2
+	    state.library_path = _dl_argv[2];
446cf2
 
446cf2
 	    _dl_skip_args += 2;
446cf2
 	    _dl_argc -= 2;
446cf2
@@ -1246,7 +1213,7 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
 	  }
446cf2
 	else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2)
446cf2
 	  {
446cf2
-	    audit_list_add_string (&audit_list, _dl_argv[2]);
446cf2
+	    audit_list_add_string (&state.audit_list, _dl_argv[2]);
446cf2
 
446cf2
 	    _dl_skip_args += 2;
446cf2
 	    _dl_argc -= 2;
446cf2
@@ -1254,7 +1221,7 @@ dl_main (const ElfW(Phdr) *phdr,
446cf2
 	  }
446cf2
 	else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2)
446cf2
 	  {
446cf2
-	    preloadarg = _dl_argv[2];
446cf2
+	    state.preloadarg = _dl_argv[2];
446cf2
 	    _dl_skip_args += 2;
446cf2
 	    _dl_argc -= 2;
446cf2
 	    _dl_argv += 2;
446cf2
@@ -1322,7 +1289,7 @@ of this helper program; chances are you did not intend to run this program.\n\
446cf2
 	    break;
446cf2
 	  }
446cf2
 
446cf2
-      if (__builtin_expect (mode, normal) == verify)
446cf2
+      if (__glibc_unlikely (state.mode == rtld_mode_verify))
446cf2
 	{
446cf2
 	  const char *objname;
446cf2
 	  const char *err_str = NULL;
446cf2
@@ -1351,7 +1318,7 @@ of this helper program; chances are you did not intend to run this program.\n\
446cf2
       /* Now the map for the main executable is available.  */
446cf2
       main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
446cf2
 
446cf2
-      if (__builtin_expect (mode, normal) == normal
446cf2
+      if (__glibc_likely (state.mode == rtld_mode_normal)
446cf2
 	  && GL(dl_rtld_map).l_info[DT_SONAME] != NULL
446cf2
 	  && main_map->l_info[DT_SONAME] != NULL
446cf2
 	  && strcmp ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
446cf2
@@ -1592,7 +1559,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
       _dl_setup_hash (main_map);
446cf2
     }
446cf2
 
446cf2
-  if (__builtin_expect (mode, normal) == verify)
446cf2
+  if (__glibc_unlikely (state.mode == rtld_mode_verify))
446cf2
     {
446cf2
       /* We were called just to verify that this is a dynamic
446cf2
 	 executable using us as the program interpreter.  Exit with an
446cf2
@@ -1619,7 +1586,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
 
446cf2
   /* Initialize the data structures for the search paths for shared
446cf2
      objects.  */
446cf2
-  _dl_init_paths (library_path);
446cf2
+  call_init_paths (&state);
446cf2
 
446cf2
   /* Initialize _r_debug.  */
446cf2
   struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr,
446cf2
@@ -1684,14 +1651,14 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
     /* Assign a module ID.  Do this before loading any audit modules.  */
446cf2
     GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
446cf2
 
446cf2
-  audit_list_add_dynamic_tag (&audit_list, main_map, DT_AUDIT);
446cf2
-  audit_list_add_dynamic_tag (&audit_list, main_map, DT_DEPAUDIT);
446cf2
+  audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_AUDIT);
446cf2
+  audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_DEPAUDIT);
446cf2
 
446cf2
   /* If we have auditing DSOs to load, do it now.  */
446cf2
   bool need_security_init = true;
446cf2
-  if (audit_list.length > 0)
446cf2
+  if (state.audit_list.length > 0)
446cf2
     {
446cf2
-      size_t naudit = audit_list_count (&audit_list);
446cf2
+      size_t naudit = audit_list_count (&state.audit_list);
446cf2
 
446cf2
       /* Since we start using the auditing DSOs right away we need to
446cf2
 	 initialize the data structures now.  */
446cf2
@@ -1704,7 +1671,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
       security_init ();
446cf2
       need_security_init = false;
446cf2
 
446cf2
-      load_audit_modules (main_map, &audit_list);
446cf2
+      load_audit_modules (main_map, &state.audit_list);
446cf2
 
446cf2
       /* The count based on audit strings may overestimate the number
446cf2
 	 of audit modules that got loaded, but not underestimate.  */
446cf2
@@ -1759,19 +1726,21 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
   struct link_map **preloads = NULL;
446cf2
   unsigned int npreloads = 0;
446cf2
 
446cf2
-  if (__glibc_unlikely (preloadlist != NULL))
446cf2
+  if (__glibc_unlikely (state.preloadlist != NULL))
446cf2
     {
446cf2
       RTLD_TIMING_VAR (start);
446cf2
       rtld_timer_start (&start;;
446cf2
-      npreloads += handle_preload_list (preloadlist, main_map, "LD_PRELOAD");
446cf2
+      npreloads += handle_preload_list (state.preloadlist, main_map,
446cf2
+					"LD_PRELOAD");
446cf2
       rtld_timer_accum (&load_time, start);
446cf2
     }
446cf2
 
446cf2
-  if (__glibc_unlikely (preloadarg != NULL))
446cf2
+  if (__glibc_unlikely (state.preloadarg != NULL))
446cf2
     {
446cf2
       RTLD_TIMING_VAR (start);
446cf2
       rtld_timer_start (&start;;
446cf2
-      npreloads += handle_preload_list (preloadarg, main_map, "--preload");
446cf2
+      npreloads += handle_preload_list (state.preloadarg, main_map,
446cf2
+					"--preload");
446cf2
       rtld_timer_accum (&load_time, start);
446cf2
     }
446cf2
 
446cf2
@@ -1878,7 +1847,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
   {
446cf2
     RTLD_TIMING_VAR (start);
446cf2
     rtld_timer_start (&start;;
446cf2
-    _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
446cf2
+    _dl_map_object_deps (main_map, preloads, npreloads,
446cf2
+			 state.mode == rtld_mode_trace, 0);
446cf2
     rtld_timer_accum (&load_time, start);
446cf2
   }
446cf2
 
446cf2
@@ -1905,7 +1875,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
       rtld_multiple_ref = true;
446cf2
 
446cf2
       GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
446cf2
-      if (__builtin_expect (mode, normal) == normal)
446cf2
+      if (__glibc_likely (state.mode == rtld_mode_normal))
446cf2
 	{
446cf2
 	  GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist
446cf2
 				    ? main_map->l_searchlist.r_list[i + 1]
446cf2
@@ -1938,8 +1908,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
      versions we need.  */
446cf2
   {
446cf2
     struct version_check_args args;
446cf2
-    args.doexit = mode == normal;
446cf2
-    args.dotrace = mode == trace;
446cf2
+    args.doexit = state.mode == rtld_mode_normal;
446cf2
+    args.dotrace = state.mode == rtld_mode_trace;
446cf2
     _dl_receive_error (print_missing_version, version_check_doit, &args);
446cf2
   }
446cf2
 
446cf2
@@ -1959,7 +1929,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
        earlier.  */
446cf2
     security_init ();
446cf2
 
446cf2
-  if (__builtin_expect (mode, normal) != normal)
446cf2
+  if (__glibc_unlikely (state.mode != rtld_mode_normal))
446cf2
     {
446cf2
       /* We were run just to list the shared libraries.  It is
446cf2
 	 important that we do this before real relocation, because the
446cf2
@@ -2061,7 +2031,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
 			  (size_t) l->l_map_start);
446cf2
 	}
446cf2
 
446cf2
-      if (__builtin_expect (mode, trace) != trace)
446cf2
+      if (__glibc_unlikely (state.mode != rtld_mode_trace))
446cf2
 	for (i = 1; i < (unsigned int) _dl_argc; ++i)
446cf2
 	  {
446cf2
 	    const ElfW(Sym) *ref = NULL;
446cf2
@@ -2115,7 +2085,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
446cf2
 		}
446cf2
 	    }
446cf2
 #define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
446cf2
-	  if (version_info)
446cf2
+	  if (state.version_info)
446cf2
 	    {
446cf2
 	      /* Print more information.  This means here, print information
446cf2
 		 about the versions needed.  */
446cf2
@@ -2477,13 +2447,10 @@ print_missing_version (int errcode __attribute__ ((unused)),
446cf2
 		    objname, errstring);
446cf2
 }
446cf2
 
446cf2
-/* Nonzero if any of the debugging options is enabled.  */
446cf2
-static int any_debug attribute_relro;
446cf2
-
446cf2
 /* Process the string given as the parameter which explains which debugging
446cf2
    options are enabled.  */
446cf2
 static void
446cf2
-process_dl_debug (const char *dl_debug)
446cf2
+process_dl_debug (struct dl_main_state *state, const char *dl_debug)
446cf2
 {
446cf2
   /* When adding new entries make sure that the maximal length of a name
446cf2
      is correctly handled in the LD_DEBUG_HELP code below.  */
446cf2
@@ -2540,7 +2507,7 @@ process_dl_debug (const char *dl_debug)
446cf2
 		&& memcmp (dl_debug, debopts[cnt].name, len) == 0)
446cf2
 	      {
446cf2
 		GLRO(dl_debug_mask) |= debopts[cnt].mask;
446cf2
-		any_debug = 1;
446cf2
+		state->any_debug = true;
446cf2
 		break;
446cf2
 	      }
446cf2
 
446cf2
@@ -2594,11 +2561,10 @@ extern char **_environ attribute_hidden;
446cf2
 
446cf2
 
446cf2
 static void
446cf2
-process_envvars (enum mode *modep, struct audit_list *audit_list)
446cf2
+process_envvars (struct dl_main_state *state)
446cf2
 {
446cf2
   char **runp = _environ;
446cf2
   char *envline;
446cf2
-  enum mode mode = normal;
446cf2
   char *debug_output = NULL;
446cf2
 
446cf2
   /* This is the default place for profiling data file.  */
446cf2
@@ -2630,25 +2596,25 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
446cf2
 	  /* Debugging of the dynamic linker?  */
446cf2
 	  if (memcmp (envline, "DEBUG", 5) == 0)
446cf2
 	    {
446cf2
-	      process_dl_debug (&envline[6]);
446cf2
+	      process_dl_debug (state, &envline[6]);
446cf2
 	      break;
446cf2
 	    }
446cf2
 	  if (memcmp (envline, "AUDIT", 5) == 0)
446cf2
-	    audit_list_add_string (audit_list, &envline[6]);
446cf2
+	    audit_list_add_string (&state->audit_list, &envline[6]);
446cf2
 	  break;
446cf2
 
446cf2
 	case 7:
446cf2
 	  /* Print information about versions.  */
446cf2
 	  if (memcmp (envline, "VERBOSE", 7) == 0)
446cf2
 	    {
446cf2
-	      version_info = envline[8] != '\0';
446cf2
+	      state->version_info = envline[8] != '\0';
446cf2
 	      break;
446cf2
 	    }
446cf2
 
446cf2
 	  /* List of objects to be preloaded.  */
446cf2
 	  if (memcmp (envline, "PRELOAD", 7) == 0)
446cf2
 	    {
446cf2
-	      preloadlist = &envline[8];
446cf2
+	      state->preloadlist = &envline[8];
446cf2
 	      break;
446cf2
 	    }
446cf2
 
446cf2
@@ -2697,7 +2663,7 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
446cf2
 	  if (!__libc_enable_secure
446cf2
 	      && memcmp (envline, "LIBRARY_PATH", 12) == 0)
446cf2
 	    {
446cf2
-	      library_path = &envline[13];
446cf2
+	      state->library_path = &envline[13];
446cf2
 	      break;
446cf2
 	    }
446cf2
 
446cf2
@@ -2739,7 +2705,7 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
446cf2
 	  /* The mode of the dynamic linker can be set.  */
446cf2
 	  if (memcmp (envline, "TRACE_PRELINKING", 16) == 0)
446cf2
 	    {
446cf2
-	      mode = trace;
446cf2
+	      state->mode = rtld_mode_trace;
446cf2
 	      GLRO(dl_verbose) = 1;
446cf2
 	      GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
446cf2
 	      GLRO(dl_trace_prelink) = &envline[17];
446cf2
@@ -2749,7 +2715,7 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
446cf2
 	case 20:
446cf2
 	  /* The mode of the dynamic linker can be set.  */
446cf2
 	  if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
446cf2
-	    mode = trace;
446cf2
+	    state->mode = rtld_mode_trace;
446cf2
 	  break;
446cf2
 
446cf2
 	  /* We might have some extra environment variable to handle.  This
446cf2
@@ -2762,9 +2728,6 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
446cf2
 	}
446cf2
     }
446cf2
 
446cf2
-  /* The caller wants this information.  */
446cf2
-  *modep = mode;
446cf2
-
446cf2
   /* Extra security for SUID binaries.  Remove all dangerous environment
446cf2
      variables.  */
446cf2
   if (__builtin_expect (__libc_enable_secure, 0))
446cf2
@@ -2793,13 +2756,13 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
446cf2
 	  GLRO(dl_debug_mask) = 0;
446cf2
 	}
446cf2
 
446cf2
-      if (mode != normal)
446cf2
+      if (state->mode != rtld_mode_normal)
446cf2
 	_exit (5);
446cf2
     }
446cf2
   /* If we have to run the dynamic linker in debugging mode and the
446cf2
      LD_DEBUG_OUTPUT environment variable is given, we write the debug
446cf2
      messages to this file.  */
446cf2
-  else if (any_debug && debug_output != NULL)
446cf2
+  else if (state->any_debug && debug_output != NULL)
446cf2
     {
446cf2
       const int flags = O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW;
446cf2
       size_t name_len = strlen (debug_output);