diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/ChangeLog | 18 | ||||
-rw-r--r-- | runtime/runtime.h | 3 | ||||
-rw-r--r-- | runtime/sym.c | 34 | ||||
-rw-r--r-- | runtime/task_finder.c | 22 | ||||
-rw-r--r-- | runtime/task_finder_vma.c | 30 |
5 files changed, 94 insertions, 13 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog index ffe0c57f..ca299a8c 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,21 @@ +2008-12-15 Mark Wielaard <mjw@redhat.com> + + * runtime.h: Just include task_finder.c instead of defining parts + of it here. + * sym.c (_stp_mod_sec_lookup): Add dbug_sym statements. + * task_finder_vma.c: Define __stp_tf_vma_entry here. + +2008-12-10 Mark Wielaard <mjw@redhat.com> + + * runtime.h: Define __stp_tf_vma_entry here. + * sym.c (_stp_mod_sec_lookup): Try vma matching first if task given. + (_stp_kallsyms_lookup): Take an optional task. + (_stp_symbol_snprint): Likewise. + task_finder.c (__stp_tf_vm_cb): Use vm_path to match and attach + module to vma entry. + task_finder_vma.c (stap_add_vma_map_info): Take an optional module. + (__stp_tf_get_vma_entry_addr): New lookup function. + 2009-01-20 David Smith <dsmith@redhat.com> PR 9673. diff --git a/runtime/runtime.h b/runtime/runtime.h index 3b3e117d..3ca43dc4 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -86,6 +86,9 @@ static struct #include "io.c" #include "arith.c" #include "copy.c" + +#include "task_finder.c" + #include "sym.c" #ifdef STP_PERFMON #include "perf.c" diff --git a/runtime/sym.c b/runtime/sym.c index 06ac14a5..82eef17d 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -77,11 +77,30 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi if found, return NULL otherwise. XXX: needs to be address-space-specific. */ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, + struct task_struct *task, struct _stp_section **sec) { struct _stp_module *m = NULL; unsigned midx = 0; unsigned long closest_section_offset = ~0; + + // Try vma matching first if task given. + struct __stp_tf_vma_entry *entry; + if (task) + { + entry = __stp_tf_get_vma_entry_addr(task, addr); + if (entry != NULL && entry->module != NULL) + { + m = entry->module; + *sec = &m->sections[0]; // XXX check actual section and relocate + dbug_sym(1, "found section %s in module %s at 0x%lx\n", + m->sections[0].name, m->name, entry->vm_start); + if (strcmp(".dynamic", m->sections[0].name) == 0) + m->sections[0].addr = entry->vm_start; // cheat... + return m; + } + } + for (midx = 0; midx < _stp_num_modules; midx++) { unsigned secidx; @@ -109,7 +128,8 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo unsigned long *offset, const char **modname, /* char ** secname? */ - char *namebuf) + char *namebuf, + struct task_struct *task) { struct _stp_module *m = NULL; struct _stp_section *sec = NULL; @@ -117,7 +137,7 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo unsigned long flags; unsigned end, begin = 0; - m = _stp_mod_sec_lookup(addr, &sec); + m = _stp_mod_sec_lookup(addr, task, &sec); if (unlikely (m == NULL || sec == NULL)) return NULL; @@ -242,7 +262,7 @@ void _stp_symbol_print(unsigned long address) const char *name; unsigned long offset, size; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL); _stp_printf("%p", (int64_t) address); @@ -267,7 +287,7 @@ int _stp_func_print(unsigned long address, int verbose, int exact) else exstr = " (inexact)"; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL); if (name) { if (verbose) { @@ -283,13 +303,15 @@ int _stp_func_print(unsigned long address, int verbose, int exact) return 0; } -void _stp_symbol_snprint(char *str, size_t len, unsigned long address) +void _stp_symbol_snprint(char *str, size_t len, unsigned long address, + struct task_struct *task) { const char *modname; const char *name; unsigned long offset, size; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, + task); if (name) strlcpy(str, name, len); else diff --git a/runtime/task_finder.c b/runtime/task_finder.c index f982eef1..31bccad8 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -55,7 +55,6 @@ typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff); -#ifdef DEBUG_TASK_FINDER_VMA int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, @@ -63,21 +62,32 @@ int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff) { + int i; +#ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); +#endif if (map_p) { - // FIXME: What should we do with vm_path? We can't save - // the vm_path pointer itself, but we don't have any - // storage space allocated to save it in... - stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); + struct _stp_module *module = NULL; + if (vm_path != NULL) + for (i = 0; i < _stp_num_modules; i++) + if (strcmp(vm_path, _stp_modules[i]->name) == 0) + { +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, + "vm_cb: matched path %s to module\n", vm_path); +#endif + module = _stp_modules[i]; + break; + } + stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); } else { stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); } return 0; } -#endif struct stap_task_finder_target { /* private: */ diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index 4dce4be8..87a32fe5 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -25,6 +25,9 @@ struct __stp_tf_vma_entry { unsigned long vm_end; unsigned long vm_pgoff; // Is that enough? Should we store a dcookie for vm_file? + + // Module that this vma entry is mapped from, if any. + struct _stp_module *module; }; static struct __stp_tf_vma_entry @@ -211,7 +214,8 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, // Add the vma info to the vma map hash table. static int stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, - unsigned long vm_end, unsigned long vm_pgoff) + unsigned long vm_end, unsigned long vm_pgoff, + struct _stp_module *module) { struct hlist_head *head; struct hlist_node *node; @@ -242,6 +246,7 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, entry->vm_start = vm_start; entry->vm_end = vm_end; entry->vm_pgoff = vm_pgoff; + entry->module = module; head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_add_head(&entry->hlist, head); @@ -305,3 +310,26 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, mutex_unlock(&__stp_tf_vma_mutex); return rc; } + +// Get vma_entry of the address (vm_start/vm_end) if the vma is +// present in the vma hash table containing. +// Returns NULL if not present. +static struct __stp_tf_vma_entry * +__stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr) +{ + struct hlist_head *head; + struct hlist_node *node; + struct __stp_tf_vma_entry *entry; + + mutex_lock(&__stp_tf_vma_mutex); + head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; + hlist_for_each_entry(entry, node, head, hlist) { + if (tsk->pid == entry->pid + && addr >= entry->vm_start && addr < entry->vm_end) { + mutex_unlock(&__stp_tf_vma_mutex); + return entry; + } + } + mutex_unlock(&__stp_tf_vma_mutex); + return NULL; +} |