(linenum→info "unix/slp.c:2238")

glibc/2.7/elf/dl-object.c

    1: /* Storage management for the chain of loaded shared objects.
    2:    Copyright (C) 1995-2002, 2004, 2006, 2007 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <errno.h>
   21: #include <string.h>
   22: #include <stdlib.h>
   23: #include <unistd.h>
   24: #include <ldsodefs.h>
   25: 
   26: #include <assert.h>
   27: 
   28: 
   29: /* Allocate a `struct link_map' for a new object being loaded,
   30:    and enter it into the _dl_loaded list.  */
   31: 
   32: struct link_map *
   33: internal_function
   34: _dl_new_object (char *realname, const char *libname, int type,
   35:                 struct link_map *loader, int mode, Lmid_t nsid)
   36: {
   37:   struct link_map *l;
   38:   int idx;
   39:   size_t libname_len = strlen (libname) + 1;
   40:   struct link_map *new;
   41:   struct libname_list *newname;
   42: #ifdef SHARED
   43:   /* We create the map for the executable before we know whether we have
   44:      auditing libraries and if yes, how many.  Assume the worst.  */
   45:   unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC)
   46:                                             ? DL_NNS : 0);
   47:   size_t audit_space = naudit * sizeof (new->l_audit[0]);
   48: #else
   49: # define audit_space 0
   50: #endif
   51: 
   52:   new = (struct link_map *) calloc (sizeof (*new) + audit_space
   53:                                     + sizeof (*newname) + libname_len, 1);
   54:   if (new == NULL)
   55:     return NULL;
   56: 
   57:   new->l_real = new;
   58:   new->l_libname = newname = (struct libname_list *) ((char *) (new + 1)
   59:                                                       + audit_space);
   60:   newname->name = (char *) memcpy (newname + 1, libname, libname_len);
   61:   /* newname->next = NULL;      We use calloc therefore not necessary.  */
   62:   newname->dont_free = 1;
   63: 
   64:   new->l_name = realname;
   65:   new->l_type = type;
   66:   new->l_loader = loader;
   67: #if NO_TLS_OFFSET != 0
   68:   new->l_tls_offset = NO_TLS_OFFSET;
   69: #endif
   70:   new->l_ns = nsid;
   71: 
   72: #ifdef SHARED
   73:   for (unsigned int cnt = 0; cnt < naudit; ++cnt)
   74:     {
   75:       new->l_audit[cnt].cookie = (uintptr_t) new;
   76:       /* new->l_audit[cnt].bindflags = 0; */
   77:     }
   78: #endif
   79: 
   80:   /* new->l_global = 0; We use calloc therefore not necessary.  */
   81: 
   82:   /* Use the 'l_scope_mem' array by default for the the 'l_scope'
   83:      information.  If we need more entries we will allocate a large
   84:      array dynamically.  */
   85:   new->l_scope = new->l_scope_mem;
   86:   new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
   87: 
   88:   /* Counter for the scopes we have to handle.  */
   89:   idx = 0;
   90: 
   91:   if (GL(dl_ns)[nsid]._ns_loaded != NULL)
   92:     {
   93:       l = GL(dl_ns)[nsid]._ns_loaded;
   94:       while (l->l_next != NULL)
   95:         l = l->l_next;
   96:       new->l_prev = l;
   97:       /* new->l_next = NULL;    Would be necessary but we use calloc.  */
   98:       l->l_next = new;
   99: 
  100:       /* Add the global scope.  */
  101:       new->l_scope[idx++] = &GL(dl_ns)[nsid]._ns_loaded->l_searchlist;
  102:     }
  103:   else
  104:     GL(dl_ns)[nsid]._ns_loaded = new;
  105:   ++GL(dl_ns)[nsid]._ns_nloaded;
  106:   new->l_serial = GL(dl_load_adds);
  107:   ++GL(dl_load_adds);
  108: 
  109:   /* If we have no loader the new object acts as it.  */
  110:   if (loader == NULL)
  111:     loader = new;
  112:   else
  113:     /* Determine the local scope.  */
  114:     while (loader->l_loader != NULL)
  115:       loader = loader->l_loader;
  116: 
  117:   /* Insert the scope if it isn't the global scope we already added.  */
  118:   if (idx == 0 || &loader->l_searchlist != new->l_scope[0])
  119:     {
  120:       if ((mode & RTLD_DEEPBIND) != 0 && idx != 0)
  121:         {
  122:           new->l_scope[1] = new->l_scope[0];
  123:           idx = 0;
  124:         }
  125: 
  126:       new->l_scope[idx] = &loader->l_searchlist;
  127:     }
  128: 
  129:   new->l_local_scope[0] = &new->l_searchlist;
  130: 
  131:   /* Don't try to find the origin for the main map which has the name "".  */
  132:   if (realname[0] != '\0')
  133:     {
  134:       size_t realname_len = strlen (realname) + 1;
  135:       char *origin;
  136:       char *cp;
  137: 
  138:       if (realname[0] == '/')
  139:         {
  140:           /* It is an absolute path.  Use it.  But we have to make a
  141:              copy since we strip out the trailing slash.  */
  142:           cp = origin = (char *) malloc (realname_len);
  143:           if (origin == NULL)
  144:             {
  145:               origin = (char *) -1;
  146:               goto out;
  147:             }
  148:         }
  149:       else
  150:         {
  151:           size_t len = realname_len;
  152:           char *result = NULL;
  153: 
  154:           /* Get the current directory name.  */
  155:           origin = NULL;
  156:           do
  157:             {
  158:               char *new_origin;
  159: 
  160:               len += 128;
  161:               new_origin = (char *) realloc (origin, len);
  162:               if (new_origin == NULL)
  163:                 /* We exit the loop.  Note that result == NULL.  */
  164:                 break;
  165:               origin = new_origin;
  166:             }
  167:           while ((result = __getcwd (origin, len - realname_len)) == NULL
  168:                  && errno == ERANGE);
  169: 
  170:           if (result == NULL)
  171:             {
  172:               /* We were not able to determine the current directory.
  173:                  Note that free(origin) is OK if origin == NULL.  */
  174:               free (origin);
  175:               origin = (char *) -1;
  176:               goto out;
  177:             }
  178: 
  179:           /* Find the end of the path and see whether we have to add a
  180:              slash.  We could use rawmemchr but this need not be
  181:              fast.  */
  182:           cp = (strchr) (origin, '\0');
  183:           if (cp[-1] != '/')
  184:             *cp++ = '/';
  185:         }
  186: 
  187:       /* Add the real file name.  */
  188:       cp = __mempcpy (cp, realname, realname_len);
  189: 
  190:       /* Now remove the filename and the slash.  Leave the slash if
  191:          the name is something like "/foo".  */
  192:       do
  193:         --cp;
  194:       while (*cp != '/');
  195: 
  196:       if (cp == origin)
  197:         /* Keep the only slash which is the first character.  */
  198:         ++cp;
  199:       *cp = '\0';
  200: 
  201:     out:
  202:       new->l_origin = origin;
  203:     }
  204: 
  205:   return new;
  206: }
Syntax (Markdown)