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