Add _rtld_functrace support.
authorSimon Schubert <corecode@dragonflybsd.org>
Tue, 8 Jan 2008 00:02:04 +0000 (00:02 +0000)
committerSimon Schubert <corecode@dragonflybsd.org>
Tue, 8 Jan 2008 00:02:04 +0000 (00:02 +0000)
Joint-work-with:  aggelos@

libexec/rtld-elf/i386/rtld_start.S
libexec/rtld-elf/rtld.1
libexec/rtld-elf/rtld.c

index fd2f74c..b5446ca 100644 (file)
@@ -23,7 +23,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/libexec/rtld-elf/i386/rtld_start.S,v 1.3 1999/08/28 00:10:15 peter Exp $
- * $DragonFly: src/libexec/rtld-elf/i386/rtld_start.S,v 1.3 2004/01/20 18:46:21 dillon Exp $
+ * $DragonFly: src/libexec/rtld-elf/i386/rtld_start.S,v 1.4 2008/01/08 00:02:04 corecode Exp $
  */
 
        .text
@@ -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    _rtld_bind@PLT          # 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
index 4100db6..8fff496 100644 (file)
@@ -1,5 +1,5 @@
 .\" $FreeBSD: src/libexec/rtld-elf/rtld.1,v 1.18.2.7 2002/01/10 17:51:28 ru Exp $
-.\" $DragonFly: src/libexec/rtld-elf/rtld.1,v 1.5 2006/02/11 21:32:41 swildner Exp $
+.\" $DragonFly: src/libexec/rtld-elf/rtld.1,v 1.6 2008/01/08 00:02:04 corecode Exp $
 .\"
 .\" Copyright (c) 1995 Paul Kranenburg
 .\" All rights reserved.
@@ -29,7 +29,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 28, 2000
+.Dd January 7, 2008
 .Dt RTLD 1
 .Os
 .Sh NAME
@@ -146,6 +146,37 @@ and
 .Ql \et
 are recognized and have their usual meaning.
 .El
+.Pp
+If a shared object preloaded by the
+.Ev LD_PRELOAD
+mechanism contains a public symbol
+.Dq _rtld_functrace ,
+.Nm
+will transfer control to this function each time
+it needs to resolve an unbound function symbol.
+By returning a non-zero value,
+.Fn _rtld_functrace
+can advise the linker to keep tracing the specified
+combination of caller shared object and called function;
+returning 0 will prevent
+.Fn _rtld_functrace
+to be called for this combination again.
+.Pp
+When implementing a custom
+.Fn _rtld_functrace
+function, be aware of the possibility that
+.Fn _rtld_functrace
+might be called for functions called on its behalf,
+or that multiple threads could enter
+.Fn _rtld_functrace
+at the same time.
+.Pp
+The signature for
+.Fn _rtld_functrace
+is specified as follows.
+.Pp
+.Ft int
+.Fn _rtld_functrace "const char *callerso" "const char *calleeso" "const char *calleefun" "void *stack"
 .Sh DIFFERENCES BETWEEN .1 and .2
 ABI changes have been made to support TLS allocation and initialization
 and to give threading libraries a chance to complete initialization of the
index 73050c9..2f2e625 100644 (file)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/libexec/rtld-elf/rtld.c,v 1.43.2.15 2003/02/20 20:42:46 kan Exp $
- * $DragonFly: src/libexec/rtld-elf/rtld.c,v 1.28 2007/11/25 18:10:06 swildner Exp $
+ * $DragonFly: src/libexec/rtld-elf/rtld.c,v 1.29 2008/01/08 00:02:04 corecode Exp $
  */
 
 /*
@@ -147,6 +147,12 @@ static const char *ld_library_path; /* Environment variable for search path */
 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 reloff)
     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;
 }