diff options
author | dfr <dfr@FreeBSD.org> | 2001-10-15 18:48:42 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2001-10-15 18:48:42 +0000 |
commit | 7d69aa453630c63bba640d287d0781db518b5a53 (patch) | |
tree | 58745c0bcc233d2e6a7a5aae303d27432c4dd053 /libexec/rtld-elf/rtld.c | |
parent | 8d45c0568791bbcc1147afa6e857e7b307c43c11 (diff) | |
download | FreeBSD-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.c | 43 |
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); |