From 17c46147bc21f7e62dddfee4e03493ec484193b9 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Mon, 10 Mar 2014 14:02:07 -0700 Subject: [PATCH] For Google b/8315591, experimental implementation of dlopen_with_offset. --- README.google | 16 ++++++++++ Versions.def | 1 + dlfcn/Versions | 3 ++ dlfcn/dlfcn.h | 12 ++++++++ dlfcn/dlmopen.c | 59 ++++++++++++++++++++++++++++-------- dlfcn/dlopen.c | 62 ++++++++++++++++++++++++++++++-------- dlfcn/dlopenold.c | 2 +- elf/dl-deps.c | 2 +- elf/dl-libc.c | 8 +++-- elf/dl-load.c | 44 +++++++++++++++++---------- elf/dl-open.c | 9 ++++-- elf/rtld.c | 8 ++--- include/dlfcn.h | 11 +++++++ sysdeps/generic/ldsodefs.h | 12 +++++--- 14 files changed, 193 insertions(+), 56 deletions(-) diff --git a/README.google b/README.google index e817c6b277..ded2578b25 100644 --- a/README.google +++ b/README.google @@ -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) diff --git a/Versions.def b/Versions.def index 554dc40c9f..1cd8db399e 100644 --- a/Versions.def +++ b/Versions.def @@ -50,6 +50,7 @@ libdl { GLIBC_2.1 GLIBC_2.3.3 GLIBC_2.3.4 + GLIBC_2.15 } libm { GLIBC_2.0 diff --git a/dlfcn/Versions b/dlfcn/Versions index 97902f0dfd..77b0cf01c4 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 461cef1862..cceed5cf95 100644 --- a/dlfcn/dlfcn.h +++ b/dlfcn/dlfcn.h @@ -22,6 +22,7 @@ #include #define __need_size_t #include +#include /* Collect various system dependent definitions and declarations. */ #include @@ -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 9e50603a10..6e297d4d69 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,55 @@ 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_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_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 +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 +132,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 c6c0c583a9..50f545dd51 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,51 @@ 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_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_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) { @@ -82,20 +129,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 diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c index 6d3a430cf6..4a133a5c1d 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); diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 20c294e5b8..18fb4d15bc 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -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, diff --git a/elf/dl-libc.c b/elf/dl-libc.c index ceac3caeb2..0dfeb5e63e 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -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); diff --git a/elf/dl-load.c b/elf/dl-load.c index cab4f6f2b2..4f114fdcdf 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -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); } diff --git a/elf/dl-open.c b/elf/dl-open.c index ea222d03e1..622a9e557f 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -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); diff --git a/elf/rtld.c b/elf/rtld.c index a771e27c7c..acc4f00458 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -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); diff --git a/include/dlfcn.h b/include/dlfcn.h index 666ee60596..f71aa8603e 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -1,5 +1,6 @@ #ifndef _DLFCN_H #include +#include #ifndef _ISOMAC #include /* For ElfW. */ #include @@ -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) diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index a20ed6f1df..f3c67ee8ae 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -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 ). 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