summary refs log tree commit diff
path: root/elf/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 7189ca6b2b..726463c882 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -61,6 +61,9 @@ int _dl_verbose;
 const char *_dl_platform;
 size_t _dl_platformlen;
 struct r_search_path *_dl_search_paths;
+const char *_dl_profile;
+const char *_dl_profile_output;
+struct link_map *_dl_profile_map;
 
 /* Set nonzero during loading and initialization of executable and
    libraries, cleared before the executable's entry point runs.  This
@@ -109,7 +112,7 @@ _dl_start (void *arg)
   /* Relocate ourselves so we can do normal function calls and
      data access using the global offset table.  */
 
-  ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0);
+  ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
 
   /* Now life is sane; we can call functions and access global data.
      Set up to use the operating system facilities, and find out from
@@ -269,6 +272,26 @@ dl_main (const ElfW(Phdr) *phdr,
   else
     lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
 
+  /* See whether we want to use profiling.  */
+  _dl_profile = getenv ("LD_PROFILE");
+  if (_dl_profile != NULL)
+    if (_dl_profile[0] == '\0')
+      /* An empty string is of not much help.  Disable profiling.  */
+      _dl_profile = NULL;
+    else
+      {
+	/* OK, we have the name of a shared object we want to
+	   profile.  It's up to the user to provide a good name, it
+	   must match the file name or soname of one of the loaded
+	   objects.  Now let's see where we are supposed to place the
+	   result.  */
+	_dl_profile_output = getenv ("LD_PROFILE_OUTPUT");
+
+	if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0')
+	  /* This is the default place.  */
+	  _dl_profile_output = "/var/tmp";
+      }
+
   /* Set up a flag which tells we are just starting.  */
   _dl_starting_up = 1;
 
@@ -814,6 +837,11 @@ of this helper program; chances are you did not intend to run this program.\n",
     _dl_debug_state ();
   }
 
+  /* Now enable profiling if needed.  */
+  if (_dl_profile_map != NULL)
+    /* We must prepare the profiling.  */
+    _dl_start_profile (_dl_profile_map, _dl_profile_output);
+
   /* Once we return, _dl_sysdep_start will invoke
      the DT_INIT functions and then *USER_ENTRY.  */
 }
@@ -824,6 +852,8 @@ static void
 print_unresolved (int errcode __attribute__ ((unused)), const char *objname,
 		  const char *errstring)
 {
+  if (objname[0] == '\0')
+    objname = _dl_argv[0] ?: "<main program>";
   _dl_sysdep_error (errstring, "	(", objname, ")\n", NULL);
 }