summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2005-12-24 15:37:30 +0000
committerkan <kan@FreeBSD.org>2005-12-24 15:37:30 +0000
commit7ed4cc5d2103c40bf23f0400f4b5a47c42d6e2a6 (patch)
tree56a73da288c87ec67d359baf1f4e7965fc53a38e /libexec
parentf4b582d6fe7067f326c6955dfb976bc7c4355861 (diff)
downloadFreeBSD-src-7ed4cc5d2103c40bf23f0400f4b5a47c42d6e2a6.zip
FreeBSD-src-7ed4cc5d2103c40bf23f0400f4b5a47c42d6e2a6.tar.gz
Make lookups for relocations from old unversioned binaries return
oldest versioned symbol available. Do not accept hidden symbols for all other versions. Use "<obj->path>: <error message>" for all error messages in new functions to make them more consistent.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/rtld.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 641d967..e164ef8 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -2425,10 +2425,25 @@ symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj,
obj->path, obj->strtab + symnum, verndx);
continue;
}
- if (verndx >= VER_NDX_GIVEN) {
- if (vsymp == NULL)
- vsymp = symp;
- vcount ++;
+ /*
+ * If we are not called from dlsym (i.e. this is a normal
+ * relocation from unversioned binary, accept the symbol
+ * immediately if it happens to have first version after
+ * this shared object became versioned. Otherwise, if
+ * symbol is versioned and not hidden, remember it. If it
+ * is the only symbol with this name exported by the
+ * shared object, it will be returned as a match at the
+ * end of the function. If symbol is global (verndx < 2)
+ * accept it unconditionally.
+ */
+ if ((flags & SYMLOOK_DLSYM) == 0 && verndx == VER_NDX_GIVEN)
+ return symp;
+ else if (verndx >= VER_NDX_GIVEN) {
+ if ((obj->versyms[symnum] & VER_NDX_HIDDEN) == 0) {
+ if (vsymp == NULL)
+ vsymp = symp;
+ vcount ++;
+ }
continue;
}
}
@@ -2451,8 +2466,8 @@ symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj,
if (obj->vertab[verndx].hash != ventry->hash ||
strcmp(obj->vertab[verndx].name, ventry->name)) {
/*
- * Version does not match. Look if this is a default symbol
- * and if it is not hidden. If default symbol (num < 2)
+ * Version does not match. Look if this is a global symbol
+ * and if it is not hidden. If global symbol (verndx < 2)
* is available, use it. Do not return symbol if we are
* called by dlvsym, because dlvsym looks for a specific
* version and default one is not what dlvsym wants.
@@ -2942,7 +2957,7 @@ free_tls_offset(Obj_Entry *obj)
* block, we give our space back to the 'allocator'. This is a
* simplistic workaround to allow libGL.so.1 to be loaded and
* unloaded multiple times. We only handle the Variant II
- * mechanism for now - this really needs a proper allocator.
+ * mechanism for now - this really needs a proper allocator.
*/
if (calculate_tls_end(obj->tlsoffset, obj->tlssize)
== calculate_tls_end(tls_last_offset, tls_last_size)) {
@@ -3018,8 +3033,8 @@ locate_dependency(const Obj_Entry *obj, const char *name)
if (object_match_name(needed->obj, name))
return needed->obj;
}
- _rtld_error("Unexpected inconsistency: %s not found in dependency list",
- name);
+ _rtld_error("%s: Unexpected inconsistency: dependency %s not found",
+ obj->path, name);
die();
}
@@ -3033,13 +3048,13 @@ check_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj,
vername = refobj->strtab + vna->vna_name;
vd = depobj->verdef;
if (vd == NULL) {
- _rtld_error("%s does not have version information, but %s requires it",
- depobj->path, refobj->path);
+ _rtld_error("%s: version %s required by %s not defined",
+ depobj->path, vername, refobj->path);
return (-1);
}
for (;;) {
if (vd->vd_version != VER_DEF_CURRENT) {
- _rtld_error("Unsupported version of Elf_Verdef entry in %s : %d",
+ _rtld_error("%s: Unsupported version %d of Elf_Verdef entry",
depobj->path, vd->vd_version);
return (-1);
}
@@ -3055,8 +3070,8 @@ check_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj,
}
if (vna->vna_flags & VER_FLG_WEAK)
return (0);
- _rtld_error("Version %s required by %s can not be found in %s", vername,
- refobj->path, depobj->path);
+ _rtld_error("%s: version %s required by %s not found",
+ depobj->path, vername, refobj->path);
return (-1);
}
@@ -3079,7 +3094,7 @@ rtld_verify_object_versions(Obj_Entry *obj)
vn = obj->verneed;
while (vn != NULL) {
if (vn->vn_version != VER_NEED_CURRENT) {
- _rtld_error("Unsupported version of Elf_Verneed entry in %s: %d",
+ _rtld_error("%s: Unsupported version %d of Elf_Verneed entry",
obj->path, vn->vn_version);
return (-1);
}
@@ -3100,8 +3115,8 @@ rtld_verify_object_versions(Obj_Entry *obj)
vd = obj->verdef;
while (vd != NULL) {
if (vd->vd_version != VER_DEF_CURRENT) {
- _rtld_error("Unsupported version of Elf_Verneed entry: %d",
- vd->vd_version);
+ _rtld_error("%s: Unsupported version %d of Elf_Verdef entry",
+ obj->path, vd->vd_version);
return (-1);
}
vernum = VER_DEF_IDX(vd->vd_ndx);
OpenPOWER on IntegriCloud