]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Update.
authorUlrich Drepper <drepper@redhat.com>
Wed, 5 May 1999 23:29:18 +0000 (23:29 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 5 May 1999 23:29:18 +0000 (23:29 +0000)
* Versions.def (ld.so): Add GLIBC_2.1.1.
* elf/Makefile (routines): Add dl-origin.
(tests): Add origtest.  Add dependencies for the program.
* elf/Versions (ld.so) [GLIBC_2.1.1]: Add _dl_origin_path,
_dl_platformlen, _dl_dst_count and _dl_dst_substitute.
* elf/dl-deps.c (expand_dst): New macro.  Expand DSTs in filename.
(_dl_map_object_deps): Use expand_dst to expand DSTs in DT_NEEDED,
DT_AUXILIARY, and DT_FILTER filenames.
* elf/dl-load.c (expand_dynamic_string_token): Explode into
two functions and three macros.
(_dl_dst_count, _dl_dst_substitute): New functions.
* elf/dl-dst.h: New file.
* elf/dl-open.c (_dl_open): Take extra parameter with address of
caller.  Pass address in args structure.
(dl_open_worker): Recognize and expand DSTs in filename.
* elf/ldsodefs.h (_dl_open): Adapt prototype.
* elf/dlopen.c (dlopen_doit): Pass caller address to _dl_open.
(__dlopen_check): Pass caller address to dlopen_doit in args.
* elf/dlopendoit.c: Likewise.
* iconv/gconv_dl.c: Adapt call of _dl_open.
* nss/nsswitch.c: Likewise.
* elf/origtest.c: New file.
* sysdeps/generic/dl-origin.h: Moved to...
* sysdeps/generic/dl-origin.c: ...here.
* sysdeps/unix/sysv/linux/dl-origin.h: Moved to...
* sysdeps/unix/sysv/linux/dl-origin.c: ...here.

16 files changed:
ChangeLog
Versions.def
elf/Makefile
elf/Versions
elf/dl-deps.c
elf/dl-dst.h [new file with mode: 0644]
elf/dl-load.c
elf/dl-open.c
elf/dlopen.c
elf/dlopenold.c
elf/ldsodefs.h
elf/origtest.c [new file with mode: 0644]
iconv/gconv_dl.c
nss/nsswitch.c
sysdeps/generic/dl-origin.c [moved from sysdeps/generic/dl-origin.h with 88% similarity]
sysdeps/unix/sysv/linux/dl-origin.c [moved from sysdeps/unix/sysv/linux/dl-origin.h with 90% similarity]

index c82015c40687aa7ed968c8769caf0a7400e377e8..3a5767f0f63686187356baf1bf0ae3b3458fde8d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,32 @@
 1999-05-05  Ulrich Drepper  <drepper@cygnus.com>
 
+       * Versions.def (ld.so): Add GLIBC_2.1.1.
+       * elf/Makefile (routines): Add dl-origin.
+       (tests): Add origtest.  Add dependencies for the program.
+       * elf/Versions (ld.so) [GLIBC_2.1.1]: Add _dl_origin_path,
+       _dl_platformlen, _dl_dst_count and _dl_dst_substitute.
+       * elf/dl-deps.c (expand_dst): New macro.  Expand DSTs in filename.
+       (_dl_map_object_deps): Use expand_dst to expand DSTs in DT_NEEDED,
+       DT_AUXILIARY, and DT_FILTER filenames.
+       * elf/dl-load.c (expand_dynamic_string_token): Explode into
+       two functions and three macros.
+       (_dl_dst_count, _dl_dst_substitute): New functions.
+       * elf/dl-dst.h: New file.
+       * elf/dl-open.c (_dl_open): Take extra parameter with address of
+       caller.  Pass address in args structure.
+       (dl_open_worker): Recognize and expand DSTs in filename.
+       * elf/ldsodefs.h (_dl_open): Adapt prototype.
+       * elf/dlopen.c (dlopen_doit): Pass caller address to _dl_open.
+       (__dlopen_check): Pass caller address to dlopen_doit in args.
+       * elf/dlopendoit.c: Likewise.
+       * iconv/gconv_dl.c: Adapt call of _dl_open.
+       * nss/nsswitch.c: Likewise.
+       * elf/origtest.c: New file.
+       * sysdeps/generic/dl-origin.h: Moved to...
+       * sysdeps/generic/dl-origin.c: ...here.
+       * sysdeps/unix/sysv/linux/dl-origin.h: Moved to...
+       * sysdeps/unix/sysv/linux/dl-origin.c: ...here.
+
        * stdio-common/_itoa.c (_itoa): Fix special 32bit platform case
        with specific bases and only few bits set in second word.
 
index 3cfd493f2a72b64bb5e6b7897851b98ce5ad8bd1..a0ed3b4c660bb2d7a1846f517507ee4dd6714b64 100644 (file)
@@ -72,4 +72,5 @@ libdb1 {
 ld.so {
   GLIBC_2.0
   GLIBC_2.1 GLIBC_2.0
+  GLIBC_2.1.1 GLIBC_2.1
 }
index 26a08322df206358286cc595f16847fe7f9e47fc..d6c37c2bb807336d24654b69a268412e0036d7b5 100644 (file)
@@ -22,7 +22,7 @@ subdir                := elf
 
 headers                = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h
 routines       = $(dl-routines) dl-open dl-close dl-symbol dl-support \
-                 dl-addr enbl-secure dl-profstub
+                 dl-addr enbl-secure dl-profstub dl-origin
 
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
@@ -78,7 +78,7 @@ install-rootsbin += ldconfig
 endif
 
 ifeq (yes,$(build-shared))
-tests = loadtest restest1 preloadtest loadfail multiload
+tests = loadtest restest1 preloadtest loadfail multiload origtest
 endif
 modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
                testobj1_1 failobj
@@ -253,6 +253,9 @@ LDFLAGS-multiload = -rdynamic
 CFLAGS-multiload.c = -DOBJDIR=\"$(elf-objpfx)\"
 
 $(objpfx)multiload.out: $(objpfx)testobj1.so
+
+$(objpfx)origtest: $(libdl)
+$(objpfx)origtest.out: $(objpfx)testobj1.so
 \f
 # muwahaha
 
index 8e6dca878bd87b0a39d0dcb75c46991a6ed44535..e26e096469291bf70030fc84139d7f31a5d46d8c 100644 (file)
@@ -37,6 +37,13 @@ ld.so {
     # functions used in other libraries
     _dl_mcount; _dl_unload_cache;
   }
+  GLIBC_2.1.1 {
+    # global variables
+    _dl_origin_path; _dl_platformlen;
+
+    # functions used in other libraries
+    _dl_dst_count; _dl_dst_substitute;
+  }
 }
 
 libdl {
index 7291cde78792a9a4266b4bef6c56603cbc51f85e..56f91f6dd06d946c3257cabfdea0658b582cb3d2 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <assert.h>
 #include <dlfcn.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/param.h>
 #include <elf/ldsodefs.h>
 
-#include <assert.h>
+#include <dl-dst.h>
 
 /* Whether an shared object references one or more auxiliary objects
    is signaled by the AUXTAG entry in l_info.  */
@@ -39,6 +41,7 @@
    reset if in _dl_close if the last global object is removed.  */
 size_t _dl_global_scope_alloc;
 
+extern size_t _dl_platformlen;
 
 /* When loading auxiliary objects we must ignore errors.  It's ok if
    an object is missing.  */
@@ -48,7 +51,7 @@ struct openaux_args
     struct link_map *map;
     int trace_mode;
     const char *strtab;
-    const ElfW(Dyn) *d;
+    const char *name;
 
     /* The return value of openaux.  */
     struct link_map *aux;
@@ -59,7 +62,7 @@ openaux (void *a)
 {
   struct openaux_args *args = (struct openaux_args *) a;
 
-  args->aux = _dl_map_object (args->map, args->strtab + args->d->d_un.d_val, 0,
+  args->aux = _dl_map_object (args->map, args->name, 0,
                              (args->map->l_type == lt_executable
                               ? lt_library : args->map->l_type),
                              args->trace_mode);
@@ -84,6 +87,43 @@ struct list
   };
 
 
+/* Macro to expand DST.  It is an macro since we use `alloca'.  */
+#define expand_dst(l, str, fatal) \
+  ({                                                                         \
+    const char *__str = (str);                                               \
+    const char *__result = __str;                                            \
+    size_t __cnt = DL_DST_COUNT(__str, 0);                                   \
+                                                                             \
+    if (__cnt != 0)                                                          \
+      {                                                                              \
+       char *__newp = (char *) alloca (DL_DST_REQUIRED (l, __str,            \
+                                                        strlen (__str),      \
+                                                        __cnt));             \
+                                                                             \
+       __result = DL_DST_SUBSTITUTE (l, __str, __newp, 0);                   \
+                                                                             \
+       if (*__result == '\0')                                                \
+         {                                                                   \
+           /* The replacement for the DST is not known.  We can't            \
+              processed.  */                                                 \
+           if (fatal)                                                        \
+             _dl_signal_error (0, __str,                                     \
+                               "empty dynamics string token substitution");  \
+           else                                                              \
+             {                                                               \
+               /* This is for DT_AUXILIARY.  */                              \
+               if (_dl_debug_libs)                                           \
+                 _dl_debug_message (1, "cannot load auxiliary `", __str,     \
+                                    "' because of empty dynamic string"      \
+                                    " token substitution\n", NULL);          \
+               continue;                                                     \
+             }                                                               \
+         }                                                                   \
+      }                                                                              \
+                                                                             \
+    __result; })
+
+
 unsigned int
 internal_function
 _dl_map_object_deps (struct link_map *map,
@@ -166,14 +206,21 @@ _dl_map_object_deps (struct link_map *map,
            if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
              {
                /* Map in the needed object.  */
-               struct link_map *dep
-                 = _dl_map_object (l, strtab + d->d_un.d_val, 0,
-                                   l->l_type == lt_executable ? lt_library :
-                                   l->l_type, trace_mode);
+               struct link_map *dep;
                /* Allocate new entry.  */
-               struct list *newp = alloca (sizeof (struct list));
+               struct list *newp;
+               /* Object name.  */
+               const char *name;
+
+               /* Recognize DSTs.  */
+               name = expand_dst (l, strtab + d->d_un.d_val, 0);
+
+               dep = _dl_map_object (l, name, 0,
+                                     l->l_type == lt_executable ? lt_library :
+                                     l->l_type, trace_mode);
 
                /* Add it in any case to the duplicate list.  */
+               newp = alloca (sizeof (struct list));
                newp->map = dep;
                newp->dup = NULL;
                dtail->dup = newp;
@@ -202,17 +249,22 @@ _dl_map_object_deps (struct link_map *map,
              {
                char *errstring;
                struct list *newp;
+               /* Object name.  */
+               const char *name;
+
+               /* Recognize DSTs.  */
+               name = expand_dst (l, strtab + d->d_un.d_val,
+                                  d->d_tag == DT_AUXILIARY);
 
                if (d->d_tag == DT_AUXILIARY)
                  {
                    /* Store the tag in the argument structure.  */
-                   args.d = d;
+                   args.name = name;
 
                    /* Say that we are about to load an auxiliary library.  */
                    if (_dl_debug_libs)
                      _dl_debug_message (1, "load auxiliary object=",
-                                        strtab + d->d_un.d_val,
-                                        " requested by file=",
+                                        name, " requested by file=",
                                         l->l_name[0]
                                         ? l->l_name : _dl_argv[0],
                                         "\n", NULL);
@@ -233,15 +285,14 @@ _dl_map_object_deps (struct link_map *map,
                  {
                    /* Say that we are about to load an auxiliary library.  */
                    if (_dl_debug_libs)
-                     _dl_debug_message (1, "load filtered object=",
-                                        strtab + d->d_un.d_val,
+                     _dl_debug_message (1, "load filtered object=", name,
                                         " requested by file=",
                                         l->l_name[0]
                                         ? l->l_name : _dl_argv[0],
                                         "\n", NULL);
 
                    /* For filter objects the dependency must be available.  */
-                   args.aux = _dl_map_object (l, strtab + d->d_un.d_val, 0,
+                   args.aux = _dl_map_object (l, name, 0,
                                               (l->l_type == lt_executable
                                                ? lt_library : l->l_type),
                                               trace_mode);
diff --git a/elf/dl-dst.h b/elf/dl-dst.h
new file mode 100644 (file)
index 0000000..4b014d6
--- /dev/null
@@ -0,0 +1,72 @@
+/* Handling of dynamic sring tokens.
+   Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Determine the number of DST elements in the name.  Only if IS_PATH is
+   nonzero paths are recognized (i.e., multiple, ':' separated filenames).  */
+#define DL_DST_COUNT(name, is_path) \
+  ({                                                                         \
+    size_t __cnt = 0;                                                        \
+    const char *__sf = strchr (name, '$');                                   \
+                                                                             \
+    if (__sf != NULL)                                                        \
+      __cnt = _dl_dst_count (__sf, is_path);                                 \
+                                                                             \
+    __cnt; })
+
+/* Prototype for used function.  */
+extern size_t _dl_dst_count (const char *name, int is_path);
+
+
+/* Guess from the number of DSTs the length of the restul string.  */
+#define DL_DST_REQUIRED(l, name, len, cnt) \
+  ({                                                                         \
+    size_t origin_len;                                                       \
+    size_t __len = (len);                                                    \
+                                                                             \
+    /* Now we make a guess how many extra characters on top of the length     \
+       of S we need to represent the result.  We know that we have CNT       \
+       replacements.  Each at most can use                                   \
+         MAX (strlen (ORIGIN), strlen (_dl_platform))                        \
+       minus 7 (which is the length of "$ORIGIN").                           \
+                                                                             \
+       First get the origin string if it is not available yet.  This can      \
+       only happen for the map of the executable.  */                        \
+    if ((l)->l_origin == NULL)                                               \
+      {                                                                              \
+       assert ((l)->l_name[0] == '\0');                                      \
+       (l)->l_origin = _dl_get_origin ();                                    \
+       origin_len = ((l)->l_origin && (l)->l_origin != (char *) -1           \
+                     ? strlen ((l)->l_origin) : 0);                          \
+      }                                                                              \
+    else                                                                     \
+      origin_len = (l)->l_origin == (char *) -1 ? 0 : strlen ((l)->l_origin); \
+                                                                             \
+    __len + cnt * (MAX (origin_len, _dl_platformlen) - 7); })
+
+/* Find origin of the executable.  */
+extern const char *_dl_get_origin (void);
+
+
+/* Perform the DST substitution.  */
+#define DL_DST_SUBSTITUTE(l, name, res, is_path) \
+  _dl_dst_substitute (l, name, res, is_path)
+
+/* Prototype for used function.  */
+extern char *_dl_dst_substitute (struct link_map *l, const char *name,
+                                char *result, int is_path);
index 46f0b67567ef5099256f44c8666d69af55c8d999..6e8b977195f65bc4e7e829856daaf6b6823ca924 100644 (file)
@@ -31,8 +31,7 @@
 #include "dynamic-link.h"
 #include <stdio-common/_itoa.h>
 
-#include <dl-origin.h>
-
+#include <dl-dst.h>
 
 /* On some systems, no flag bits are given to specify file mapping.  */
 #ifndef MAP_FILE
@@ -146,129 +145,139 @@ local_strdup (const char *s)
   return (char *) memcpy (new, s, len);
 }
 
-/* Return copy of argument with all recognized dynamic string tokens
-   ($ORIGIN and $PLATFORM for now) replaced.  On some platforms it
-   might not be possible to determine the path from which the object
-   belonging to the map is loaded.  In this case the path element
-   containing $ORIGIN is left out.  */
-static char *
-expand_dynamic_string_token (struct link_map *l, const char *s)
+
+size_t
+_dl_dst_count (const char *name, int is_path)
 {
-  /* We make two runs over the string.  First we determine how large the
-     resulting string is and then we copy it over.  Since this is now
-     frequently executed operation we are looking here not for performance
-     but rather for code size.  */
-  const char *sf;
   size_t cnt = 0;
-  size_t origin_len;
-  size_t total;
-  char *result, *last_elem, *wp;
 
-  sf = strchr (s, '$');
-  while (sf != NULL)
+  do
     {
       size_t len = 1;
 
       /* $ORIGIN is not expanded for SUID/GUID programs.  */
       if ((((!__libc_enable_secure
-            && strncmp (&sf[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
-           || (strncmp (&sf[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
-          && (s[len] == '\0' || s[len] == '/' || s[len] == ':'))
-         || (s[1] == '{'
+            && strncmp (&name[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
+           || (strncmp (&name[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
+          && (name[len] == '\0' || name[len] == '/'
+              || (is_path && name[len] == ':')))
+         || (name[1] == '{'
              && ((!__libc_enable_secure
-                  && strncmp (&sf[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
-                 || (strncmp (&sf[2], "PLATFORM}", 9) == 0
+                  && strncmp (&name[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
+                 || (strncmp (&name[2], "PLATFORM}", 9) == 0
                      && (len = 11) != 0))))
        ++cnt;
 
-      sf = strchr (sf + len, '$');
+      name = strchr (name + len, '$');
     }
+  while (name != NULL);
 
-  /* If we do not have to replace anything simply copy the string.  */
-  if (cnt == 0)
-    return local_strdup (s);
-
-  /* Now we make a guess how many extra characters on top of the length
-     of S we need to represent the result.  We know that we have CNT
-     replacements.  Each at most can use
-       MAX (strlen (ORIGIN), strlen (_dl_platform))
-     minus 7 (which is the length of "$ORIGIN").
+  return cnt;
+}
 
-     First get the origin string if it is not available yet.  This can
-     only happen for the map of the executable.  */
-  if (l->l_origin == NULL)
-    {
-      assert (l->l_name[0] == '\0');
-      l->l_origin = get_origin ();
-      origin_len = (l->l_origin && l->l_origin != (char *) -1
-                   ? strlen (l->l_origin) : 0);
-    }
-  else
-    origin_len = l->l_origin == (char *) -1 ? 0 : strlen (l->l_origin);
 
-  total = strlen (s) + cnt * (MAX (origin_len, _dl_platformlen) - 7);
-  result = (char *) malloc (total + 1);
-  if (result == NULL)
-    return NULL;
+char *
+_dl_dst_substitute (struct link_map *l, const char *name, char *result,
+                   int is_path)
+{
+  char *last_elem, *wp;
 
   /* Now fill the result path.  While copying over the string we keep
      track of the start of the last path element.  When we come accross
      a DST we copy over the value or (if the value is not available)
      leave the entire path element out.  */
   last_elem = wp = result;
+
   do
     {
-      if (*s == '$')
+      if (*name == '$')
        {
          const char *repl;
          size_t len;
 
-         if ((((strncmp (&s[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
-               || (strncmp (&s[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
-              && (s[len] == '\0' || s[len] == '/' || s[len] == ':'))
-             || (s[1] == '{'
-                 && ((strncmp (&s[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
-                     || (strncmp (&s[2], "PLATFORM}", 9) == 0
+         if ((((strncmp (&name[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
+               || (strncmp (&name[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
+              && (name[len] == '\0' || name[len] == '/'
+                  || (is_path && name[len] == ':')))
+             || (name[1] == '{'
+                 && ((strncmp (&name[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
+                     || (strncmp (&name[2], "PLATFORM}", 9) == 0
                          && (len = 11) != 0))))
            {
-             repl = ((len == 7 || s[2] == 'O')
+             repl = ((len == 7 || name[2] == 'O')
                      ? (__libc_enable_secure ? NULL : l->l_origin)
                      : _dl_platform);
 
              if (repl != NULL && repl != (const char *) -1)
                {
                  wp = __stpcpy (wp, repl);
-                 s += len;
+                 name += len;
                }
              else
                {
                  /* We cannot use this path element, the value of the
                     replacement is unknown.  */
                  wp = last_elem;
-                 s += len;
-                 while (*s != '\0' && *s != ':')
-                   ++s;
+                 name += len;
+                 while (*name != '\0' && (!is_path || *name != ':'))
+                   ++name;
                }
            }
          else
            /* No DST we recognize.  */
-           *wp++ = *s++;
+           *wp++ = *name++;
        }
-      else if (*s == ':')
+      else if (is_path && *name == ':')
        {
-         *wp++ = *s++;
+         *wp++ = *name++;
          last_elem = wp;
        }
       else
-       *wp++ = *s++;
+       *wp++ = *name++;
     }
-  while (*s != '\0');
+  while (*name != '\0');
 
   *wp = '\0';
 
   return result;
 }
 
+
+/* Return copy of argument with all recognized dynamic string tokens
+   ($ORIGIN and $PLATFORM for now) replaced.  On some platforms it
+   might not be possible to determine the path from which the object
+   belonging to the map is loaded.  In this case the path element
+   containing $ORIGIN is left out.  */
+static char *
+expand_dynamic_string_token (struct link_map *l, const char *s)
+{
+  /* We make two runs over the string.  First we determine how large the
+     resulting string is and then we copy it over.  Since this is now
+     frequently executed operation we are looking here not for performance
+     but rather for code size.  */
+  size_t cnt;
+  size_t total;
+  char *result;
+
+  /* Determine the nubmer of DST elements.  */
+  cnt = DL_DST_COUNT (s, 1);
+
+  /* If we do not have to replace anything simply copy the string.  */
+  if (cnt == 0)
+    return local_strdup (s);
+
+  /* Determine the length of the substituted string.  */
+  total = DL_DST_REQUIRED (l, s, strlen (s), cnt);
+
+  /* Allocate the necessary memory.  */
+  result = (char *) malloc (total + 1);
+  if (result == NULL)
+    return NULL;
+
+  return DL_DST_SUBSTITUTE (l, s, result, 1);
+}
+
+
 /* Add `name' to the list of names for a particular shared object.
    `name' is expected to have been allocated with malloc and will
    be freed if the shared object already has this name.
index 2b3352b6743df1cef70346f8ce4299867abdd4be..9a3c0939d814af147ea634991905337ad8f4dd0c 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <assert.h>
 #include <dlfcn.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>          /* Check whether MAP_COPY is defined.  */
+#include <sys/param.h>
 #include <bits/libc-lock.h>
 #include <elf/ldsodefs.h>
 
+#include <dl-dst.h>
+
 
 extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
                                    void (*dl_main) (const ElfW(Phdr) *phdr,
@@ -57,6 +61,7 @@ static void show_scope (struct link_map *new);
    At this time it is not anymore a problem to modify the tables.  */
 __libc_lock_define_initialized_recursive (, _dl_load_lock)
 
+extern size_t _dl_platformlen;
 
 /* We must be carefull not to leave us in an inconsistent state.  Thus we
    catch any error and re-raise it after cleaning up.  */
@@ -65,6 +70,7 @@ struct dl_open_args
 {
   const char *file;
   int mode;
+  const void *caller;
   struct link_map *map;
 };
 
@@ -78,6 +84,50 @@ dl_open_worker (void *a)
   ElfW(Addr) init;
   struct r_debug *r;
   unsigned int global_add;
+  const char *dst;
+
+  /* Maybe we have to expand a DST.  */
+  dst = strchr (file, '$');
+  if (dst != NULL)
+    {
+      const void *caller = args->caller;
+      size_t len = strlen (file);
+      size_t required;
+      struct link_map *call_map;
+      char *new_file;
+
+      /* We have to find out from which object the caller is calling.
+        Find the highest-addressed object that ADDRESS is not below.  */
+      call_map = NULL;
+      for (l = _dl_loaded; l; l = l->l_next)
+       if (l->l_addr != 0 /* Make sure we do not currently set this map up
+                             in this moment.  */
+           && caller >= (const void *) l->l_addr
+           && (call_map == NULL || call_map->l_addr < l->l_addr))
+         call_map = l;
+
+      if (call_map == NULL)
+       /* In this case we assume this is the main application.  */
+       call_map = _dl_loaded;
+
+      /* Determine how much space we need.  We have to allocate the
+        memory locally.  */
+      required = DL_DST_REQUIRED (call_map, file, len, _dl_dst_count (dst, 0));
+
+      /* Get space for the new file name.  */
+      new_file = (char *) alloca (required + 1);
+
+      /* Generate the new file name.  */
+      DL_DST_SUBSTITUTE (call_map, file, new_file, 0);
+
+      /* If the substitution failed don't try to load.  */
+      if (*new_file == '\0')
+       _dl_signal_error (0, "dlopen",
+                         "empty dynamics string token substitution");
+
+      /* Now we have a new file name.  */
+      file = new_file;
+    }
 
   /* Load the named object.  */
   args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0);
@@ -157,7 +207,7 @@ dl_open_worker (void *a)
 
 struct link_map *
 internal_function
-_dl_open (const char *file, int mode)
+_dl_open (const char *file, int mode, const void *caller)
 {
   struct dl_open_args args;
   char *errstring;
@@ -172,6 +222,7 @@ _dl_open (const char *file, int mode)
 
   args.file = file;
   args.mode = mode;
+  args.caller = caller;
   args.map = NULL;
   errcode = _dl_catch_error (&errstring, dl_open_worker, &args);
 
index 496fc7d386fa54a3528cc028665c14e7ffce2ac9..b72300df5cce4efd3a767e5d9f669982bf4d21ed 100644 (file)
@@ -1,5 +1,5 @@
 /* Load a shared object at run time.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -28,6 +28,8 @@ struct dlopen_args
   int mode;
   /* The return value of dlopen_doit.  */
   struct link_map *new;
+  /* Address of the caller.  */
+  const void *caller;
 };
 
 
@@ -36,7 +38,7 @@ dlopen_doit (void *a)
 {
   struct dlopen_args *args = (struct dlopen_args *) a;
 
-  args->new = _dl_open (args->file ?: "", args->mode);
+  args->new = _dl_open (args->file ?: "", args->mode, args->caller);
 }
 
 
@@ -46,6 +48,7 @@ __dlopen_check (const char *file, int mode)
   struct dlopen_args args;
   args.file = file;
   args.mode = mode;
+  args.caller = __builtin_return_address (0);
 
   return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
 }
index 7e7b462e1a25f376971530934a1f59420d7ade52..661a40579adf129ccd06e85d9793157b40aff424 100644 (file)
@@ -32,6 +32,8 @@ struct dlopen_args
   int mode;
   /* The return value of dlopen_doit.  */
   struct link_map *new;
+  /* Address of the caller.  */
+  const void *caller;
 };
 
 
@@ -40,7 +42,7 @@ dlopen_doit (void *a)
 {
   struct dlopen_args *args = (struct dlopen_args *) a;
 
-  args->new = _dl_open (args->file ?: "", args->mode);
+  args->new = _dl_open (args->file ?: "", args->mode, args->caller);
 }
 
 
@@ -49,6 +51,7 @@ __dlopen_nocheck (const char *file, int mode)
 {
   struct dlopen_args args;
   args.file = file;
+  args.caller = __builtin_return_address (0);
 
   if ((mode & RTLD_BINDING_MASK) == 0)
     /* By default assume RTLD_LAZY.  */
index 392ea1787fd2275ebcbe8029a120c0bebc2b32e5..f8db76c32cb4b27918e43ee3498990a1ca855473 100644 (file)
@@ -270,7 +270,8 @@ extern void _dl_setup_hash (struct link_map *map) internal_function;
 /* Open the shared object NAME, relocate it, and run its initializer if it
    hasn't already been run.  MODE is as for `dlopen' (see <dlfcn.h>).  If
    the object is already opened, returns its existing map.  */
-extern struct link_map *_dl_open (const char *name, int mode)
+extern struct link_map *_dl_open (const char *name, int mode,
+                                 const void *caller)
      internal_function;
 
 /* Close an object previously opened by _dl_open.  */
diff --git a/elf/origtest.c b/elf/origtest.c
new file mode 100644 (file)
index 0000000..11bd0f7
--- /dev/null
@@ -0,0 +1,38 @@
+#include <dlfcn.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  void *h;
+  int (*fp) (int);
+  int res;
+
+  h = dlopen ("${ORIGIN}/testobj1.so", RTLD_LAZY);
+  if (h == NULL)
+    error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
+          dlerror ());
+
+  fp = dlsym (h, "obj1func1");
+  if (fp == NULL)
+    error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s",
+          "testobj1.so", dlerror ());
+
+  res = fp (10);
+  printf ("fp(10) = %d\n", res);
+
+  if (dlclose (h) != 0)
+    error (EXIT_FAILURE, 0, "while close `%s': %s",
+          "testobj1.so", dlerror ());
+
+  return res != 42;
+}
+
+
+int
+foo (int a)
+{
+  return a + 10;
+}
index 33f0efea90ca224725d82f81446c8f6d9e0c0836..52cf9d30648a682dca2895e9012954bca19b2fd5 100644 (file)
@@ -64,7 +64,7 @@ do_open (void *a)
 {
   struct gconv_loaded_object *args = (struct gconv_loaded_object *) a;
   /* Open and relocate the shared object.  */
-  args->handle = _dl_open (args->name, RTLD_LAZY);
+  args->handle = _dl_open (args->name, RTLD_LAZY, NULL);
 }
 
 
index 1a6c16e3ae6a1ddc61aba9d24e0016146e80a3e8..241fa2c6fc42094ba26d9dffade019dbde861e87 100644 (file)
@@ -285,7 +285,7 @@ do_open (void *a)
 {
   struct do_open_args *args = (struct do_open_args *) a;
   /* Open and relocate the shared object.  */
-  args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY);
+  args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY, NULL);
 }
 
 static void
similarity index 88%
rename from sysdeps/generic/dl-origin.h
rename to sysdeps/generic/dl-origin.c
index 495df60296657f94b24ea05f757f0218b4a27dd2..b10fee2d57fae2dd757e6493e73695d7d40508ac 100644 (file)
@@ -1,5 +1,5 @@
 /* Find path of executable.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <elf/ldsodefs.h>
+
+#include <dl-dst.h>
+
 /* Generally it is not possible to implement this.  We have to fall
    back on a solution where the user provides the information.  */
 extern const char *_dl_origin_path;
 
-static inline const char *
-get_origin (void)
+const char *
+_dl_get_origin (void)
 {
   char *result = (char *) -1;
   /* We use the environment variable LD_ORIGIN_PATH.  If it is set make
similarity index 90%
rename from sysdeps/unix/sysv/linux/dl-origin.h
rename to sysdeps/unix/sysv/linux/dl-origin.c
index 5654b42a2f60c9d119f0ca09d91cc9a2cf9e7997..a69684d99ee22f3a7281a31f488f00646892c3aa 100644 (file)
@@ -1,5 +1,5 @@
 /* Find path of executable.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <elf/ldsodefs.h>
+
+#include <dl-dst.h>
+
 /* On Linux >= 2.1 systems which have the dcache implementation we can get
    the path of the application from the /proc/self/exe symlink.  Try this
    first and fall back on the generic method if necessary.  */
 extern const char *_dl_origin_path;
 
-static inline const char *
-get_origin (void)
+const char *
+_dl_get_origin (void)
 {
   char linkval[PATH_MAX];
   char *result;