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