Bug #907 ยป rtld_functrace.diff
rtld.c 31 Dec 2007 17:39:18 -0000 | ||
---|---|---|
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;
|
||
... | ... | |
}
|
||
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)
|
||
... | ... | |
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;
|
||
}
|
||
... | ... | |
return 0;
|
||
}
|
||
#define RTLD_FUNCTRACE "_rtld_functrace"
|
||
static int
|
||
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;
|
||
}
|
i386/rtld_start.S 30 Dec 2007 21:42:15 -0000 | ||
---|---|---|
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
|