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@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