diff options
author | Mark Wielaard <mjw@redhat.com> | 2008-12-10 20:39:45 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2008-12-10 20:39:45 +0100 |
commit | d2f4d7286629da6e9f1b844beefb141a4d3ef2c3 (patch) | |
tree | ffcff9ea678de1196ad1d95a3ee6880eaf39e3df /runtime | |
parent | e8318a92c7b07579b89da5ff6fef782ce5d2b58c (diff) | |
download | systemtap-steved-d2f4d7286629da6e9f1b844beefb141a4d3ef2c3.tar.gz systemtap-steved-d2f4d7286629da6e9f1b844beefb141a4d3ef2c3.tar.xz systemtap-steved-d2f4d7286629da6e9f1b844beefb141a4d3ef2c3.zip |
PR6866: First pass at translating addresses to symbol names through vma.
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/ChangeLog | 11 | ||||
-rw-r--r-- | runtime/runtime.h | 18 | ||||
-rw-r--r-- | runtime/sym.c | 32 | ||||
-rw-r--r-- | runtime/task_finder.c | 22 | ||||
-rw-r--r-- | runtime/task_finder_vma.c | 38 |
5 files changed, 97 insertions, 24 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 3f88bae2..d83ac12c 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,14 @@ +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. + 2008-12-09 Frank Ch. Eigler <fche@elastic.org> * time.c (_stp_gettimeofday_ns): Protect some more against freq=0. diff --git a/runtime/runtime.h b/runtime/runtime.h index 3b3e117d..055d3f27 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -86,6 +86,24 @@ static struct #include "io.c" #include "arith.c" #include "copy.c" + +/* Lifted task_finder, internal details used in sym.c - XXX */ +struct __stp_tf_vma_entry { + struct hlist_node hlist; + + pid_t pid; + unsigned long addr; + unsigned long vm_start; + 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 * +__stp_tf_get_vma_entry_addr(struct task_struct *, unsigned long); + #include "sym.c" #ifdef STP_PERFMON #include "perf.c" diff --git a/runtime/sym.c b/runtime/sym.c index 06ac14a5..9b295f58 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -77,11 +77,28 @@ 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 + 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 +126,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 +135,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 +260,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 +285,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 +301,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 25fad1a4..1e0a8474 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..b65d9ea4 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -16,17 +16,6 @@ static DEFINE_MUTEX(__stp_tf_vma_mutex); #define TASK_FINDER_VMA_ENTRY_ITEMS 100 #endif -struct __stp_tf_vma_entry { - struct hlist_node hlist; - - pid_t pid; - unsigned long addr; - unsigned long vm_start; - unsigned long vm_end; - unsigned long vm_pgoff; - // Is that enough? Should we store a dcookie for vm_file? -}; - static struct __stp_tf_vma_entry __stp_tf_vma_free_list_items[TASK_FINDER_VMA_ENTRY_ITEMS]; @@ -211,7 +200,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 +232,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 +296,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; +} |