]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
For Google b/8315591, experimental implementation of dlopen_with_offset.
authorPaul Pluzhnikov <ppluzhnikov@google.com>
Mon, 10 Mar 2014 21:02:07 +0000 (14:02 -0700)
committerPaul Pluzhnikov <ppluzhnikov@google.com>
Mon, 10 Mar 2014 21:02:07 +0000 (14:02 -0700)
14 files changed:
README.google
Versions.def
dlfcn/Versions
dlfcn/dlfcn.h
dlfcn/dlmopen.c
dlfcn/dlopen.c
dlfcn/dlopenold.c
elf/dl-deps.c
elf/dl-libc.c
elf/dl-load.c
elf/dl-open.c
elf/rtld.c
include/dlfcn.h
sysdeps/generic/ldsodefs.h

index e817c6b277a51ee30b6a85fa6f498da03a3e365b..ded2578b25e70e3b2d5689654a04eec186afe0a6 100644 (file)
@@ -262,3 +262,19 @@ ports/sysdeps/unix/sysv/linux/tile/bits/local_lim.h
   Forward ported from cl/59612021, cl/59817832, and cl/59176280.
   (ahh, google-local)
 
+Versions.def
+dlfcn/Versions
+dlfcn/dlfcn.h
+dlfcn/dlmopen.c
+dlfcn/dlopen.c
+dlfcn/dlopenold.c
+elf/dl-deps.c
+elf/dl-libc.c
+elf/dl-load.c
+elf/dl-open.c
+elf/rtld.c
+include/dlfcn.h
+sysdeps/generic/ldsodefs.h
+  For Google b/8315591, experimental implementation of dlopen_with_offset.
+  Forward-ported from cl/59286541, cl/59438930
+  (ppluzhnikov, google-local)
index 554dc40c9f471b5c435d78106a82d89b232716f5..1cd8db399e6617a3c5c8a04eff52c2c5ed8a65e3 100644 (file)
@@ -50,6 +50,7 @@ libdl {
   GLIBC_2.1
   GLIBC_2.3.3
   GLIBC_2.3.4
+  GLIBC_2.15
 }
 libm {
   GLIBC_2.0
index 97902f0dfdb5bbf9cc31e0d90cb19413fce68347..77b0cf01c40996118bdefcac9c9fea57de6f27d6 100644 (file)
@@ -11,6 +11,9 @@ libdl {
   GLIBC_2.3.4 {
     dlmopen;
   }
+  GLIBC_2.15 {
+    __google_dlopen_with_offset; __google_dlmopen_with_offset;
+  }
   GLIBC_PRIVATE {
     _dlfcn_hook;
   }
index 461cef1862dd69b5ee841a9eb3ae241d56096707..cceed5cf9569d43c9fe94f0c237a106ddeb3de3e 100644 (file)
@@ -22,6 +22,7 @@
 #include <features.h>
 #define __need_size_t
 #include <stddef.h>
+#include <sys/types.h>
 
 /* Collect various system dependent definitions and declarations.  */
 #include <bits/dlfcn.h>
@@ -55,6 +56,11 @@ __BEGIN_DECLS
    passed to `dlsym' to get symbol values from it.  */
 extern void *dlopen (const char *__file, int __mode) __THROWNL;
 
+/* Same as above, but ELF header is at OFF from the start of file.  */
+extern void *__google_dlopen_with_offset (__const char *__file,
+                                         off_t offset,
+                                         int __mode) __THROW;
+
 /* Unmap and close a shared object opened by `dlopen'.
    The handle cannot be used again after calling `dlclose'.  */
 extern int dlclose (void *__handle) __THROWNL __nonnull ((1));
@@ -68,6 +74,12 @@ extern void *dlsym (void *__restrict __handle,
 /* Like `dlopen', but request object to be allocated in a new namespace.  */
 extern void *dlmopen (Lmid_t __nsid, const char *__file, int __mode) __THROWNL;
 
+/* Same as above, but ELF header is at OFF from the start of file.  */
+extern void *__google_dlmopen_with_offset (Lmid_t __nsid,
+                                          __const char *__file,
+                                          off_t offset,
+                                          int __mode) __THROW;
+
 /* Find the run-time address in the shared object HANDLE refers to
    of the symbol called NAME with VERSION.  */
 extern void *dlvsym (void *__restrict __handle,
index 9e50603a10ffab3a429e1ec3df89b7b522e482dd..6e297d4d6962419247da41236d62dd3e3f49ecf4 100644 (file)
@@ -40,6 +40,8 @@ struct dlmopen_args
 {
   /* Namespace ID.  */
   Lmid_t nsid;
+  /* ELF header at offset in file.  */
+  off_t offset;
   /* The arguments for dlopen_doit.  */
   const char *file;
   int mode;
@@ -70,38 +72,71 @@ dlmopen_doit (void *a)
        GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid mode"));
     }
 
-  args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
+  args->new = GLRO(dl_open) (args->file ?: "",
+                            args->offset,
+                            args->mode | __RTLD_DLOPEN,
                             args->caller,
                             args->nsid, __dlfcn_argc, __dlfcn_argv,
                             __environ);
 }
 
 
+static void *
+__dlmopen_common (struct dlmopen_args *args)
+{
+
+# ifdef SHARED
+  return _dlerror_run (dlmopen_doit, args) ? NULL : args->new;
+# else
+  if (_dlerror_run (dlmopen_doit, args))
+    return NULL;
+
+  __libc_register_dl_open_hook ((struct link_map *) args->new);
+  __libc_register_dlfcn_hook ((struct link_map *) args->new);
+
+  return args->new;
+# endif
+}
+
 void *
-__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
+__dlmopen_with_offset (Lmid_t nsid, const char *file, off_t offset,
+                      int mode DL_CALLER_DECL)
 {
 # ifdef SHARED
   if (__builtin_expect (_dlfcn_hook != NULL, 0))
-    return _dlfcn_hook->dlmopen (nsid, file, mode, RETURN_ADDRESS (0));
+    return _dlfcn_hook->dlmopen_with_offset (nsid, file, offset,
+                                            mode, RETURN_ADDRESS (0));
 # endif
 
   struct dlmopen_args args;
   args.nsid = nsid;
   args.file = file;
+  args.offset = offset;
   args.mode = mode;
   args.caller = DL_CALLER;
 
+  return __dlmopen_common (&args);
+}
 # ifdef SHARED
-  return _dlerror_run (dlmopen_doit, &args) ? NULL : args.new;
-# else
-  if (_dlerror_run (dlmopen_doit, &args))
-    return NULL;
-
-  __libc_register_dl_open_hook ((struct link_map *) args.new);
-  __libc_register_dlfcn_hook ((struct link_map *) args.new);
+strong_alias (__dlmopen_with_offset, __google_dlmopen_with_offset)
+# endif
 
-  return args.new;
+void *
+__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
+{
+# ifdef SHARED
+  if (__builtin_expect (_dlfcn_hook != NULL, 0))
+    return _dlfcn_hook->dlmopen (nsid, file, mode, RETURN_ADDRESS (0));
 # endif
+
+  struct dlmopen_args args;
+  args.nsid = nsid;
+  args.file = file;
+  args.offset = 0;
+  args.mode = mode;
+  args.caller = DL_CALLER;
+
+  return __dlmopen_common (&args);
 }
 # ifdef SHARED
 strong_alias (__dlmopen, dlmopen)
index c6c0c583a97754d5c2ab101ea804fd445d5c1d36..50f545dd512e0b9e0c75a2f2c63cd5c9ac75f156 100644 (file)
@@ -33,12 +33,21 @@ dlopen (const char *file, int mode)
 static_link_warning (dlopen)
 #endif
 
+void *
+dlopen_with_offset (const char *file, off_t offset, int mode)
+{
+  return __dlopen_with_offset (file, offset, mode, RETURN_ADDRESS (0));
+}
+static_link_warning (dlopen_with_offset)
+
 #else
 
 struct dlopen_args
 {
   /* The arguments for dlopen_doit.  */
   const char *file;
+  /* ELF header at offset in file.  */
+  off_t offset;
   int mode;
   /* The return value of dlopen_doit.  */
   void *new;
@@ -65,37 +74,66 @@ dlopen_doit (void *a)
                     | __RTLD_SPROF))
     GLRO(dl_signal_error) (0, NULL, NULL, _("invalid mode parameter"));
 
-  args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
+  args->new = GLRO(dl_open) (args->file ?: "",
+                            args->offset,
+                            args->mode | __RTLD_DLOPEN,
                             args->caller,
                             args->file == NULL ? LM_ID_BASE : NS,
                             __dlfcn_argc, __dlfcn_argv, __environ);
 }
 
 
+static void *
+__dlopen_common (struct dlopen_args *args)
+{
+# ifdef SHARED
+  return _dlerror_run (dlopen_doit, args) ? NULL : args->new;
+# else
+  if (_dlerror_run (dlopen_doit, args))
+    return NULL;
+
+  __libc_register_dl_open_hook ((struct link_map *) args->new);
+  __libc_register_dlfcn_hook ((struct link_map *) args->new);
+
+  return args->new;
+# endif
+}
+
 void *
-__dlopen (const char *file, int mode DL_CALLER_DECL)
+__dlopen_with_offset (const char *file, off_t offset, int mode DL_CALLER_DECL)
 {
 # ifdef SHARED
   if (__builtin_expect (_dlfcn_hook != NULL, 0))
-    return _dlfcn_hook->dlopen (file, mode, DL_CALLER);
+    return _dlfcn_hook->dlopen_with_offset (file, offset, mode, DL_CALLER);
 # endif
 
   struct dlopen_args args;
   args.file = file;
+  args.offset = offset;
   args.mode = mode;
   args.caller = DL_CALLER;
 
+  return __dlopen_common (&args);
+}
+# ifdef SHARED
+strong_alias (__dlopen_with_offset, __google_dlopen_with_offset)
+# endif
+
+void *
+__dlopen (const char *file, int mode DL_CALLER_DECL)
+{
 # ifdef SHARED
-  return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
-# else
-  if (_dlerror_run (dlopen_doit, &args))
-    return NULL;
+  if (__builtin_expect (_dlfcn_hook != NULL, 0))
+    return _dlfcn_hook->dlopen (file, mode, DL_CALLER);
+# endif
 
-  __libc_register_dl_open_hook ((struct link_map *) args.new);
-  __libc_register_dlfcn_hook ((struct link_map *) args.new);
+  struct dlopen_args args;
+  args.file = file;
+  args.offset = 0;
+  args.mode = mode;
+  args.caller = DL_CALLER;
 
-  return args.new;
-# endif
+  return __dlopen_common (&args);
 }
 # ifdef SHARED
 #  include <shlib-compat.h>
index 6d3a430cf68a6ea6a1b9d31c4b0aa020b30b1e87..4a133a5c1d25fd6466b9b03e4a99d9f65a048693 100644 (file)
@@ -51,7 +51,7 @@ dlopen_doit (void *a)
 {
   struct dlopen_args *args = (struct dlopen_args *) a;
 
-  args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
+  args->new = GLRO(dl_open) (args->file ?: "", 0, args->mode | __RTLD_DLOPEN,
                             args->caller,
                             args->file == NULL ? LM_ID_BASE : NS,
                             __dlfcn_argc, __dlfcn_argv, __environ);
index 20c294e5b889dda30204a69e4a2ba39ec8dcc755..18fb4d15bc657cbdd86b3762c40e6aca15687e28 100644 (file)
@@ -60,7 +60,7 @@ openaux (void *a)
 {
   struct openaux_args *args = (struct openaux_args *) a;
 
-  args->aux = _dl_map_object (args->map, args->name,
+  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, args->open_mode,
index ceac3caeb27a0ff33b868ae69a462442c3650c07..0dfeb5e63eacc117d1e6457dc031a69285ac685f 100644 (file)
@@ -59,6 +59,7 @@ struct do_dlopen_args
 {
   /* Argument to do_dlopen.  */
   const char *name;
+  off_t offset;
   /* Opening mode.  */
   int mode;
   /* This is the caller of the dlopen() function.  */
@@ -84,9 +85,9 @@ do_dlopen (void *ptr)
 {
   struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
   /* Open and relocate the shared object.  */
-  args->map = GLRO(dl_open) (args->name, args->mode, args->caller_dlopen,
-                            __LM_ID_CALLER, __libc_argc, __libc_argv,
-                            __environ);
+  args->map = GLRO(dl_open) (args->name, args->offset, args->mode,
+                            args->caller_dlopen, __LM_ID_CALLER,
+                            __libc_argc, __libc_argv, __environ);
 }
 
 static void
@@ -154,6 +155,7 @@ __libc_dlopen_mode (const char *name, int mode)
 {
   struct do_dlopen_args args;
   args.name = name;
+  args.offset = 0;
   args.mode = mode;
   args.caller_dlopen = RETURN_ADDRESS (0);
 
index cab4f6f2b21f5afb3a4eac278f3b47ef104b7f3b..4f114fdcdf6c60338969f3c6ed29284b26a11aea 100644 (file)
@@ -925,7 +925,8 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
 static
 #endif
 struct link_map *
-_dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
+_dl_map_object_from_fd (const char *name, int fd, off_t offset,
+                       struct filebuf *fbp,
                        char *realname, struct link_map *loader, int l_type,
                        int mode, void **stack_endp, Lmid_t nsid)
 {
@@ -1152,7 +1153,12 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
                       & ~(GLRO(dl_pagesize) - 1));
          c->dataend = ph->p_vaddr + ph->p_filesz;
          c->allocend = ph->p_vaddr + ph->p_memsz;
-         c->mapoff = ph->p_offset & ~(GLRO(dl_pagesize) - 1);
+         if (offset & (GLRO(dl_pagesize) - 1))
+           {
+             errstring = N_("invalid offset");
+             goto call_lose;
+           }
+         c->mapoff = offset + ph->p_offset & ~(GLRO(dl_pagesize) - 1);
 
          /* Determine whether there is a gap between the last segment
             and this one.  */
@@ -1674,7 +1680,8 @@ print_search_path (struct r_search_path_elem **list,
    this could mean there is something wrong in the installation and the
    user might want to know about this.  */
 static int
-open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
+open_verify (const char *name, off_t offset,
+            struct filebuf *fbp, struct link_map *loader,
             int whatcode, bool *found_other_class, bool free_name)
 {
   /* This is the expected ELF header.  */
@@ -1742,6 +1749,9 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
       unsigned int osversion;
       size_t maplength;
 
+      if (__lseek (fd, offset, SEEK_SET) == -1)
+       goto close_and_out;
+
       /* We successfully opened the file.  Now verify it is a file
         we can use.  */
       __set_errno (0);
@@ -1936,7 +1946,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
    if MAY_FREE_DIRS is true.  */
 
 static int
-open_path (const char *name, size_t namelen, int secure,
+open_path (const char *name, size_t namelen, off_t offset, int secure,
           struct r_search_path_struct *sps, char **realname,
           struct filebuf *fbp, struct link_map *loader, int whatcode,
           bool *found_other_class)
@@ -1988,8 +1998,8 @@ open_path (const char *name, size_t namelen, int secure,
          if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
            _dl_debug_printf ("  trying file=%s\n", buf);
 
-         fd = open_verify (buf, fbp, loader, whatcode, found_other_class,
-                           false);
+         fd = open_verify (buf, offset, fbp, loader, whatcode,
+                           found_other_class, false);
          if (this_dir->status[cnt] == unknown)
            {
              if (fd != -1)
@@ -2118,7 +2128,7 @@ match_one (const char *name, struct link_map *l)
 
 struct link_map *
 internal_function
-_dl_map_object (struct link_map *loader, const char *name,
+_dl_map_object (struct link_map *loader, const char *name, off_t offset,
                int type, int trace_mode, int mode, Lmid_t nsid)
 {
   int fd;
@@ -2210,7 +2220,7 @@ _dl_map_object (struct link_map *loader, const char *name,
          for (l = loader; l; l = l->l_loader)
            if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
              {
-               fd = open_path (name, namelen, mode & __RTLD_SECURE,
+               fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
                                &l->l_rpath_dirs,
                                &realname, &fb, loader, LA_SER_RUNPATH,
                                &found_other_class);
@@ -2226,7 +2236,7 @@ _dl_map_object (struct link_map *loader, const char *name,
              && main_map != NULL && main_map->l_type != lt_loaded
              && cache_rpath (main_map, &main_map->l_rpath_dirs, DT_RPATH,
                              "RPATH"))
-           fd = open_path (name, namelen, mode & __RTLD_SECURE,
+           fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
                            &main_map->l_rpath_dirs,
                            &realname, &fb, loader ?: main_map, LA_SER_RUNPATH,
                            &found_other_class);
@@ -2234,7 +2244,8 @@ _dl_map_object (struct link_map *loader, const char *name,
 
       /* Try the LD_LIBRARY_PATH environment variable.  */
       if (fd == -1 && env_path_list.dirs != (void *) -1)
-       fd = open_path (name, namelen, mode & __RTLD_SECURE, &env_path_list,
+       fd = open_path (name, namelen, offset,
+                       mode & __RTLD_SECURE, &env_path_list,
                        &realname, &fb,
                        loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
                        LA_SER_LIBPATH, &found_other_class);
@@ -2243,7 +2254,7 @@ _dl_map_object (struct link_map *loader, const char *name,
       if (fd == -1 && loader != NULL
          && cache_rpath (loader, &loader->l_runpath_dirs,
                          DT_RUNPATH, "RUNPATH"))
-       fd = open_path (name, namelen, mode & __RTLD_SECURE,
+       fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
                        &loader->l_runpath_dirs, &realname, &fb, loader,
                        LA_SER_RUNPATH, &found_other_class);
 
@@ -2291,7 +2302,7 @@ _dl_map_object (struct link_map *loader, const char *name,
 
              if (cached != NULL)
                {
-                 fd = open_verify (cached,
+                 fd = open_verify (cached, 0,
                                    &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
                                    LA_SER_CONFIG, &found_other_class, false);
                  if (__builtin_expect (fd != -1, 1))
@@ -2313,7 +2324,8 @@ _dl_map_object (struct link_map *loader, const char *name,
          && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
              || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
          && rtld_search_dirs.dirs != (void *) -1)
-       fd = open_path (name, namelen, mode & __RTLD_SECURE, &rtld_search_dirs,
+       fd = open_path (name, namelen, offset, mode & __RTLD_SECURE,
+                       &rtld_search_dirs,
                        &realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
 
       /* Add another newline when we are tracing the library loading.  */
@@ -2330,7 +2342,7 @@ _dl_map_object (struct link_map *loader, const char *name,
        fd = -1;
       else
        {
-         fd = open_verify (realname, &fb,
+         fd = open_verify (realname, offset, &fb,
                            loader ?: GL(dl_ns)[nsid]._ns_loaded, 0,
                            &found_other_class, true);
          if (__builtin_expect (fd, 0) == -1)
@@ -2392,8 +2404,8 @@ _dl_map_object (struct link_map *loader, const char *name,
     }
 
   void *stack_end = __libc_stack_end;
-  return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode,
-                                &stack_end, nsid);
+  return _dl_map_object_from_fd (name, fd, offset, &fb, realname, loader, type,
+                                mode, &stack_end, nsid);
 }
 
 
index ea222d03e185f414564a17fe277b4321da2435ef..622a9e557f1614ca71882608b6185db0659d9b41 100644 (file)
@@ -45,6 +45,8 @@ extern int __libc_multiple_libcs;     /* Defined in init-first.c.  */
 struct dl_open_args
 {
   const char *file;
+  /* ELF header at offset in file.  */
+  off_t offset;
   int mode;
   /* This is the caller of the dlopen() function.  */
   const void *caller_dlopen;
@@ -221,7 +223,7 @@ dl_open_worker (void *a)
 
   /* Load the named object.  */
   struct link_map *new;
-  args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
+  args->map = new = _dl_map_object (call_map, file, args->offset, lt_loaded, 0,
                                    mode | __RTLD_CALLMAP, args->nsid);
 
   /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
@@ -592,9 +594,9 @@ cannot load any more object with static TLS"));
                      new->l_name, new->l_ns, new->l_direct_opencount);
 }
 
-
 void *
-_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
+_dl_open (const char *file, off_t offset, int mode,
+         const void *caller_dlopen, Lmid_t nsid,
          int argc, char *argv[], char *env[])
 {
   if ((mode & RTLD_BINDING_MASK) == 0)
@@ -638,6 +640,7 @@ no more namespaces available for dlmopen()"));
 
   struct dl_open_args args;
   args.file = file;
+  args.offset = offset;
   args.mode = mode;
   args.caller_dlopen = caller_dlopen;
   args.caller_dl_open = RETURN_ADDRESS (0);
index a771e27c7cca98f2768c03882acbd7e912966927..acc4f00458c3244c1e53521a4428c273c2181015 100644 (file)
@@ -634,15 +634,15 @@ static void
 map_doit (void *a)
 {
   struct map_args *args = (struct map_args *) a;
-  args->map = _dl_map_object (args->loader, args->str, lt_library, 0,
-                             args->mode, LM_ID_BASE);
+  args->map = _dl_map_object (args->loader, args->str, 0, lt_library,
+                             0, args->mode, LM_ID_BASE);
 }
 
 static void
 dlmopen_doit (void *a)
 {
   struct dlmopen_args *args = (struct dlmopen_args *) a;
-  args->map = _dl_open (args->fname,
+  args->map = _dl_open (args->fname, 0,
                        (RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT
                         | __RTLD_SECURE),
                        dl_main, LM_ID_NEWLM, _dl_argc, INTUSE(_dl_argv),
@@ -1088,7 +1088,7 @@ of this helper program; chances are you did not intend to run this program.\n\
       else
        {
          HP_TIMING_NOW (start);
-         _dl_map_object (NULL, rtld_progname, lt_library, 0,
+         _dl_map_object (NULL, rtld_progname, 0, lt_library, 0,
                          __RTLD_OPENEXEC, LM_ID_BASE);
          HP_TIMING_NOW (stop);
 
index 666ee605961816959e71e1c23c15c75b31d39b20..f71aa8603eb9f9f2ecf34becb511a1d6aeb9ed61 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _DLFCN_H
 #include <dlfcn/dlfcn.h>
+#include <sys/types.h>
 #ifndef _ISOMAC
 #include <link.h>              /* For ElfW.  */
 #include <stdbool.h>
@@ -106,6 +107,8 @@ extern int _dlerror_run (void (*operate) (void *), void *args)
 struct dlfcn_hook
 {
   void *(*dlopen) (const char *file, int mode, void *dl_caller);
+  void *(*dlopen_with_offset) (const char *file, off_t offset,
+                              int mode, void *dl_caller);
   int (*dlclose) (void *handle);
   void *(*dlsym) (void *handle, const char *name, void *dl_caller);
   void *(*dlvsym) (void *handle, const char *name, const char *version,
@@ -116,6 +119,8 @@ struct dlfcn_hook
                  void **extra_info, int flags);
   int (*dlinfo) (void *handle, int request, void *arg, void *dl_caller);
   void *(*dlmopen) (Lmid_t nsid, const char *file, int mode, void *dl_caller);
+  void *(*dlmopen_with_offset) (Lmid_t nsid, const char *file, off_t offset,
+                               int mode, void *dl_caller);
   void *pad[4];
 };
 
@@ -124,8 +129,14 @@ libdl_hidden_proto (_dlfcn_hook)
 
 extern void *__dlopen (const char *file, int mode DL_CALLER_DECL)
      attribute_hidden;
+extern void *__dlopen_with_offset (const char *file, off_t offset,
+                                  int mode DL_CALLER_DECL)
+     attribute_hidden;
 extern void *__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
      attribute_hidden;
+extern void *__dlmopen_with_offset (Lmid_t nsid, const char *file, off_t offset,
+                                   int mode DL_CALLER_DECL)
+     attribute_hidden;
 extern int __dlclose (void *handle)
      attribute_hidden;
 extern void *__dlsym (void *handle, const char *name DL_CALLER_DECL)
index a20ed6f1df050ecb84041c24e5c5218d53b7aa00..f3c67ee8aee4946382408911dfb322ae68907658 100644 (file)
@@ -624,8 +624,9 @@ struct rtld_global_ro
                                                     int, int,
                                                     struct link_map *);
   int (*_dl_check_caller) (const void *, enum allowmask);
-  void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen,
-                    Lmid_t nsid, int argc, char *argv[], char *env[]);
+  void *(*_dl_open) (const char *file, off_t offset, int mode,
+                    const void *caller_dlopen, Lmid_t nsid,
+                    int argc, char *argv[], char *env[]);
   void (*_dl_close) (void *map);
   void *(*_dl_tls_get_addr_soft) (struct link_map *);
 #ifdef HAVE_DL_DISCOVER_OSVERSION
@@ -797,10 +798,12 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
 
 
 /* Open the shared object NAME and map in its segments.
+   ELF header is at OFFSET into the file.
    LOADER's DT_RPATH is used in searching for NAME.
    If the object is already opened, returns its existing map.  */
 extern struct link_map *_dl_map_object (struct link_map *loader,
                                        const char *name,
+                                       off_t offset,
                                        int type, int trace_mode, int mode,
                                        Lmid_t nsid)
      internal_function attribute_hidden;
@@ -1068,8 +1071,9 @@ extern int _dl_check_caller (const void *caller, enum allowmask mask)
 /* 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 void *_dl_open (const char *name, int mode, const void *caller,
-                      Lmid_t nsid, int argc, char *argv[], char *env[])
+extern void *_dl_open (const char *name, off_t offset, int mode,
+                      const void *caller, Lmid_t nsid,
+                      int argc, char *argv[], char *env[])
      attribute_hidden;
 
 /* Free or queue for freeing scope OLD.  If other threads might be