From 14a55adf3628d7fa359a37f14bb7bf59f6cec53f Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Mon, 29 Oct 2001 10:10:10 +0000 Subject: [PATCH] Update rtld for the "new" ia64 ABI. In the old toolchain, the DT_INIT and DT_FINI tags pointed to fptr records. In 2.11.2, it points to the actuall address of the function. On IA64 you cannot just take an address of a function, store it in a function pointer variable and call it.. the function pointers point to a fptr data block that has the target gp and address in it. This is absolutely necessary for using the in-tree binutils toolchain, but (unfortunately) will not work with old shared libraries. Save your old ld-elf.so.1 if you want to use old ones still. Do not mix-and-match. This is a no-op change for i386 and alpha. Reviewed by: dfr --- libexec/rtld-elf/alpha/rtld_machdep.h | 3 +++ libexec/rtld-elf/amd64/rtld_machdep.h | 3 +++ libexec/rtld-elf/i386/rtld_machdep.h | 3 +++ libexec/rtld-elf/ia64/reloc.c | 12 ++++++++++++ libexec/rtld-elf/ia64/rtld_machdep.h | 1 + libexec/rtld-elf/rtld.c | 17 ++++++++++------- libexec/rtld-elf/rtld.h | 4 ++-- 7 files changed, 34 insertions(+), 9 deletions(-) diff --git a/libexec/rtld-elf/alpha/rtld_machdep.h b/libexec/rtld-elf/alpha/rtld_machdep.h index a461debd9799..11dd60c8fb86 100644 --- a/libexec/rtld-elf/alpha/rtld_machdep.h +++ b/libexec/rtld-elf/alpha/rtld_machdep.h @@ -40,6 +40,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *, Elf_Addr, #define make_function_pointer(def, defobj) \ ((defobj)->relocbase + (def)->st_value) +#define call_initfini_pointer(obj, target) \ + (((InitFunc)(target))()) + /* Atomic operations. */ int cmp0_and_store_int(volatile int *, int); void atomic_add_int(volatile int *, int); diff --git a/libexec/rtld-elf/amd64/rtld_machdep.h b/libexec/rtld-elf/amd64/rtld_machdep.h index a26394f48c70..e51194cf159f 100644 --- a/libexec/rtld-elf/amd64/rtld_machdep.h +++ b/libexec/rtld-elf/amd64/rtld_machdep.h @@ -49,6 +49,9 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define make_function_pointer(def, defobj) \ ((defobj)->relocbase + (def)->st_value) +#define call_initfini_pointer(obj, target) \ + (((InitFunc)(target))()) + static inline void atomic_decr_int(volatile int *p) { diff --git a/libexec/rtld-elf/i386/rtld_machdep.h b/libexec/rtld-elf/i386/rtld_machdep.h index a26394f48c70..e51194cf159f 100644 --- a/libexec/rtld-elf/i386/rtld_machdep.h +++ b/libexec/rtld-elf/i386/rtld_machdep.h @@ -49,6 +49,9 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define make_function_pointer(def, defobj) \ ((defobj)->relocbase + (def)->st_value) +#define call_initfini_pointer(obj, target) \ + (((InitFunc)(target))()) + static inline void atomic_decr_int(volatile int *p) { diff --git a/libexec/rtld-elf/ia64/reloc.c b/libexec/rtld-elf/ia64/reloc.c index 86b7ce6f2710..8ec68608f8a0 100644 --- a/libexec/rtld-elf/ia64/reloc.c +++ b/libexec/rtld-elf/ia64/reloc.c @@ -407,6 +407,18 @@ make_function_pointer(const Elf_Sym *sym, const Obj_Entry *obj) return fptrs[index]; } +void +call_initfini_pointer(const Obj_Entry *obj, Elf_Addr target) +{ + struct fptr fptr; + + fptr.gp = (Elf_Addr) obj->pltgot; + fptr.target = target; + dbg(" initfini: target=%p, gp=%p", + (void *) fptr.target, (void *) fptr.gp); + ((InitFunc) &fptr)(); +} + /* Initialize the special PLT entries. */ void init_pltgot(Obj_Entry *obj) diff --git a/libexec/rtld-elf/ia64/rtld_machdep.h b/libexec/rtld-elf/ia64/rtld_machdep.h index 74a3f62ce2a1..b4f8e2c3d1a6 100644 --- a/libexec/rtld-elf/ia64/rtld_machdep.h +++ b/libexec/rtld-elf/ia64/rtld_machdep.h @@ -47,6 +47,7 @@ struct Struct_Obj_Entry; Elf_Addr reloc_jmpslot(Elf_Addr *, Elf_Addr, const struct Struct_Obj_Entry *); void *make_function_pointer(const Elf_Sym *, const struct Struct_Obj_Entry *); +void call_initfini_pointer(const struct Struct_Obj_Entry *, Elf_Addr); /* Atomic operations. */ int cmp0_and_store_int(volatile int *, int); diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index fc6f2fa07fa1..94ea8fd7dfa0 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -625,11 +625,11 @@ digest_dynamic(Obj_Entry *obj) break; case DT_INIT: - obj->init = (InitFunc) (obj->relocbase + dynp->d_un.d_ptr); + obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_FINI: - obj->fini = (InitFunc) (obj->relocbase + dynp->d_un.d_ptr); + obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_DEBUG: @@ -639,7 +639,8 @@ digest_dynamic(Obj_Entry *obj) break; default: - dbg("Ignoring d_tag %d = %#x", dynp->d_tag, dynp->d_tag); + dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, + (long)dynp->d_tag); break; } } @@ -1248,8 +1249,9 @@ objlist_call_fini(Objlist *list) saved_msg = errmsg_save(); STAILQ_FOREACH(elm, list, link) { if (elm->obj->refcount == 0) { - dbg("calling fini function for %s", elm->obj->path); - (*elm->obj->fini)(); + dbg("calling fini function for %s at %p", elm->obj->path, + (void *)elm->obj->fini); + call_initfini_pointer(elm->obj, elm->obj->fini); } } errmsg_restore(saved_msg); @@ -1272,8 +1274,9 @@ objlist_call_init(Objlist *list) */ saved_msg = errmsg_save(); STAILQ_FOREACH(elm, list, link) { - dbg("calling init function for %s", elm->obj->path); - (*elm->obj->init)(); + dbg("calling init function for %s at %p", elm->obj->path, + (void *)elm->obj->init); + call_initfini_pointer(elm->obj, elm->obj->init); } errmsg_restore(saved_msg); } diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index c8cb39843431..b4250132ea3e 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -145,8 +145,8 @@ typedef struct Struct_Obj_Entry { const char *rpath; /* Search path specified in object */ Needed_Entry *needed; /* Shared objects needed by this one (%) */ - InitFunc init; /* Initialization function to call */ - InitFunc fini; /* Termination function to call */ + Elf_Addr init; /* Initialization function to call */ + Elf_Addr fini; /* Termination function to call */ bool mainprog; /* True if this is the main program */ bool rtld; /* True if this is the dynamic linker */