hey,

i have a patch for rtld which enables wrapping of linux shared objects.  i'd 
appreciate review and comments.  if wanted, i can post the diffs to the 
linuxpluginwrapper so that people can try flash.

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

Reply via email to