aboutsummaryrefslogtreecommitdiff
path: root/dlfcn
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2014-03-10 14:02:07 -0700
committerPaul Pluzhnikov <ppluzhnikov@google.com>2014-03-10 14:02:07 -0700
commit9590be99606bd4903f8527affccc7c0957a9515d (patch)
tree129dbe46c6bfd6004804fad25c153f8cd6fd2b50 /dlfcn
parent8eb1716c9108c987004e886e37d33296032d8663 (diff)
downloadglibc-9590be99606bd4903f8527affccc7c0957a9515d.zip
glibc-9590be99606bd4903f8527affccc7c0957a9515d.tar.gz
glibc-9590be99606bd4903f8527affccc7c0957a9515d.tar.bz2
For Google b/8315591, experimental implementation of dlopen_with_offset.
Diffstat (limited to 'dlfcn')
-rw-r--r--dlfcn/Versions3
-rw-r--r--dlfcn/dlfcn.h12
-rw-r--r--dlfcn/dlmopen.c56
-rw-r--r--dlfcn/dlopen.c60
-rw-r--r--dlfcn/dlopenold.c2
5 files changed, 108 insertions, 25 deletions
diff --git a/dlfcn/Versions b/dlfcn/Versions
index 97902f0..77b0cf0 100644
--- a/dlfcn/Versions
+++ b/dlfcn/Versions
@@ -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;
}
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index 0921fd7..caa92e6 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -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,
diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c
index 2be1319..fb665ed 100644
--- a/dlfcn/dlmopen.c
+++ b/dlfcn/dlmopen.c
@@ -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,13 +72,52 @@ dlmopen_doit (void *a)
_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_with_offset (Lmid_t nsid, const char *file, off_t offset,
+ int mode DL_CALLER_DECL)
+{
+# ifdef SHARED
+ if (!rtld_active ())
+ return _dlfcn_hook->dlmopen_with_offset (nsid, file, offset, mode, RETURN_ADDRESS (0));
+# endif
+
+ struct dlmopen_args oargs;
+ oargs.nsid = nsid;
+ oargs.file = file;
+ oargs.offset = offset;
+ oargs.mode = mode;
+ oargs.caller = DL_CALLER;
+
+ return __dlmopen_common (&oargs);
+}
+# ifdef SHARED
+strong_alias (__dlmopen_with_offset, __google_dlmopen_with_offset)
+# endif
+
void *
__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
{
@@ -88,20 +129,11 @@ __dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
struct dlmopen_args args;
args.nsid = nsid;
args.file = file;
+ args.offset = 0;
args.mode = mode;
args.caller = DL_CALLER;
-# 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
+ return __dlmopen_common (&args);
}
# ifdef SHARED
strong_alias (__dlmopen, dlmopen)
diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
index c62ca23..319ae6e 100644
--- a/dlfcn/dlopen.c
+++ b/dlfcn/dlopen.c
@@ -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,13 +74,49 @@ dlopen_doit (void *a)
| __RTLD_SPROF))
_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_with_offset (const char *file, off_t offset, int mode DL_CALLER_DECL)
+{
+# ifdef SHARED
+ if (!rtld_active ())
+ return _dlfcn_hook->dlopen_with_offset (file, offset, mode, DL_CALLER);
+# endif
+
+ struct dlopen_args oargs;
+ oargs.file = file;
+ oargs.offset = offset;
+ oargs.mode = mode;
+ oargs.caller = DL_CALLER;
+
+ return __dlopen_common (&oargs);
+}
+# ifdef SHARED
+strong_alias (__dlopen_with_offset, __google_dlopen_with_offset)
+# endif
+
void *
__dlopen (const char *file, int mode DL_CALLER_DECL)
{
@@ -82,20 +127,11 @@ __dlopen (const char *file, int mode DL_CALLER_DECL)
struct dlopen_args args;
args.file = file;
+ args.offset = 0;
args.mode = mode;
args.caller = DL_CALLER;
-# 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
+ return __dlopen_common (&args);
}
# ifdef SHARED
# include <shlib-compat.h>
diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c
index d3b6a6c..d9ca12d 100644
--- a/dlfcn/dlopenold.c
+++ b/dlfcn/dlopenold.c
@@ -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);