GLIBC_2.3.4 {
dlmopen;
}
+ GLIBC_2.15 {
+ __google_dlopen_with_offset; __google_dlmopen_with_offset;
+ }
GLIBC_PRIVATE {
_dlfcn_hook;
}
#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>
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));
/* 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,
{
/* Namespace ID. */
Lmid_t nsid;
+ /* ELF header at offset in file. */
+ off_t offset;
/* The arguments for dlopen_doit. */
const char *file;
int mode;
_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)
{
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)
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;
| __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)
{
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>
{
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);
{
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,
{
/* Argument to do_dlopen. */
const char *name;
+ off_t offset;
/* Opening mode. */
int mode;
/* This is the caller of the dlopen() function. */
{
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,
+ args->map = GLRO(dl_open) (args->name, args->offset, args->mode, args->caller_dlopen,
__LM_ID_CALLER, __libc_argc, __libc_argv,
__environ);
}
{
struct do_dlopen_args args;
args.name = name;
+ args.offset = 0;
args.mode = mode;
args.caller_dlopen = RETURN_ADDRESS (0);
static
#endif
struct link_map *
-_dl_map_object_from_fd (const char *name, const char *origname, int fd,
+_dl_map_object_from_fd (const char *name, const char *origname, 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)
c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
c->dataend = ph->p_vaddr + ph->p_filesz;
c->allocend = ph->p_vaddr + ph->p_memsz;
- c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize));
+ if (offset & (GLRO(dl_pagesize) - 1))
+ {
+ errstring = N_("invalid offset");
+ goto call_lose;
+ }
+ c->mapoff = ALIGN_DOWN(offset + ph->p_offset, GLRO(dl_pagesize));
/* Determine whether there is a gap between the last segment
and this one. */
If FD is not -1, then the file is already open and FD refers to it.
In that case, FD is consumed for both successful and error returns. */
static int
-open_verify (const char *name, int fd,
+open_verify (const char *name, int fd, off_t offset,
struct filebuf *fbp, struct link_map *loader,
int whatcode, int mode, bool *found_other_class, bool free_name)
{
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);
if MAY_FREE_DIRS is true. */
static int
-open_path (const char *name, size_t namelen, int mode,
+open_path (const char *name, size_t namelen, off_t offset, int mode,
struct r_search_path_struct *sps, char **realname,
struct filebuf *fbp, struct link_map *loader, int whatcode,
bool *found_other_class)
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
_dl_debug_printf (" trying file=%s\n", buf);
- fd = open_verify (buf, -1, fbp, loader, whatcode, mode,
+ fd = open_verify (buf, -1, offset, fbp, loader, whatcode, mode,
found_other_class, false);
if (this_dir->status[cnt] == unknown)
{
/* Map in the shared object file NAME. */
struct link_map *
-_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;
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,
+ fd = open_path (name, namelen, offset, mode,
&l->l_rpath_dirs,
&realname, &fb, loader, LA_SER_RUNPATH,
&found_other_class);
&& 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,
+ fd = open_path (name, namelen, mode, offset,
&main_map->l_rpath_dirs,
&realname, &fb, loader ?: main_map, LA_SER_RUNPATH,
&found_other_class);
/* Try the LD_LIBRARY_PATH environment variable. */
if (fd == -1 && env_path_list.dirs != (void *) -1)
- fd = open_path (name, namelen, mode, &env_path_list,
+ fd = open_path (name, namelen, offset, mode, &env_path_list,
&realname, &fb,
loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
LA_SER_LIBPATH, &found_other_class);
if (fd == -1 && loader != NULL
&& cache_rpath (loader, &loader->l_runpath_dirs,
DT_RUNPATH, "RUNPATH"))
- fd = open_path (name, namelen, mode,
+ fd = open_path (name, namelen, offset, mode,
&loader->l_runpath_dirs, &realname, &fb, loader,
LA_SER_RUNPATH, &found_other_class);
realname = _dl_sysdep_open_object (name, namelen, &fd);
if (realname != NULL)
{
- fd = open_verify (realname, fd,
+ fd = open_verify (realname, fd, offset,
&fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
LA_SER_CONFIG, mode, &found_other_class,
false);
if (cached != NULL)
{
- fd = open_verify (cached, -1,
+ fd = open_verify (cached, -1, 0,
&fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
LA_SER_CONFIG, mode, &found_other_class,
false);
&& ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
|| __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB)))
&& rtld_search_dirs.dirs != (void *) -1)
- fd = open_path (name, namelen, mode, &rtld_search_dirs,
+ fd = open_path (name, namelen, offset, mode, &rtld_search_dirs,
&realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
/* Add another newline when we are tracing the library loading. */
fd = -1;
else
{
- fd = open_verify (realname, -1, &fb,
+ fd = open_verify (realname, -1, offset, &fb,
loader ?: GL(dl_ns)[nsid]._ns_loaded, 0, mode,
&found_other_class, true);
if (__glibc_unlikely (fd == -1))
}
void *stack_end = __libc_stack_end;
- return _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader,
+ return _dl_map_object_from_fd (name, origname, fd, offset, &fb, realname, loader,
type, mode, &stack_end, nsid);
}
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;
/* 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
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)
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);
{
struct map_args *args = (struct map_args *) a;
int type = (args->mode == __RTLD_OPENEXEC) ? lt_executable : lt_library;
- args->map = _dl_map_object (args->loader, args->str, type, 0,
+ args->map = _dl_map_object (args->loader, args->str, 0, type, 0,
args->mode, LM_ID_BASE);
}
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, _dl_argv,
else
{
HP_TIMING_NOW (start);
- _dl_map_object (NULL, rtld_progname, lt_executable, 0,
+ _dl_map_object (NULL, rtld_progname, 0, lt_executable, 0,
__RTLD_OPENEXEC, LM_ID_BASE);
HP_TIMING_NOW (stop);
#ifndef _DLFCN_H
#include <dlfcn/dlfcn.h>
+#include <sys/types.h>
#ifndef _ISOMAC
#include <link.h> /* For ElfW. */
#include <stdbool.h>
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,
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];
};
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)
const struct r_found_version *, 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
libc_hidden_proto (_dl_catch_exception)
/* 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) attribute_hidden;
/* 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