summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf/rtld.c
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2001-10-15 18:48:42 +0000
committerdfr <dfr@FreeBSD.org>2001-10-15 18:48:42 +0000
commit7d69aa453630c63bba640d287d0781db518b5a53 (patch)
tree58745c0bcc233d2e6a7a5aae303d27432c4dd053 /libexec/rtld-elf/rtld.c
parent8d45c0568791bbcc1147afa6e857e7b307c43c11 (diff)
downloadFreeBSD-src-7d69aa453630c63bba640d287d0781db518b5a53.zip
FreeBSD-src-7d69aa453630c63bba640d287d0781db518b5a53.tar.gz
Add ia64 support. Various adjustments were made to existing targets to
cope with a few interface changes required by the ia64. In particular, function pointers on ia64 need special treatment in rtld.
Diffstat (limited to 'libexec/rtld-elf/rtld.c')
-rw-r--r--libexec/rtld-elf/rtld.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 3b67cb5..fc6f2fa 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -437,7 +437,14 @@ _rtld_bind(Obj_Entry *obj, Elf_Word reloff)
defobj->strtab + def->st_name, basename(obj->path),
(void *)target, basename(defobj->path));
- reloc_jmpslot(where, target);
+ /*
+ * Write the new contents for the jmpslot. Note that depending on
+ * architecture, the value which we need to return back to the
+ * lazy binding trampoline may or may not be the target
+ * address. The value returned from reloc_jmpslot() is the value
+ * that the trampoline needs.
+ */
+ target = reloc_jmpslot(where, target, defobj);
rlock_release();
return target;
}
@@ -572,7 +579,7 @@ digest_dynamic(Obj_Entry *obj)
case DT_HASH:
{
- const Elf_Addr *hashtab = (const Elf_Addr *)
+ const Elf_Hashelt *hashtab = (const Elf_Hashelt *)
(obj->relocbase + dynp->d_un.d_ptr);
obj->nbuckets = hashtab[0];
obj->nchains = hashtab[1];
@@ -863,8 +870,10 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
cache[symnum].sym = def;
cache[symnum].obj = defobj;
}
- } else
- _rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name);
+ } else {
+ if (refobj != &obj_rtld)
+ _rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name);
+ }
return def;
}
@@ -1031,15 +1040,19 @@ initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list)
objlist_push_head(&list_fini, obj);
}
+#ifndef FPTR_TARGET
+#define FPTR_TARGET(f) ((Elf_Addr) (f))
+#endif
+
static bool
is_exported(const Elf_Sym *def)
{
- func_ptr_type value;
+ Elf_Addr value;
const func_ptr_type *p;
- value = (func_ptr_type)(obj_rtld.relocbase + def->st_value);
- for (p = exports; *p != NULL; p++)
- if (*p == value)
+ value = (Elf_Addr)(obj_rtld.relocbase + def->st_value);
+ for (p = exports; *p != NULL; p++)
+ if (FPTR_TARGET(*p) == value)
return true;
return false;
}
@@ -1651,7 +1664,19 @@ dlsym(void *handle, const char *name)
if (def != NULL) {
rlock_release();
- return defobj->relocbase + def->st_value;
+
+ /*
+ * The value required by the caller is derived from the value
+ * of the symbol. For the ia64 architecture, we need to
+ * construct a function descriptor which the caller can use to
+ * call the function with the right 'gp' value. For other
+ * architectures and for non-functions, the value is simply
+ * the relocated value of the symbol.
+ */
+ if (ELF_ST_TYPE(def->st_info) == STT_FUNC)
+ return make_function_pointer(def, defobj);
+ else
+ return defobj->relocbase + def->st_value;
}
_rtld_error("Undefined symbol \"%s\"", name);
OpenPOWER on IntegriCloud