function tracing from rtld

Simon 'corecode' Schubert corecode at fs.ei.tum.de
Sat Jan 5 15:20:27 PST 2008


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	_rtld_bind at 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




More information about the Submit mailing list