preliminary hack for running linux-flash under native firefox

Simon 'corecode' Schubert corecode at fs.ei.tum.de
Wed Oct 25 00:39:53 PDT 2006


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pgp00004.pgp
Type: application/octet-stream
Size: 252 bytes
Desc: "Description: OpenPGP digital signature"
URL: <http://lists.dragonflybsd.org/pipermail/kernel/attachments/20061025/96021340/attachment-0019.obj>


More information about the Kernel mailing list