From: | "Simon 'corecode' Schubert" <corecode@xxxxxxxxxxxx> |
Date: | Wed, 25 Oct 2006 09:22:56 +0200 |
cheers simon
-- Serve - BSD +++ RENT this banner advert +++ ASCII Ribbon /"\ Work - Mac +++ space for low €€€ NOW!1 +++ Campaign \ / Party Enjoy Relax | http://dragonflybsd.org Against HTML \ Dude 2c 2 the max ! http://golden-apple.biz Mail + News / \
Index: Makefile =================================================================== RCS file: /home/dcvs/src/libexec/rtld-elf/Makefile,v retrieving revision 1.12 diff -u -r1.12 Makefile --- Makefile 19 Nov 2005 22:00:20 -0000 1.12 +++ Makefile 25 Oct 2006 07:19:58 -0000 @@ -14,6 +14,8 @@ MLINKS= rtld.1 ld-elf.so.1.1 MLINKS+= rtld.1 ld-elf.so.2.1 +INCS+= rtld_wrap.h + .if exists(${.CURDIR}/${MACHINE_ARCH}/Makefile.inc) .include "${.CURDIR}/${MACHINE_ARCH}/Makefile.inc" .endif Index: rtld.c =================================================================== RCS file: /home/dcvs/src/libexec/rtld-elf/rtld.c,v retrieving revision 1.24 diff -u -r1.24 rtld.c --- rtld.c 16 Jul 2006 22:15:38 -0000 1.24 +++ rtld.c 22 Oct 2006 12:08:27 -0000 @@ -771,7 +771,8 @@ break; default: - dbg("Ignoring d_tag %d = %#x", dynp->d_tag, dynp->d_tag); + if (obj != &obj_rtld) + dbg("Ignoring d_tag %d = %#x", dynp->d_tag, dynp->d_tag); break; } } @@ -943,6 +944,9 @@ return xstrdup(name); } + if (refobj && refobj->wrapper_func) + name = refobj->wrapper_func(WRAP_OP_SONAME, refobj->path, name); + dbg(" Searching for \"%s\"", name); if ((pathname = search_library_path(name, ld_library_path)) != NULL || @@ -993,6 +997,11 @@ hash = elf_hash(name); defobj = NULL; + if (refobj->wrapper_func != NULL) { + name = refobj->wrapper_func(WRAP_OP_SYMNAME, refobj->path, name); + hash = elf_hash(name); + } + def = symlook_default(name, hash, refobj, &defobj, in_plt); /* @@ -1301,6 +1310,49 @@ return(obj); } +static void +load_wrapper_object(Obj_Entry *obj) +{ + char *wrapper_path; + Obj_Entry *wrapper_obj = NULL; + Obj_Entry **old_objtail; + const Elf_Sym *wrap_func_sym; + const char *wrap_func_name = "__wrapper_func"; + unsigned long hash = elf_hash(wrap_func_name); + int result; + + /* Save the tail so that we can remove the wrapper from the list */ + old_objtail = obj_tail; + + wrapper_path = xmalloc(strlen(obj->path) + strlen(".wrapper") + 1); + strcpy(wrapper_path, obj->path); + strcat(wrapper_path, ".wrapper"); + + wrapper_obj = load_object(wrapper_path); + if (wrapper_obj == NULL) { + free(wrapper_path); + return; + } + + result = load_needed_objects(obj); + + if (result == -1 || + (init_dag(wrapper_obj), relocate_objects(wrapper_obj, true)) == -1) { + unref_dag(wrapper_obj); + if (wrapper_obj->refcount == 0) + unload_object(wrapper_obj); + return; + } + + wrap_func_sym = symlook_obj(wrap_func_name, hash, wrapper_obj, true); + if (wrap_func_sym != NULL) + obj->wrapper_func = (wrapper_func)(wrapper_obj->relocbase + wrap_func_sym->st_value); + + /* Hide the wrapper object from the list */ + obj_tail = old_objtail; + obj->wrapper_obj = wrapper_obj; +} + /* * Load a shared object into memory, if it is not already loaded. The * argument must be a string allocated on the heap. This function assumes @@ -1334,6 +1386,7 @@ } dbg("loading \"%s\"", path); + obj = map_object(fd, path, &sb); close(fd); if (obj == NULL) { @@ -1342,6 +1395,9 @@ } obj->path = path; + + load_wrapper_object(obj); + digest_dynamic(obj); *obj_tail = obj; @@ -1816,25 +1872,34 @@ dlsym(void *handle, const char *name) { const Obj_Entry *obj; + const Obj_Entry *callobj; unsigned long hash; const Elf_Sym *def; const Obj_Entry *defobj; + void *retaddr; hash = elf_hash(name); def = NULL; defobj = NULL; rlock_acquire(); + retaddr = __builtin_return_address(0); /* __GNUC__ only */ + if ((callobj = obj_from_addr(retaddr)) != NULL && + callobj->wrapper_func != NULL) { + handle = callobj->wrapper_func(WRAP_OP_HANDLE, callobj->path, handle); + name = callobj->wrapper_func(WRAP_OP_SYMNAME, callobj->path, name); + hash = elf_hash(name); + } + if (handle == NULL || handle == RTLD_NEXT || handle == RTLD_DEFAULT || handle == RTLD_SELF) { - void *retaddr; - retaddr = __builtin_return_address(0); /* __GNUC__ only */ - if ((obj = obj_from_addr(retaddr)) == NULL) { + if (callobj == NULL) { _rtld_error("Cannot determine caller's shared object"); rlock_release(); return NULL; } + obj = callobj; if (handle == NULL) { /* Just the caller's shared object. */ def = symlook_obj(name, hash, obj, true); defobj = obj; @@ -2279,6 +2344,16 @@ } } + /* Search the wrapper */ + if (refobj->wrapper_obj != NULL && + (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK)) { + symp = symlook_obj(name, hash, refobj->wrapper_obj, in_plt); + if (symp != NULL) { + def = symp; + defobj = refobj->wrapper_obj; + } + } + /* Search all objects loaded at program start up. */ if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { symp = symlook_list(name, hash, &list_main, &obj, in_plt, &donelist); Index: rtld.h =================================================================== RCS file: /home/dcvs/src/libexec/rtld-elf/rtld.h,v retrieving revision 1.11 diff -u -r1.11 rtld.h --- rtld.h 11 May 2005 19:47:06 -0000 1.11 +++ rtld.h 22 Oct 2006 11:05:54 -0000 @@ -38,6 +38,7 @@ #include <stddef.h> #include "rtld_machdep.h" +#include "rtld_wrap.h" #ifndef STANDARD_LIBRARY_PATH #define STANDARD_LIBRARY_PATH "/usr/lib" @@ -181,6 +182,9 @@ Objlist dagmembers; /* DAG has these members (%) */ dev_t dev; /* Object's filesystem's device */ ino_t ino; /* Object's inode number */ + + struct Struct_Obj_Entry *wrapper_obj; /* Object's wrapper DSO */ + wrapper_func wrapper_func; /* Object's translator func */ } Obj_Entry; #define RTLD_MAGIC 0xd550b87a Index: rtld_wrap.h =================================================================== RCS file: rtld_wrap.h diff -N rtld_wrap.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ rtld_wrap.h 22 Oct 2006 12:08:24 -0000 @@ -0,0 +1,5 @@ +#define WRAP_OP_SONAME 1 +#define WRAP_OP_SYMNAME 2 +#define WRAP_OP_HANDLE 3 + +typedef void *(*wrapper_func)(int, const char *, const void *);
Attachment:
signature.asc
Description: OpenPGP digital signature