Hey,

on my quest to get firefox/thunderbird working with libthread_xu, Aggelos and me developed a nice hook for rtld to trace function calls in dynamically linked binaries.

What do people think, should we add this to rtld?  It's quite small.

cheers
  simon
Index: rtld.c
===================================================================
RCS file: /home/repos/cvs/dragonfly/src/libexec/rtld-elf/rtld.c,v
retrieving revision 1.28
diff -u -p -r1.28 rtld.c
--- rtld.c      25 Nov 2007 18:10:06 -0000      1.28
+++ rtld.c      31 Dec 2007 17:39:18 -0000
@@ -147,6 +147,12 @@ static const char *ld_library_path; /* E
 static char *ld_preload;       /* Environment variable for libraries to
                                   load first */
 static const char *ld_tracing; /* Called from ldd(1) to print libs */
+                               /* Optional function call tracing hook */
+static int (*rtld_functrace)(const char *caller_obj,
+                            const char *callee_obj,
+                            const char *callee_func,
+                            void *stack);
+static Obj_Entry *rtld_functrace_obj;  /* Object thereof */
 static Obj_Entry *obj_list;    /* Head of linked list of shared objects */
 static Obj_Entry **obj_tail;   /* Link field of last object in list */
 static Obj_Entry **preload_tail;
@@ -536,13 +542,14 @@ _rtld_call_init(void)
 }
 
 Elf_Addr
-_rtld_bind(Obj_Entry *obj, Elf_Word reloff)
+_rtld_bind(Obj_Entry *obj, Elf_Word reloff, void *stack)
 {
     const Elf_Rel *rel;
     const Elf_Sym *def;
     const Obj_Entry *defobj;
     Elf_Addr *where;
     Elf_Addr target;
+    int do_reloc = 1;
 
     rlock_acquire();
     if (obj->pltrel)
@@ -560,9 +567,27 @@ _rtld_bind(Obj_Entry *obj, Elf_Word relo
     dbg("\"%s\" in \"%s\" ==> %p in \"%s\"",
       defobj->strtab + def->st_name, basename(obj->path),
       (void *)target, basename(defobj->path));
-
-    reloc_jmpslot(where, target);
     rlock_release();
+
+    /*
+     * If we have a function call tracing hook, and the
+     * hook would like to keep tracing this one function,
+     * prevent the relocation so we will wind up here
+     * the next time again.
+     *
+     * We don't want to functrace calls from the functracer
+     * to avoid recursive loops.
+     */
+    if (rtld_functrace != NULL && obj != rtld_functrace_obj) {
+       if (rtld_functrace(obj->path,
+                          defobj->path,
+                          defobj->strtab + def->st_name,
+                          stack))
+           do_reloc = 0;
+    }
+
+    if (do_reloc)
+       reloc_jmpslot(where, target);
     return target;
 }
 
@@ -1246,6 +1271,8 @@ load_needed_objects(Obj_Entry *first)
     return 0;
 }
 
+#define RTLD_FUNCTRACE "_rtld_functrace"
+
 static int
 load_preload_objects(void)
 {
@@ -1260,16 +1287,26 @@ load_preload_objects(void)
        size_t len = strcspn(p, delim);
        char *path;
        char savech;
+       Obj_Entry *obj;
+       const Elf_Sym *sym;
 
        savech = p[len];
        p[len] = '\0';
        if ((path = find_library(p, NULL)) == NULL)
            return -1;
-       if (load_object(path) == NULL)
+       obj = load_object(path);
+       if (obj == NULL)
            return -1;  /* XXX - cleanup */
        p[len] = savech;
        p += len;
        p += strspn(p, delim);
+
+       /* Check for the magic tracing function */
+       sym = symlook_obj(RTLD_FUNCTRACE, elf_hash(RTLD_FUNCTRACE), obj, true);
+       if (sym != NULL) {
+               rtld_functrace = (void *)(obj->relocbase + sym->st_value);
+               rtld_functrace_obj = obj;
+       }
     }
     return 0;
 }
Index: i386/rtld_start.S
===================================================================
RCS file: /home/repos/cvs/dragonfly/src/libexec/rtld-elf/i386/rtld_start.S,v
retrieving revision 1.3
diff -u -p -r1.3 rtld_start.S
--- i386/rtld_start.S   20 Jan 2004 18:46:21 -0000      1.3
+++ i386/rtld_start.S   30 Dec 2007 21:42:15 -0000
@@ -75,13 +75,15 @@ _rtld_bind_start:
        pushl   %eax                    # Save %eax
        pushl   %edx                    # Save %edx
        pushl   %ecx                    # Save %ecx
-       pushl   20(%esp)                # Copy reloff argument
-       pushl   20(%esp)                # Copy obj argument
+       leal    24(%esp),%eax           # Calculate original stack addr
+       pushl   %eax                    # Pass stack addr as 3. arg
+       pushl   24(%esp)                # Copy reloff argument
+       pushl   24(%esp)                # Copy obj argument
 
        call    [EMAIL PROTECTED]               # Transfer control to the binder
        /* Now %eax contains the entry point of the function being called. */
 
-       addl    $8,%esp                 # Discard binder arguments
+       addl    $12,%esp                # Discard binder arguments
        movl    %eax,20(%esp)           # Store target over obj argument
        popl    %ecx                    # Restore %ecx
        popl    %edx                    # Restore %edx

Reply via email to