Import the DragonFly BSD commit 4f0bc915b65fcf5a23214f6d221d65c80be68ad4

by John Marino <draco@marino.st>, with the following (edited) commit
message
Date: Sat, 24 Mar 2012 06:40:50 +0100
Subject: [PATCH 1/1] rtld: Implement DT_RUNPATH and -z nodefaultlib

DT_RUNPATH is incorrectly being considered as an alias of DT_RPATH.  The
purpose of DT_RUNPATH is to have two different types of rpath: one that
can be overridden by the environment variable LD_LIBRARY_PATH and one that
can't.  With the currently implementation, LD_LIBRARY_PATH will always
trump any embedded rpath or runpath tags.

Current path search order by rtld:
==================================
LD_LIBRARY_PATH
DT_RPATH / DT_RUNPATH (always the same)
ldconfig hints file (default: /var/run/ld-elf.so.hints)
/usr/lib

New path search order by rtld:
==============================
DT_RPATH of the calling object if no DT_RUNPATH
DT_RPATH of the main binary if no DT_RUNPATH and binary isn't calling obj
LD_LIBRARY_PATH
DT_RUNPATH
ldconfig hints file
/usr/lib

The new path search matches how the linux runtime loader works.  The other
major added feature is support for linker flag "-z nodefaultlib".  When
this flag is passed to the linker, rtld will skip all references to the
standard library search path ("/usr/lib" in this case but it could handle
more color delimited paths) except in DT_RPATH and DT_RUNPATH.

New path search order by rtld with -z nodefaultlib flag set:
============================================================
DT_RPATH of the calling object if no DT_RUNPATH
DT_RPATH of the main binary if no DT_RUNPATH and binary isn't calling obj
LD_LIBRARY_PATH
DT_RUNPATH
ldconfig hints file (skips all references to /usr/lib)

FreeBSD notes:
- we fixed some bugs which were submitted to DragonFly and merged there
  as commit 1ff8a2bd3eb6e5587174c6a983303ea3a79e0002;
- we added LD_LIBRARY_PATH_RPATH environment variable to switch to
  the previous behaviour of considering DT_RPATH a synonym for DT_RUNPATH;
- the FreeBSD default search path is /lib:/usr/lib and not /usr/lib.

Reviewed by:   kan
MFC after:     1 month
MFC note:      flip the ld_library_path_rpath default value for stable/9
This commit is contained in:
kib 2012-07-15 10:53:48 +00:00
parent 4d945ad412
commit a78a2e3c36
3 changed files with 275 additions and 71 deletions

View File

@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 1, 2009
.Dd June 28, 2012
.Dt RTLD 1
.Os
.Sh NAME
@ -86,14 +86,39 @@ dynamic linker.
After the dynamic linker has finished loading,
relocating, and initializing the program and its required shared
objects, it transfers control to the entry point of the program.
The following search order is used to locate required shared objects:
.Pp
To locate the required shared objects in the file system,
.Nm
may use a
.Dq hints
file prepared by the
.Bl -enum -offset indent -compact
.It
.Dv DT_RPATH
of the referencing object unless that object also contains a
.Dv DT_RUNPATH
tag
.It
.Dv DT_RPATH
of the program unless the referencing object contains a
.Dv DT_RUNPATH
tag
.It
Path indicated by
.Ev LD_LIBRARY_PATH
environment variable
.It
.Dv DT_RUNPATH
of the referencing object
.It
Hints file produced by the
.Xr ldconfig 8
utility.
utility
.It
The
.Pa /lib
and
.Pa /usr/lib
directories, unless the referencing object was linked using the
.Dq Fl z Ar nodefaultlib
option
.El
.Pp
The
.Nm
@ -143,6 +168,20 @@ This variable is unset for set-user-ID and set-group-ID programs.
A colon separated list of directories, overriding the default search path
for shared libraries.
This variable is unset for set-user-ID and set-group-ID programs.
.It Ev LD_LIBRARY_PATH_RPATH
If the variable is specified and has a value starting with
any of \'y\', \'Y\' or \'1\' symbols, the path specified by
.Ev LD_LIBRARY_PATH
variable is allowed to override the path from
.Dv DT_RPATH
for binaries which does not contain
.Dv DT_RUNPATH
tag.
For such binaries, when the variable
.Ev LD_LIBRARY_PATH_RPATH
is set,
.Dq Fl z Ar nodefaultlib
link-time option is ignored as well.
.It Ev LD_PRELOAD
A list of shared libraries, separated by colons and/or white space,
to be linked in before any

View File

@ -80,8 +80,9 @@ typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg);
static const char *basename(const char *);
static void die(void) __dead2;
static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **,
const Elf_Dyn **);
static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *);
const Elf_Dyn **, const Elf_Dyn **);
static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *,
const Elf_Dyn *);
static void digest_dynamic(Obj_Entry *, int);
static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
static Obj_Entry *dlcheck(void *);
@ -94,7 +95,7 @@ static void errmsg_restore(char *);
static char *errmsg_save(void);
static void *fill_search_info(const char *, size_t, void *);
static char *find_library(const char *, const Obj_Entry *);
static const char *gethints(void);
static const char *gethints(bool);
static void init_dag(Obj_Entry *);
static void init_rtld(caddr_t, Elf_Auxinfo **);
static void initlist_add_neededs(Needed_Entry *, Objlist *);
@ -233,6 +234,8 @@ size_t tls_static_space; /* Static TLS space allocated */
int tls_dtv_generation = 1; /* Used to detect when dtv size changes */
int tls_max_index = 1; /* Largest module index allocated */
bool ld_library_path_rpath = false;
/*
* Fill in a DoneList with an allocation large enough to hold all of
* the currently-loaded objects. Keep this as a macro since it calls
@ -323,6 +326,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
Obj_Entry **preload_tail;
Objlist initlist;
RtldLockState lockstate;
char *library_path_rpath;
int mib[2];
size_t len;
@ -394,7 +398,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
if (unsetenv(LD_ "PRELOAD") || unsetenv(LD_ "LIBMAP") ||
unsetenv(LD_ "LIBRARY_PATH") || unsetenv(LD_ "LIBMAP_DISABLE") ||
unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH") ||
unsetenv(LD_ "LOADFLTR")) {
unsetenv(LD_ "LOADFLTR") || unsetenv(LD_ "LIBRARY_PATH_RPATH")) {
_rtld_error("environment corrupt; aborting");
die();
}
@ -406,6 +410,15 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
ld_preload = getenv(LD_ "PRELOAD");
ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH");
ld_loadfltr = getenv(LD_ "LOADFLTR") != NULL;
library_path_rpath = getenv(LD_ "LIBRARY_PATH_RPATH");
if (library_path_rpath != NULL) {
if (library_path_rpath[0] == 'y' ||
library_path_rpath[0] == 'Y' ||
library_path_rpath[0] == '1')
ld_library_path_rpath = true;
else
ld_library_path_rpath = false;
}
dangerous_ld_env = libmap_disable || (libmap_override != NULL) ||
(ld_library_path != NULL) || (ld_preload != NULL) ||
(ld_elf_hints_path != NULL) || ld_loadfltr;
@ -828,7 +841,7 @@ die(void)
*/
static void
digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
const Elf_Dyn **dyn_soname)
const Elf_Dyn **dyn_soname, const Elf_Dyn **dyn_runpath)
{
const Elf_Dyn *dynp;
Needed_Entry **needed_tail = &obj->needed;
@ -843,6 +856,7 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
*dyn_rpath = NULL;
*dyn_soname = NULL;
*dyn_runpath = NULL;
obj->bind_now = false;
for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) {
@ -1009,7 +1023,6 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
break;
case DT_RPATH:
case DT_RUNPATH: /* XXX: process separately */
/*
* We have to wait until later to process this, because we
* might not have gotten the address of the string table yet.
@ -1021,6 +1034,10 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
*dyn_soname = dynp;
break;
case DT_RUNPATH:
*dyn_runpath = dynp;
break;
case DT_INIT:
obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr);
break;
@ -1114,6 +1131,8 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
obj->z_nodelete = true;
if (dynp->d_un.d_val & DF_1_LOADFLTR)
obj->z_loadfltr = true;
if (dynp->d_un.d_val & DF_1_NODEFLIB)
obj->z_nodeflib = true;
break;
default:
@ -1153,7 +1172,7 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
static void
digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath,
const Elf_Dyn *dyn_soname)
const Elf_Dyn *dyn_soname, const Elf_Dyn *dyn_runpath)
{
if (obj->z_origin && obj->origin_path == NULL) {
@ -1162,7 +1181,12 @@ digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath,
die();
}
if (dyn_rpath != NULL) {
if (dyn_runpath != NULL) {
obj->runpath = (char *)obj->strtab + dyn_runpath->d_un.d_val;
if (obj->z_origin)
obj->runpath = origin_subst(obj->runpath, obj->origin_path);
}
else if (dyn_rpath != NULL) {
obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val;
if (obj->z_origin)
obj->rpath = origin_subst(obj->rpath, obj->origin_path);
@ -1177,9 +1201,10 @@ digest_dynamic(Obj_Entry *obj, int early)
{
const Elf_Dyn *dyn_rpath;
const Elf_Dyn *dyn_soname;
const Elf_Dyn *dyn_runpath;
digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname);
digest_dynamic2(obj, dyn_rpath, dyn_soname);
digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname, &dyn_runpath);
digest_dynamic2(obj, dyn_rpath, dyn_soname, dyn_runpath);
}
/*
@ -1389,43 +1414,71 @@ gnu_hash(const char *s)
* loaded shared object, whose library search path will be searched.
*
* The search order is:
* DT_RPATH in the referencing file _unless_ DT_RUNPATH is present (1)
* DT_RPATH of the main object if DSO without defined DT_RUNPATH (1)
* LD_LIBRARY_PATH
* rpath in the referencing file
* ldconfig hints
* /lib:/usr/lib
* DT_RUNPATH in the referencing file
* ldconfig hints (if -z nodefaultlib, filter out default library directories
* from list)
* /lib:/usr/lib _unless_ the referencing file is linked with -z nodefaultlib
*
* (1) Handled in digest_dynamic2 - rpath left NULL if runpath defined.
*/
static char *
find_library(const char *xname, const Obj_Entry *refobj)
{
char *pathname;
char *name;
bool objgiven;
objgiven = refobj != NULL;
if (strchr(xname, '/') != NULL) { /* Hard coded pathname */
if (xname[0] != '/' && !trust) {
_rtld_error("Absolute pathname required for shared object \"%s\"",
xname);
return NULL;
}
if (refobj != NULL && refobj->z_origin)
if (objgiven && refobj->z_origin)
return origin_subst(xname, refobj->origin_path);
else
return xstrdup(xname);
}
if (libmap_disable || (refobj == NULL) ||
if (libmap_disable || !objgiven ||
(name = lm_find(refobj->path, xname)) == NULL)
name = (char *)xname;
dbg(" Searching for \"%s\"", name);
if ((pathname = search_library_path(name, ld_library_path)) != NULL ||
(refobj != NULL &&
(pathname = search_library_path(name, refobj->rpath)) != NULL) ||
(pathname = search_library_path(name, gethints())) != NULL ||
(pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
return pathname;
/*
* If refobj->rpath != NULL, then refobj->runpath is NULL. Fall
* back to pre-conforming behaviour if user requested so with
* LD_LIBRARY_PATH_RPATH environment variable and ignore -z
* nodeflib.
*/
if (objgiven && refobj->rpath != NULL && ld_library_path_rpath) {
if ((pathname = search_library_path(name, ld_library_path)) != NULL ||
(refobj != NULL &&
(pathname = search_library_path(name, refobj->rpath)) != NULL) ||
(pathname = search_library_path(name, gethints(false))) != NULL ||
(pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
return (pathname);
} else {
if ((objgiven &&
(pathname = search_library_path(name, refobj->rpath)) != NULL) ||
(objgiven && refobj->runpath == NULL && refobj != obj_main &&
(pathname = search_library_path(name, obj_main->rpath)) != NULL) ||
(pathname = search_library_path(name, ld_library_path)) != NULL ||
(objgiven &&
(pathname = search_library_path(name, refobj->runpath)) != NULL) ||
(pathname = search_library_path(name, gethints(refobj->z_nodeflib)))
!= NULL ||
(objgiven && !refobj->z_nodeflib &&
(pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL))
return (pathname);
}
if(refobj != NULL && refobj->path != NULL) {
if (objgiven && refobj->path != NULL) {
_rtld_error("Shared object \"%s\" not found, required by \"%s\"",
name, basename(refobj->path));
} else {
@ -1520,41 +1573,142 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
/*
* Return the search path from the ldconfig hints file, reading it if
* necessary. Returns NULL if there are problems with the hints file,
* necessary. If nostdlib is true, then the default search paths are
* not added to result.
*
* Returns NULL if there are problems with the hints file,
* or if the search path there is empty.
*/
static const char *
gethints(void)
gethints(bool nostdlib)
{
static char *hints;
if (hints == NULL) {
int fd;
static char *hints, *filtered_path;
struct elfhints_hdr hdr;
struct fill_search_info_args sargs, hargs;
struct dl_serinfo smeta, hmeta, *SLPinfo, *hintinfo;
struct dl_serpath *SLPpath, *hintpath;
char *p;
unsigned int SLPndx, hintndx, fndx, fcount;
int fd;
size_t flen;
bool skip;
/* Keep from trying again in case the hints file is bad. */
hints = "";
/* First call, read the hints file */
if (hints == NULL) {
/* Keep from trying again in case the hints file is bad. */
hints = "";
if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
return NULL;
if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
hdr.magic != ELFHINTS_MAGIC ||
hdr.version != 1) {
close(fd);
return NULL;
if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
return (NULL);
if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
hdr.magic != ELFHINTS_MAGIC ||
hdr.version != 1) {
close(fd);
return (NULL);
}
p = xmalloc(hdr.dirlistlen + 1);
if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 ||
read(fd, p, hdr.dirlistlen + 1) !=
(ssize_t)hdr.dirlistlen + 1) {
free(p);
close(fd);
return (NULL);
}
hints = p;
close(fd);
}
p = xmalloc(hdr.dirlistlen + 1);
if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 ||
read(fd, p, hdr.dirlistlen + 1) != (ssize_t)hdr.dirlistlen + 1) {
free(p);
close(fd);
return NULL;
/*
* If caller agreed to receive list which includes the default
* paths, we are done. Otherwise, if we still did not
* calculated filtered result, do it now.
*/
if (!nostdlib)
return (hints[0] != '\0' ? hints : NULL);
if (filtered_path != NULL)
goto filt_ret;
/*
* Obtain the list of all configured search paths, and the
* list of the default paths.
*
* First estimate the size of the results.
*/
smeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath);
smeta.dls_cnt = 0;
hmeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath);
hmeta.dls_cnt = 0;
sargs.request = RTLD_DI_SERINFOSIZE;
sargs.serinfo = &smeta;
hargs.request = RTLD_DI_SERINFOSIZE;
hargs.serinfo = &hmeta;
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs);
path_enumerate(p, fill_search_info, &hargs);
SLPinfo = xmalloc(smeta.dls_size);
hintinfo = xmalloc(hmeta.dls_size);
/*
* Next fetch both sets of paths.
*/
sargs.request = RTLD_DI_SERINFO;
sargs.serinfo = SLPinfo;
sargs.serpath = &SLPinfo->dls_serpath[0];
sargs.strspace = (char *)&SLPinfo->dls_serpath[smeta.dls_cnt];
hargs.request = RTLD_DI_SERINFO;
hargs.serinfo = hintinfo;
hargs.serpath = &hintinfo->dls_serpath[0];
hargs.strspace = (char *)&hintinfo->dls_serpath[hmeta.dls_cnt];
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs);
path_enumerate(p, fill_search_info, &hargs);
/*
* Now calculate the difference between two sets, by excluding
* standard paths from the full set.
*/
fndx = 0;
fcount = 0;
filtered_path = xmalloc(hdr.dirlistlen + 1);
hintpath = &hintinfo->dls_serpath[0];
for (hintndx = 0; hintndx < hmeta.dls_cnt; hintndx++, hintpath++) {
skip = false;
SLPpath = &SLPinfo->dls_serpath[0];
/*
* Check each standard path against current.
*/
for (SLPndx = 0; SLPndx < smeta.dls_cnt; SLPndx++, SLPpath++) {
/* matched, skip the path */
if (!strcmp(hintpath->dls_name, SLPpath->dls_name)) {
skip = true;
break;
}
}
if (skip)
continue;
/*
* Not matched against any standard path, add the path
* to result. Separate consequtive paths with ':'.
*/
if (fcount > 0) {
filtered_path[fndx] = ':';
fndx++;
}
fcount++;
flen = strlen(hintpath->dls_name);
strncpy((filtered_path + fndx), hintpath->dls_name, flen);
fndx += flen;
}
hints = p;
close(fd);
}
return hints[0] != '\0' ? hints : NULL;
filtered_path[fndx] = '\0';
free(SLPinfo);
free(hintinfo);
filt_ret:
return (filtered_path[0] != '\0' ? filtered_path : NULL);
}
static void
@ -1600,6 +1754,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
Obj_Entry objtmp; /* Temporary rtld object */
const Elf_Dyn *dyn_rpath;
const Elf_Dyn *dyn_soname;
const Elf_Dyn *dyn_runpath;
/*
* Conjure up an Obj_Entry structure for the dynamic linker.
@ -1616,7 +1771,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
#endif
if (RTLD_IS_DYNAMIC()) {
objtmp.dynamic = rtld_dynamic(&objtmp);
digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname);
digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname, &dyn_runpath);
assert(objtmp.needed == NULL);
#if !defined(__mips__)
/* MIPS has a bogus DT_TEXTREL. */
@ -1642,7 +1797,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
if (aux_info[AT_OSRELDATE] != NULL)
osreldate = aux_info[AT_OSRELDATE]->a_un.a_val;
digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname);
digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname, dyn_runpath);
/* Replace the path with a dynamically allocated copy. */
obj_rtld.path = xstrdup(PATH_RTLD);
@ -3070,14 +3225,6 @@ dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
return (error);
}
struct fill_search_info_args {
int request;
unsigned int flags;
Dl_serinfo *serinfo;
Dl_serpath *serpath;
char *strspace;
};
static void *
fill_search_info(const char *dir, size_t dirlen, void *param)
{
@ -3087,7 +3234,7 @@ fill_search_info(const char *dir, size_t dirlen, void *param)
if (arg->request == RTLD_DI_SERINFOSIZE) {
arg->serinfo->dls_cnt ++;
arg->serinfo->dls_size += sizeof(Dl_serpath) + dirlen + 1;
arg->serinfo->dls_size += sizeof(struct dl_serpath) + dirlen + 1;
} else {
struct dl_serpath *s_entry;
@ -3117,10 +3264,12 @@ do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info)
_info.dls_size = __offsetof(struct dl_serinfo, dls_serpath);
_info.dls_cnt = 0;
path_enumerate(ld_library_path, fill_search_info, &args);
path_enumerate(obj->rpath, fill_search_info, &args);
path_enumerate(gethints(), fill_search_info, &args);
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args);
path_enumerate(ld_library_path, fill_search_info, &args);
path_enumerate(obj->runpath, fill_search_info, &args);
path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args);
if (!obj->z_nodeflib)
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args);
if (request == RTLD_DI_SERINFOSIZE) {
@ -3139,20 +3288,26 @@ do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info)
args.serpath = &info->dls_serpath[0];
args.strspace = (char *)&info->dls_serpath[_info.dls_cnt];
args.flags = LA_SER_RUNPATH;
if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL)
return (-1);
args.flags = LA_SER_LIBPATH;
if (path_enumerate(ld_library_path, fill_search_info, &args) != NULL)
return (-1);
args.flags = LA_SER_RUNPATH;
if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL)
if (path_enumerate(obj->runpath, fill_search_info, &args) != NULL)
return (-1);
args.flags = LA_SER_CONFIG;
if (path_enumerate(gethints(), fill_search_info, &args) != NULL)
if (path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args)
!= NULL)
return (-1);
args.flags = LA_SER_DEFAULT;
if (path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL)
if (!obj->z_nodeflib &&
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL)
return (-1);
return (0);
}

View File

@ -222,6 +222,7 @@ typedef struct Struct_Obj_Entry {
const Elf_Hashelt *chain_zero_gnu; /* GNU hash table value array (Zeroed) */
char *rpath; /* Search path specified in object */
char *runpath; /* Search path with different priority */
Needed_Entry *needed; /* Shared objects needed by this one (%) */
Needed_Entry *needed_filtees;
Needed_Entry *needed_aux_filtees;
@ -258,6 +259,7 @@ typedef struct Struct_Obj_Entry {
bool z_nodelete : 1; /* Do not unload the object and dependencies */
bool z_noopen : 1; /* Do not load on dlopen */
bool z_loadfltr : 1; /* Immediately load filtees */
bool z_nodeflib : 1; /* Don't search default library path */
bool ref_nodel : 1; /* Refcount increased to prevent dlclose */
bool init_scanned: 1; /* Object is already on init list. */
bool on_fini_list: 1; /* Object is already on fini list. */
@ -321,6 +323,14 @@ struct Struct_RtldLockState {
sigjmp_buf env;
};
struct fill_search_info_args {
int request;
unsigned int flags;
struct dl_serinfo *serinfo;
struct dl_serpath *serpath;
char *strspace;
};
/*
* The pack of arguments and results for the symbol lookup functions.
*/