summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2008-12-10 20:39:45 +0100
committerMark Wielaard <mjw@redhat.com>2008-12-10 20:39:45 +0100
commitd2f4d7286629da6e9f1b844beefb141a4d3ef2c3 (patch)
treeffcff9ea678de1196ad1d95a3ee6880eaf39e3df /runtime
parente8318a92c7b07579b89da5ff6fef782ce5d2b58c (diff)
downloadsystemtap-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/ChangeLog11
-rw-r--r--runtime/runtime.h18
-rw-r--r--runtime/sym.c32
-rw-r--r--runtime/task_finder.c22
-rw-r--r--runtime/task_finder_vma.c38
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;
+}