Back to index

glibc  2.9
Classes | Defines | Functions | Variables
rtld.c File Reference
#include <errno.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ldsodefs.h>
#include <stdio-common/_itoa.h>
#include <entry.h>
#include <fpu_control.h>
#include <hp-timing.h>
#include <bits/libc-lock.h>
#include "dynamic-link.h"
#include <dl-librecon.h>
#include <unsecvars.h>
#include <dl-cache.h>
#include <dl-osinfo.h>
#include <dl-procinfo.h>
#include <tls.h>
#include <assert.h>
#include <dl-procinfo.c>

Go to the source code of this file.

Classes

struct  dl_start_final_info
struct  relocate_args
struct  map_args
struct  dlmopen_args
struct  lookup_args
struct  version_check_args

Defines

#define _exit   exit_internal
#define ADDRIDX(tag)
#define bootstrap_map   info.l
#define RTLD_BOOTSTRAP
#define RESOLVE_MAP(sym, version, flags)   (&bootstrap_map)
#define ELF_MACHINE_START_ADDRESS(map, start)   (start)
#define VERDEFTAG   (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERDEF))
#define naudit_ifaces   8
#define STRING(s)   __STRING (s)
#define VERNEEDTAG   (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
#define NONTLS_INIT_TP   do { } while (0)
#define LEN_AND_STR(str)   sizeof (str) - 1, str
#define ndebopts   (sizeof (debopts) / sizeof (debopts[0]))

Functions

 __typeof (__mempcpy)
static void process_envvars (enum mode *modep)
uintptr_t
__pointer_chk_guard_local
attribute_relro
attribute_hidden 
__attribute__ ((nocommon))
 strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
struct rtld_global __attribute__ ((alias("_rtld_global"), visibility("hidden")))
struct rtld_global_ro __attribute__ ((alias("_rtld_global_ro"), visibility("hidden")))
static void dl_main (const ElfW(Phdr)*phdr, ElfW(Word) phnum, ElfW(Addr)*user_entry)
static ElfW (Addr)
static void relocate_doit (void *a)
static void map_doit (void *a)
static void dlmopen_doit (void *a)
static void lookup_doit (void *a)
static void version_check_doit (void *a)
static struct link_mapfind_needed (const char *name)
static int match_version (const char *string, struct link_map *map)
static void * init_tls (void)
static unsigned int do_preload (char *fname, struct link_map *main_map, const char *where)
static void security_init (void)
static void print_unresolved (int errcode __attribute__((unused)), const char *objname, const char *errstring)
static void print_missing_version (int errcode __attribute__((unused)), const char *objname, const char *errstring)
static void process_dl_debug (const char *dl_debug)
static void process_dl_audit (char *str)
static void __attribute ((noinline))

Variables

int _dl_argc attribute_relro attribute_hidden
char **_dl_argv attribute_relro = NULL
audit_list
int _dl_starting_up = 0
static struct libname_list
static hp_timing_t relocate_time
static bool tls_init_tp_called

Class Documentation

struct dl_start_final_info

Definition at line 221 of file rtld.c.

struct relocate_args

Definition at line 574 of file rtld.c.

Collaboration diagram for relocate_args:
Class Members
struct link_map * l
int lazy
struct map_args

Definition at line 580 of file rtld.c.

Collaboration diagram for map_args:
Class Members
int is_preloaded
struct link_map * loader
struct link_map * map
int mode
char * str
struct dlmopen_args

Definition at line 38 of file dlmopen.c.

Collaboration diagram for dlmopen_args:
Class Members
const void * caller
const char * file
const char * fname
struct link_map * map
int mode
void * new
Lmid_t nsid
struct lookup_args

Definition at line 597 of file rtld.c.

Collaboration diagram for lookup_args:
Class Members
struct link_map * map
const char * name
void * result
struct version_check_args

Definition at line 605 of file rtld.c.

Class Members
int doexit
int dotrace

Define Documentation

#define _exit   exit_internal
#define ADDRIDX (   tag)
#define bootstrap_map   info.l
#define ELF_MACHINE_START_ADDRESS (   map,
  start 
)    (start)
#define LEN_AND_STR (   str)    sizeof (str) - 1, str
#define naudit_ifaces   8
#define ndebopts   (sizeof (debopts) / sizeof (debopts[0]))
#define NONTLS_INIT_TP   do { } while (0)
#define RESOLVE_MAP (   sym,
  version,
  flags 
)    (&bootstrap_map)
#define RTLD_BOOTSTRAP
#define STRING (   s)    __STRING (s)

Function Documentation

static void __attribute ( (noinline)  ) [static]

Definition at line 2721 of file rtld.c.

{
#ifndef HP_TIMING_NONAVAIL
  char buf[200];
  char *cp;
  char *wp;

  /* Total time rtld used.  */
  if (HP_TIMING_AVAIL)
    {
      HP_TIMING_PRINT (buf, sizeof (buf), *rtld_total_timep);
      _dl_debug_printf ("\nruntime linker statistics:\n"
                     "  total startup time in dynamic loader: %s\n", buf);

      /* Print relocation statistics.  */
      char pbuf[30];
      HP_TIMING_PRINT (buf, sizeof (buf), relocate_time);
      cp = _itoa ((1000ULL * relocate_time) / *rtld_total_timep,
                pbuf + sizeof (pbuf), 10, 0);
      wp = pbuf;
      switch (pbuf + sizeof (pbuf) - cp)
       {
       case 3:
         *wp++ = *cp++;
       case 2:
         *wp++ = *cp++;
       case 1:
         *wp++ = '.';
         *wp++ = *cp++;
       }
      *wp = '\0';
      _dl_debug_printf ("\
            time needed for relocation: %s (%s%%)\n", buf, pbuf);
    }
#endif

  unsigned long int num_relative_relocations = 0;
  for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
    {
      if (GL(dl_ns)[ns]._ns_loaded == NULL)
       continue;

      struct r_scope_elem *scope = &GL(dl_ns)[ns]._ns_loaded->l_searchlist;

      for (unsigned int i = 0; i < scope->r_nlist; i++)
       {
         struct link_map *l = scope->r_list [i];

         if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELCOUNT)])
           num_relative_relocations
             += l->l_info[VERSYMIDX (DT_RELCOUNT)]->d_un.d_val;
#ifndef ELF_MACHINE_REL_RELATIVE
         /* Relative relocations are processed on these architectures if
            library is loaded to different address than p_vaddr or
            if not prelinked.  */
         if ((l->l_addr != 0 || !l->l_info[VALIDX(DT_GNU_PRELINKED)])
             && l->l_info[VERSYMIDX (DT_RELACOUNT)])
#else
         /* On e.g. IA-64 or Alpha, relative relocations are processed
            only if library is loaded to different address than p_vaddr.  */
         if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELACOUNT)])
#endif
           num_relative_relocations
             += l->l_info[VERSYMIDX (DT_RELACOUNT)]->d_un.d_val;
       }
    }

  _dl_debug_printf ("                 number of relocations: %lu\n"
                  "      number of relocations from cache: %lu\n"
                  "        number of relative relocations: %lu\n",
                  GL(dl_num_relocations),
                  GL(dl_num_cache_relocations),
                  num_relative_relocations);

#ifndef HP_TIMING_NONAVAIL
  /* Time spend while loading the object and the dependencies.  */
  if (HP_TIMING_AVAIL)
    {
      char pbuf[30];
      HP_TIMING_PRINT (buf, sizeof (buf), load_time);
      cp = _itoa ((1000ULL * load_time) / *rtld_total_timep,
                pbuf + sizeof (pbuf), 10, 0);
      wp = pbuf;
      switch (pbuf + sizeof (pbuf) - cp)
       {
       case 3:
         *wp++ = *cp++;
       case 2:
         *wp++ = *cp++;
       case 1:
         *wp++ = '.';
         *wp++ = *cp++;
       }
      *wp = '\0';
      _dl_debug_printf ("\
           time needed to load objects: %s (%s%%)\n",
                            buf, pbuf);
    }
#endif
}

Here is the call graph for this function:

uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden __attribute__ ( (nocommon)  )
struct rtld_global __attribute__ ( (alias("_rtld_global"), visibility("hidden"))  ) [read, abstract]
struct rtld_global_ro __attribute__ ( (alias("_rtld_global_ro"), visibility("hidden"))  ) [read, abstract]

Definition at line 47 of file rtld.c.

          { normal, list, verify, trace };

Here is the caller graph for this function:

static void dl_main ( const ElfW(Phdr)*  phdr,
ElfW(Word)  phnum,
ElfW(Addr)*  user_entry 
) [static]
static void dlmopen_doit ( void *  a) [static]

Definition at line 629 of file rtld.c.

{
  struct dlmopen_args *args = (struct dlmopen_args *) a;
  args->map = _dl_open (args->fname, RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT,
                     dl_main, LM_ID_NEWLM, _dl_argc, INTUSE(_dl_argv),
                     __environ);
}

Here is the call graph for this function:

static unsigned int do_preload ( char *  fname,
struct link_map main_map,
const char *  where 
) [static]

Definition at line 793 of file rtld.c.

{
  const char *objname;
  const char *err_str = NULL;
  struct map_args args;
  bool malloced;

  args.str = fname;
  args.loader = main_map;
  args.is_preloaded = 1;
  args.mode = 0;

  unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;

  (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, &args);
  if (__builtin_expect (err_str != NULL, 0))
    {
      _dl_error_printf ("\
ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
                     fname, where);
      /* No need to call free, this is still before
        the libc's malloc is used.  */
    }
  else if (GL(dl_ns)[LM_ID_BASE]._ns_nloaded != old_nloaded)
    /* It is no duplicate.  */
    return 1;

  /* Nothing loaded.  */
  return 0;
}

Here is the call graph for this function:

static ElfW ( Addr  ) [static]

Definition at line 228 of file rtld.c.

{
  ElfW(Addr) start_addr;

  if (HP_TIMING_AVAIL)
    {
      /* If it hasn't happen yet record the startup time.  */
      if (! HP_TIMING_INLINE)
       HP_TIMING_NOW (start_time);
#if !defined DONT_USE_BOOTSTRAP_MAP && !defined HP_TIMING_NONAVAIL
      else
       start_time = info->start_time;
#endif

      /* Initialize the timing functions.  */
      HP_TIMING_DIFF_INIT ();
    }

  /* Transfer data about ourselves to the permanent link_map structure.  */
#ifndef DONT_USE_BOOTSTRAP_MAP
  GL(dl_rtld_map).l_addr = info->l.l_addr;
  GL(dl_rtld_map).l_ld = info->l.l_ld;
  memcpy (GL(dl_rtld_map).l_info, info->l.l_info,
         sizeof GL(dl_rtld_map).l_info);
  GL(dl_rtld_map).l_mach = info->l.l_mach;
  GL(dl_rtld_map).l_relocated = 1;
#endif
  _dl_setup_hash (&GL(dl_rtld_map));
  GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
  GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
  GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
  GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
  /* Copy the TLS related data if necessary.  */
#ifndef DONT_USE_BOOTSTRAP_MAP
# if USE___THREAD
  assert (info->l.l_tls_modid != 0);
  GL(dl_rtld_map).l_tls_blocksize = info->l.l_tls_blocksize;
  GL(dl_rtld_map).l_tls_align = info->l.l_tls_align;
  GL(dl_rtld_map).l_tls_firstbyte_offset = info->l.l_tls_firstbyte_offset;
  GL(dl_rtld_map).l_tls_initimage_size = info->l.l_tls_initimage_size;
  GL(dl_rtld_map).l_tls_initimage = info->l.l_tls_initimage;
  GL(dl_rtld_map).l_tls_offset = info->l.l_tls_offset;
  GL(dl_rtld_map).l_tls_modid = 1;
# else
#  if NO_TLS_OFFSET != 0
  GL(dl_rtld_map).l_tls_offset = NO_TLS_OFFSET;
#  endif
# endif

#endif

#if HP_TIMING_AVAIL
  HP_TIMING_NOW (GL(dl_cpuclock_offset));
#endif

  /* Initialize the stack end variable.  */
  __libc_stack_end = __builtin_frame_address (0);

  /* Call the OS-dependent function to set up life so we can do things like
     file access.  It will call `dl_main' (below) to do all the real work
     of the dynamic linker, and then unwind our frame and run the user
     entry point on the same stack we entered on.  */
  start_addr = _dl_sysdep_start (arg, &dl_main);

#ifndef HP_TIMING_NONAVAIL
  hp_timing_t rtld_total_time;
  if (HP_TIMING_AVAIL)
    {
      hp_timing_t end_time;

      /* Get the current time.  */
      HP_TIMING_NOW (end_time);

      /* Compute the difference.  */
      HP_TIMING_DIFF (rtld_total_time, start_time, end_time);
    }
#endif

  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
    {
#ifndef HP_TIMING_NONAVAIL
      print_statistics (&rtld_total_time);
#else
      print_statistics (NULL);
#endif
    }

  return start_addr;
}

Here is the call graph for this function:

static struct link_map* find_needed ( const char *  name) [static, read]

Definition at line 662 of file rtld.c.

{
  struct r_scope_elem *scope = &GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_searchlist;
  unsigned int n = scope->r_nlist;

  while (n-- > 0)
    if (_dl_name_match_p (name, scope->r_list[n]))
      return scope->r_list[n];

  /* Should never happen.  */
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* init_tls ( void  ) [static]

Definition at line 711 of file rtld.c.

{
  /* Number of elements in the static TLS block.  */
  GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);

  /* Do not do this twice.  The audit interface might have required
     the DTV interfaces to be set up early.  */
  if (GL(dl_initial_dtv) != NULL)
    return NULL;

  /* Allocate the array which contains the information about the
     dtv slots.  We allocate a few entries more than needed to
     avoid the need for reallocation.  */
  size_t nelem = GL(dl_tls_max_dtv_idx) + 1 + TLS_SLOTINFO_SURPLUS;

  /* Allocate.  */
  GL(dl_tls_dtv_slotinfo_list) = (struct dtv_slotinfo_list *)
    calloc (sizeof (struct dtv_slotinfo_list)
           + nelem * sizeof (struct dtv_slotinfo), 1);
  /* No need to check the return value.  If memory allocation failed
     the program would have been terminated.  */

  struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
  GL(dl_tls_dtv_slotinfo_list)->len = nelem;
  GL(dl_tls_dtv_slotinfo_list)->next = NULL;

  /* Fill in the information from the loaded modules.  No namespace
     but the base one can be filled at this time.  */
  assert (GL(dl_ns)[LM_ID_BASE + 1]._ns_loaded == NULL);
  int i = 0;
  for (struct link_map *l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL;
       l = l->l_next)
    if (l->l_tls_blocksize != 0)
      {
       /* This is a module with TLS data.  Store the map reference.
          The generation counter is zero.  */
       slotinfo[i].map = l;
       /* slotinfo[i].gen = 0; */
       ++i;
      }
  assert (i == GL(dl_tls_max_dtv_idx));

  /* Compute the TLS offsets for the various blocks.  */
  _dl_determine_tlsoffset ();

  /* Construct the static TLS block and the dtv for the initial
     thread.  For some platforms this will include allocating memory
     for the thread descriptor.  The memory for the TLS block will
     never be freed.  It should be allocated accordingly.  The dtv
     array can be changed if dynamic loading requires it.  */
  void *tcbp = _dl_allocate_tls_storage ();
  if (tcbp == NULL)
    _dl_fatal_printf ("\
cannot allocate TLS data structures for initial thread");

  /* Store for detection of the special case by __tls_get_addr
     so it knows not to pass this dtv to the normal realloc.  */
  GL(dl_initial_dtv) = GET_DTV (tcbp);

  /* And finally install it for the main thread.  If ld.so itself uses
     TLS we know the thread pointer was initialized earlier.  */
  const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
  if (__builtin_expect (lossage != NULL, 0))
    _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
  tls_init_tp_called = true;

  return tcbp;
}

Here is the call graph for this function:

static void lookup_doit ( void *  a) [static]

Definition at line 638 of file rtld.c.

{
  struct lookup_args *args = (struct lookup_args *) a;
  const ElfW(Sym) *ref = NULL;
  args->result = NULL;
  lookup_t l = _dl_lookup_symbol_x (args->name, args->map, &ref,
                                args->map->l_local_scope, NULL, 0,
                                DL_LOOKUP_RETURN_NEWEST, NULL);
  if (ref != NULL)
    args->result = DL_SYMBOL_ADDRESS (l, ref);
}

Here is the call graph for this function:

static void map_doit ( void *  a) [static]

Definition at line 620 of file rtld.c.

{
  struct map_args *args = (struct map_args *) a;
  args->map = _dl_map_object (args->loader, args->str,
                           args->is_preloaded, lt_library, 0, args->mode,
                           LM_ID_BASE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int match_version ( const char *  string,
struct link_map map 
) [static]

Definition at line 676 of file rtld.c.

{
  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
  ElfW(Verdef) *def;

#define VERDEFTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERDEF))
  if (map->l_info[VERDEFTAG] == NULL)
    /* The file has no symbol versioning.  */
    return 0;

  def = (ElfW(Verdef) *) ((char *) map->l_addr
                       + map->l_info[VERDEFTAG]->d_un.d_ptr);
  while (1)
    {
      ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux);

      /* Compare the version strings.  */
      if (strcmp (string, strtab + aux->vda_name) == 0)
       /* Bingo!  */
       return 1;

      /* If no more definitions we failed to find what we want.  */
      if (def->vd_next == 0)
       break;

      /* Next definition.  */
      def = (ElfW(Verdef) *) ((char *) def + def->vd_next);
    }

  return 0;
}
static void print_missing_version ( int errcode   __attribute__(unused),
const char *  objname,
const char *  errstring 
) [static]

Definition at line 2353 of file rtld.c.

{
  _dl_error_printf ("%s: %s: %s\n", rtld_progname ?: "<program name unknown>",
                  objname, errstring);
}
static void print_unresolved ( int errcode   __attribute__(unused),
const char *  objname,
const char *  errstring 
) [static]

Definition at line 2342 of file rtld.c.

{
  if (objname[0] == '\0')
    objname = rtld_progname ?: "<main program>";
  _dl_error_printf ("%s     (%s)\n", errstring, objname);
}
static void process_dl_audit ( char *  str) [static]

Definition at line 2460 of file rtld.c.

{
  /* The parameter is a colon separated list of DSO names.  */
  char *p;

  while ((p = (strsep) (&str, ":")) != NULL)
    if (p[0] != '\0'
       && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
           || strchr (p, '/') == NULL))
      {
       /* This is using the local malloc, not the system malloc.  The
          memory can never be freed.  */
       struct audit_list *newp = malloc (sizeof (*newp));
       newp->name = p;

       if (audit_list == NULL)
         audit_list = newp->next = newp;
       else
         {
           newp->next = audit_list->next;
           audit_list = audit_list->next = newp;
         }
      }
}

Here is the caller graph for this function:

static void process_dl_debug ( const char *  dl_debug) [static]

Definition at line 2366 of file rtld.c.

{
  /* When adding new entries make sure that the maximal length of a name
     is correctly handled in the LD_DEBUG_HELP code below.  */
  static const struct
  {
    unsigned char len;
    const char name[10];
    const char helptext[41];
    unsigned short int mask;
  } debopts[] =
    {
#define LEN_AND_STR(str) sizeof (str) - 1, str
      { LEN_AND_STR ("libs"), "display library search paths",
       DL_DEBUG_LIBS | DL_DEBUG_IMPCALLS },
      { LEN_AND_STR ("reloc"), "display relocation processing",
       DL_DEBUG_RELOC | DL_DEBUG_IMPCALLS },
      { LEN_AND_STR ("files"), "display progress for input file",
       DL_DEBUG_FILES | DL_DEBUG_IMPCALLS },
      { LEN_AND_STR ("symbols"), "display symbol table processing",
       DL_DEBUG_SYMBOLS | DL_DEBUG_IMPCALLS },
      { LEN_AND_STR ("bindings"), "display information about symbol binding",
       DL_DEBUG_BINDINGS | DL_DEBUG_IMPCALLS },
      { LEN_AND_STR ("versions"), "display version dependencies",
       DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
      { LEN_AND_STR ("all"), "all previous options combined",
       DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS
       | DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
      { LEN_AND_STR ("statistics"), "display relocation statistics",
       DL_DEBUG_STATISTICS },
      { LEN_AND_STR ("unused"), "determined unused DSOs",
       DL_DEBUG_UNUSED },
      { LEN_AND_STR ("help"), "display this help message and exit",
       DL_DEBUG_HELP },
    };
#define ndebopts (sizeof (debopts) / sizeof (debopts[0]))

  /* Skip separating white spaces and commas.  */
  while (*dl_debug != '\0')
    {
      if (*dl_debug != ' ' && *dl_debug != ',' && *dl_debug != ':')
       {
         size_t cnt;
         size_t len = 1;

         while (dl_debug[len] != '\0' && dl_debug[len] != ' '
               && dl_debug[len] != ',' && dl_debug[len] != ':')
           ++len;

         for (cnt = 0; cnt < ndebopts; ++cnt)
           if (debopts[cnt].len == len
              && memcmp (dl_debug, debopts[cnt].name, len) == 0)
             {
              GLRO(dl_debug_mask) |= debopts[cnt].mask;
              any_debug = 1;
              break;
             }

         if (cnt == ndebopts)
           {
             /* Display a warning and skip everything until next
               separator.  */
             char *copy = strndupa (dl_debug, len);
             _dl_error_printf ("\
warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy);
           }

         dl_debug += len;
         continue;
       }

      ++dl_debug;
    }

  if (GLRO(dl_debug_mask) & DL_DEBUG_HELP)
    {
      size_t cnt;

      _dl_printf ("\
Valid options for the LD_DEBUG environment variable are:\n\n");

      for (cnt = 0; cnt < ndebopts; ++cnt)
       _dl_printf ("  %.*s%s%s\n", debopts[cnt].len, debopts[cnt].name,
                  "         " + debopts[cnt].len - 3,
                  debopts[cnt].helptext);

      _dl_printf ("\n\
To direct the debugging output into a file instead of standard output\n\
a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
      _exit (0);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_envvars ( enum mode modep) [static]

Definition at line 2492 of file rtld.c.

{
  char **runp = _environ;
  char *envline;
  enum mode mode = normal;
  char *debug_output = NULL;

  /* This is the default place for profiling data file.  */
  GLRO(dl_profile_output)
    = &"/var/tmp\0/var/profile"[INTUSE(__libc_enable_secure) ? 9 : 0];

  while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)
    {
      size_t len = 0;

      while (envline[len] != '\0' && envline[len] != '=')
       ++len;

      if (envline[len] != '=')
       /* This is a "LD_" variable at the end of the string without
          a '=' character.  Ignore it since otherwise we will access
          invalid memory below.  */
       continue;

      switch (len)
       {
       case 4:
         /* Warning level, verbose or not.  */
         if (memcmp (envline, "WARN", 4) == 0)
           GLRO(dl_verbose) = envline[5] != '\0';
         break;

       case 5:
         /* Debugging of the dynamic linker?  */
         if (memcmp (envline, "DEBUG", 5) == 0)
           {
             process_dl_debug (&envline[6]);
             break;
           }
         if (memcmp (envline, "AUDIT", 5) == 0)
           process_dl_audit (&envline[6]);
         break;

       case 7:
         /* Print information about versions.  */
         if (memcmp (envline, "VERBOSE", 7) == 0)
           {
             version_info = envline[8] != '\0';
             break;
           }

         /* List of objects to be preloaded.  */
         if (memcmp (envline, "PRELOAD", 7) == 0)
           {
             preloadlist = &envline[8];
             break;
           }

         /* Which shared object shall be profiled.  */
         if (memcmp (envline, "PROFILE", 7) == 0 && envline[8] != '\0')
           GLRO(dl_profile) = &envline[8];
         break;

       case 8:
         /* Do we bind early?  */
         if (memcmp (envline, "BIND_NOW", 8) == 0)
           {
             GLRO(dl_lazy) = envline[9] == '\0';
             break;
           }
         if (memcmp (envline, "BIND_NOT", 8) == 0)
           GLRO(dl_bind_not) = envline[9] != '\0';
         break;

       case 9:
         /* Test whether we want to see the content of the auxiliary
            array passed up from the kernel.  */
         if (!INTUSE(__libc_enable_secure)
             && memcmp (envline, "SHOW_AUXV", 9) == 0)
           _dl_show_auxv ();
         break;

       case 10:
         /* Mask for the important hardware capabilities.  */
         if (memcmp (envline, "HWCAP_MASK", 10) == 0)
           GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL,
                                                0, 0);
         break;

       case 11:
         /* Path where the binary is found.  */
         if (!INTUSE(__libc_enable_secure)
             && memcmp (envline, "ORIGIN_PATH", 11) == 0)
           GLRO(dl_origin_path) = &envline[12];
         break;

       case 12:
         /* The library search path.  */
         if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
           {
             library_path = &envline[13];
             break;
           }

         /* Where to place the profiling data file.  */
         if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0)
           {
             debug_output = &envline[13];
             break;
           }

         if (!INTUSE(__libc_enable_secure)
             && memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
           GLRO(dl_dynamic_weak) = 1;
         break;

       case 13:
         /* We might have some extra environment variable with length 13
            to handle.  */
#ifdef EXTRA_LD_ENVVARS_13
         EXTRA_LD_ENVVARS_13
#endif
         if (!INTUSE(__libc_enable_secure)
             && memcmp (envline, "USE_LOAD_BIAS", 13) == 0)
           {
             GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
             break;
           }

         if (memcmp (envline, "POINTER_GUARD", 13) == 0)
           GLRO(dl_pointer_guard) = envline[14] != '0';
         break;

       case 14:
         /* Where to place the profiling data file.  */
         if (!INTUSE(__libc_enable_secure)
             && memcmp (envline, "PROFILE_OUTPUT", 14) == 0
             && envline[15] != '\0')
           GLRO(dl_profile_output) = &envline[15];
         break;

       case 16:
         /* The mode of the dynamic linker can be set.  */
         if (memcmp (envline, "TRACE_PRELINKING", 16) == 0)
           {
             mode = trace;
             GLRO(dl_verbose) = 1;
             GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
             GLRO(dl_trace_prelink) = &envline[17];
           }
         break;

       case 20:
         /* The mode of the dynamic linker can be set.  */
         if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
           mode = trace;
         break;

         /* We might have some extra environment variable to handle.  This
            is tricky due to the pre-processing of the length of the name
            in the switch statement here.  The code here assumes that added
            environment variables have a different length.  */
#ifdef EXTRA_LD_ENVVARS
         EXTRA_LD_ENVVARS
#endif
       }
    }

  /* The caller wants this information.  */
  *modep = mode;

  /* Extra security for SUID binaries.  Remove all dangerous environment
     variables.  */
  if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
    {
      static const char unsecure_envvars[] =
#ifdef EXTRA_UNSECURE_ENVVARS
       EXTRA_UNSECURE_ENVVARS
#endif
       UNSECURE_ENVVARS;
      const char *nextp;

      nextp = unsecure_envvars;
      do
       {
         unsetenv (nextp);
         /* We could use rawmemchr but this need not be fast.  */
         nextp = (char *) (strchr) (nextp, '\0') + 1;
       }
      while (*nextp != '\0');

      if (__access ("/etc/suid-debug", F_OK) != 0)
        {
         unsetenv ("MALLOC_CHECK_");
         GLRO(dl_debug_mask) = 0;
        }

      if (mode != normal)
       _exit (5);
    }
  /* If we have to run the dynamic linker in debugging mode and the
     LD_DEBUG_OUTPUT environment variable is given, we write the debug
     messages to this file.  */
  else if (any_debug && debug_output != NULL)
    {
#ifdef O_NOFOLLOW
      const int flags = O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW;
#else
      const int flags = O_WRONLY | O_APPEND | O_CREAT;
#endif
      size_t name_len = strlen (debug_output);
      char buf[name_len + 12];
      char *startp;

      buf[name_len + 11] = '\0';
      startp = _itoa (__getpid (), &buf[name_len + 11], 10, 0);
      *--startp = '.';
      startp = memcpy (startp - name_len, debug_output, name_len);

      GLRO(dl_debug_fd) = __open (startp, flags, DEFFILEMODE);
      if (GLRO(dl_debug_fd) == -1)
       /* We use standard output if opening the file failed.  */
       GLRO(dl_debug_fd) = STDOUT_FILENO;
    }
}

Here is the call graph for this function:

static void relocate_doit ( void *  a) [static]

Definition at line 612 of file rtld.c.

{
  struct relocate_args *args = (struct relocate_args *) a;

  _dl_relocate_object (args->l, args->l->l_scope, args->lazy, 0);
}

Here is the call graph for this function:

static void security_init ( void  ) [static]

Definition at line 841 of file rtld.c.

{
  /* Set up the stack checker's canary.  */
  uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
#ifdef THREAD_SET_STACK_GUARD
  THREAD_SET_STACK_GUARD (stack_chk_guard);
#else
  __stack_chk_guard = stack_chk_guard;
#endif

  /* Set up the pointer guard as well, if necessary.  */
  if (GLRO(dl_pointer_guard))
    {
      // XXX If it is cheap, we should use a separate value.
      uintptr_t pointer_chk_guard = stack_chk_guard;
#ifndef HP_TIMING_NONAVAIL
      hp_timing_t now;
      HP_TIMING_NOW (now);
      pointer_chk_guard ^= now;
#endif
#ifdef THREAD_SET_POINTER_GUARD
      THREAD_SET_POINTER_GUARD (pointer_chk_guard);
#endif
      __pointer_chk_guard_local = pointer_chk_guard;
    }
}
strong_alias ( __pointer_chk_guard_local  ,
__pointer_chk_guard   
)

Definition at line 98 of file rtld.c.

{
  const char *name;
  struct audit_list *next;
} *audit_list;
static void version_check_doit ( void *  a) [static]

Definition at line 651 of file rtld.c.

{
  struct version_check_args *args = (struct version_check_args *) a;
  if (_dl_check_all_versions (GL(dl_ns)[LM_ID_BASE]._ns_loaded, 1,
                           args->dotrace) && args->doexit)
    /* We cannot start the application.  Abort now.  */
    _exit (1);
}

Here is the call graph for this function:


Variable Documentation

Definition at line 117 of file rtld.c.

Definition at line 81 of file rtld.c.

int any_debug attribute_relro = NULL

Definition at line 82 of file rtld.c.

Definition at line 107 of file rtld.c.

static struct libname_list [static]

Definition at line 182 of file rtld.c.

Definition at line 193 of file rtld.c.

bool tls_init_tp_called [static]

Definition at line 708 of file rtld.c.