mirror of
https://git.musl-libc.org/git/musl
synced 2025-02-24 06:04:36 +03:00
add recursive rpath support to dynamic linker
previously, rpath was only honored for direct dependencies. in other words, if A depends on B and B depends on C, only B's rpath (if any), not A's rpath, was being searched for C. this limitation made rpath-based deployment difficult in the presence of multiple levels of library dependency. at present, $ORIGIN processing in rpath is still unsupported.
This commit is contained in:
parent
8b491f1499
commit
709355e1f6
@ -72,7 +72,8 @@ struct dso {
|
|||||||
signed char global;
|
signed char global;
|
||||||
char relocated;
|
char relocated;
|
||||||
char constructed;
|
char constructed;
|
||||||
struct dso **deps;
|
struct dso **deps, *needed_by;
|
||||||
|
char *rpath;
|
||||||
void *tls_image;
|
void *tls_image;
|
||||||
size_t tls_len, tls_size, tls_align, tls_id, tls_offset;
|
size_t tls_len, tls_size, tls_align, tls_id, tls_offset;
|
||||||
void **new_dtv;
|
void **new_dtv;
|
||||||
@ -95,7 +96,7 @@ void *__install_initial_tls(void *);
|
|||||||
void __init_libc(char **, char *);
|
void __init_libc(char **, char *);
|
||||||
|
|
||||||
static struct dso *head, *tail, *ldso, *fini_head;
|
static struct dso *head, *tail, *ldso, *fini_head;
|
||||||
static char *env_path, *sys_path, *r_path;
|
static char *env_path, *sys_path;
|
||||||
static unsigned long long gencnt;
|
static unsigned long long gencnt;
|
||||||
static int ssp_used;
|
static int ssp_used;
|
||||||
static int runtime;
|
static int runtime;
|
||||||
@ -455,13 +456,15 @@ static void decode_dyn(struct dso *p)
|
|||||||
p->strings = (void *)(p->base + dyn[DT_STRTAB]);
|
p->strings = (void *)(p->base + dyn[DT_STRTAB]);
|
||||||
if (dyn[0]&(1<<DT_HASH))
|
if (dyn[0]&(1<<DT_HASH))
|
||||||
p->hashtab = (void *)(p->base + dyn[DT_HASH]);
|
p->hashtab = (void *)(p->base + dyn[DT_HASH]);
|
||||||
|
if (dyn[0]&(1<<DT_RPATH))
|
||||||
|
p->rpath = (void *)(p->strings + dyn[DT_RPATH]);
|
||||||
if (search_vec(p->dynv, dyn, DT_GNU_HASH))
|
if (search_vec(p->dynv, dyn, DT_GNU_HASH))
|
||||||
p->ghashtab = (void *)(p->base + *dyn);
|
p->ghashtab = (void *)(p->base + *dyn);
|
||||||
if (search_vec(p->dynv, dyn, DT_VERSYM))
|
if (search_vec(p->dynv, dyn, DT_VERSYM))
|
||||||
p->versym = (void *)(p->base + *dyn);
|
p->versym = (void *)(p->base + *dyn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dso *load_library(const char *name)
|
static struct dso *load_library(const char *name, struct dso *needed_by)
|
||||||
{
|
{
|
||||||
char buf[2*NAME_MAX+2];
|
char buf[2*NAME_MAX+2];
|
||||||
const char *pathname;
|
const char *pathname;
|
||||||
@ -521,7 +524,9 @@ static struct dso *load_library(const char *name)
|
|||||||
if (strlen(name) > NAME_MAX) return 0;
|
if (strlen(name) > NAME_MAX) return 0;
|
||||||
fd = -1;
|
fd = -1;
|
||||||
if (env_path) fd = path_open(name, env_path, buf, sizeof buf);
|
if (env_path) fd = path_open(name, env_path, buf, sizeof buf);
|
||||||
if (fd < 0 && r_path) fd = path_open(name, r_path, buf, sizeof buf);
|
for (p=needed_by; fd < 0 && p; p=p->needed_by)
|
||||||
|
if (p->rpath)
|
||||||
|
fd = path_open(name, p->rpath, buf, sizeof buf);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (!sys_path) {
|
if (!sys_path) {
|
||||||
char *prefix = 0;
|
char *prefix = 0;
|
||||||
@ -601,6 +606,7 @@ static struct dso *load_library(const char *name)
|
|||||||
p->dev = st.st_dev;
|
p->dev = st.st_dev;
|
||||||
p->ino = st.st_ino;
|
p->ino = st.st_ino;
|
||||||
p->refcnt = 1;
|
p->refcnt = 1;
|
||||||
|
p->needed_by = needed_by;
|
||||||
p->name = p->buf;
|
p->name = p->buf;
|
||||||
strcpy(p->name, pathname);
|
strcpy(p->name, pathname);
|
||||||
/* Add a shortname only if name arg was not an explicit pathname. */
|
/* Add a shortname only if name arg was not an explicit pathname. */
|
||||||
@ -642,13 +648,9 @@ static void load_deps(struct dso *p)
|
|||||||
size_t i, ndeps=0;
|
size_t i, ndeps=0;
|
||||||
struct dso ***deps = &p->deps, **tmp, *dep;
|
struct dso ***deps = &p->deps, **tmp, *dep;
|
||||||
for (; p; p=p->next) {
|
for (; p; p=p->next) {
|
||||||
for (i=0; p->dynv[i]; i+=2) {
|
|
||||||
if (p->dynv[i] != DT_RPATH) continue;
|
|
||||||
r_path = (void *)(p->strings + p->dynv[i+1]);
|
|
||||||
}
|
|
||||||
for (i=0; p->dynv[i]; i+=2) {
|
for (i=0; p->dynv[i]; i+=2) {
|
||||||
if (p->dynv[i] != DT_NEEDED) continue;
|
if (p->dynv[i] != DT_NEEDED) continue;
|
||||||
dep = load_library(p->strings + p->dynv[i+1]);
|
dep = load_library(p->strings + p->dynv[i+1], p);
|
||||||
if (!dep) {
|
if (!dep) {
|
||||||
snprintf(errbuf, sizeof errbuf,
|
snprintf(errbuf, sizeof errbuf,
|
||||||
"Error loading shared library %s: %m (needed by %s)",
|
"Error loading shared library %s: %m (needed by %s)",
|
||||||
@ -666,7 +668,6 @@ static void load_deps(struct dso *p)
|
|||||||
*deps = tmp;
|
*deps = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r_path = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,7 +680,7 @@ static void load_preload(char *s)
|
|||||||
for (z=s; *z && !isspace(*z); z++);
|
for (z=s; *z && !isspace(*z); z++);
|
||||||
tmp = *z;
|
tmp = *z;
|
||||||
*z = 0;
|
*z = 0;
|
||||||
load_library(s);
|
load_library(s, 0);
|
||||||
*z = tmp;
|
*z = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1153,7 +1154,7 @@ void *dlopen(const char *file, int mode)
|
|||||||
p = 0;
|
p = 0;
|
||||||
errflag = 1;
|
errflag = 1;
|
||||||
goto end;
|
goto end;
|
||||||
} else p = load_library(file);
|
} else p = load_library(file, 0);
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
snprintf(errbuf, sizeof errbuf, noload ?
|
snprintf(errbuf, sizeof errbuf, noload ?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user