From 35f71b69bb66beaaf2b583c2547169a7fbf90cda Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Sun, 7 Nov 2010 17:09:57 -0500 Subject: [PATCH] PR11811 prep: save full mmpath for found vmas Extend the print_*backtrace symbol names with the full path of the user-space ELF module, not just the basename. This requires saving a char[] copy in the __stp_tf_vma_entry structure instead of a char* pointing into a dentry.d_name. -DTASK_FINDER_VMA_ENTRY_PATHLEN governs copy length. * runtime/task_finder_vma.c (__stp_tf_vma_entry): Change char*name -> char[]path field. Update manipulating functions accordingly. * runtime/vma.c (_stp_vma_mmap_cb): Pass mmpath to tf-vma table if available. * testsuite/systemtap.context/usymbols.exp: Update for expected full path in output string. * NEWS: Mention change. * runtime/sym.h (_STP_SYM_MODULE_BASENAME): New flag. (_STP_SYM_SIMPLE): Include it. * runtime/sym.c (_stp_snprint_addr): Process it. --- NEWS | 5 ++++ runtime/sym.c | 4 +++ runtime/sym.h | 4 ++- runtime/task_finder_vma.c | 34 +++++++++++++++++------- runtime/vma.c | 9 ++++--- testsuite/systemtap.context/usymbols.exp | 4 +-- 6 files changed, 45 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index 0e5e86359..819d8f038 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ * What's new in version 1.4 +- The print_ubacktrace and usym* functions attempt to print the full + path of the user-space binaries' paths, instead of just the basename. + The maximum saved path length is set by -DTASK_FINDER_VMA_ENTRY_PATHLEN, + default 64. + - The new tz_ctime() tapset function prints times in the local time zone. - More kernel tracepoints are accessible to the kernel.trace("...") mechanism, diff --git a/runtime/sym.c b/runtime/sym.c index 0fc050044..e11f6d14e 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -392,6 +392,10 @@ static int _stp_snprint_addr(char *str, size_t len, unsigned long address, if (flags & (_STP_SYM_SYMBOL | _STP_SYM_MODULE)) name = _stp_kallsyms_lookup(address, &size, &offset, &modname, task); + if (modname && (flags & _STP_SYM_MODULE_BASENAME)) { + modname = strrchr (modname, '/') ?: modname; + } + if (name && (flags & _STP_SYM_SYMBOL)) { if ((flags & _STP_SYM_MODULE) && modname && *modname) { if (flags & _STP_SYM_OFFSET) { diff --git a/runtime/sym.h b/runtime/sym.h index 55d02d5c6..a16ca022d 100644 --- a/runtime/sym.h +++ b/runtime/sym.h @@ -33,6 +33,8 @@ #define _STP_SYM_POST_SPACE 128 /* Adds a newline character, doesn't combine with _STP_SYM_POST_SPACE. */ #define _STP_SYM_NEWLINE 256 +/* Adds only module " [`basename name`]" if found, use with _STP_SYM_MODULE. */ +#define _STP_SYM_MODULE_BASENAME 512 /* Used for backtraces in hex string form. */ #define _STP_SYM_NONE (_STP_SYM_HEXSTR | _STP_SYM_POST_SPACE) @@ -44,7 +46,7 @@ | _STP_SYM_SIZE | _STP_SYM_PRE_SPACE \ | _STP_SYM_NEWLINE) /* Simple symbol format, as used in backtraces for strings. */ -#define _STP_SYM_SIMPLE (_STP_SYM_SYMBOL | _STP_SYM_MODULE \ +#define _STP_SYM_SIMPLE (_STP_SYM_SYMBOL | _STP_SYM_MODULE | _STP_SYM_MODULE_BASENAME \ | _STP_SYM_OFFSET | _STP_SYM_NEWLINE) /* All symbol information (as used by [u]symdata). */ #define _STP_SYM_DATA (_STP_SYM_SYMBOL | _STP_SYM_MODULE \ diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index d57ec5d81..7ea695570 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -28,13 +28,20 @@ static DEFINE_RWLOCK(__stp_tf_vma_lock); #define TASK_FINDER_VMA_ENTRY_ITEMS 1536 #endif +#ifndef TASK_FINDER_VMA_ENTRY_PATHLEN +#define TASK_FINDER_VMA_ENTRY_PATHLEN 64 +#elif TASK_FINDER_VMA_ENTRY_PATHLEN < 8 +#error "gimme a little more TASK_FINDER_VMA_ENTRY_PATHLEN" +#endif + + struct __stp_tf_vma_entry { struct hlist_node hlist; pid_t pid; unsigned long vm_start; unsigned long vm_end; - const char *name; + char path[TASK_FINDER_VMA_ENTRY_PATHLEN]; /* mmpath name, if known */ // User data (possibly stp_module) void *user; @@ -130,7 +137,7 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, static int stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, unsigned long vm_end, - const char *name, void *user) + const char *path, void *user) { struct hlist_head *head; struct hlist_node *node; @@ -162,7 +169,16 @@ stap_add_vma_map_info(struct task_struct *tsk, entry->pid = tsk->pid; entry->vm_start = vm_start; entry->vm_end = vm_end; - entry->name = name; + if (strlen(path) >= TASK_FINDER_VMA_ENTRY_PATHLEN-3) + { + strncpy (entry->path, "...", TASK_FINDER_VMA_ENTRY_PATHLEN); + strlcpy (entry->path+3, &path[strlen(path)-TASK_FINDER_VMA_ENTRY_PATHLEN+4], + TASK_FINDER_VMA_ENTRY_PATHLEN-3); + } + else + { + strlcpy (entry->path, path, TASK_FINDER_VMA_ENTRY_PATHLEN); + } entry->user = user; head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; @@ -203,7 +219,7 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start) static int stap_find_vma_map_info(struct task_struct *tsk, unsigned long addr, unsigned long *vm_start, unsigned long *vm_end, - const char **name, void **user) + const char **path, void **user) { struct hlist_head *head; struct hlist_node *node; @@ -227,8 +243,8 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long addr, *vm_start = found_entry->vm_start; if (vm_end != NULL) *vm_end = found_entry->vm_end; - if (name != NULL) - *name = found_entry->name; + if (path != NULL) + *path = found_entry->path; if (user != NULL) *user = found_entry->user; rc = 0; @@ -244,7 +260,7 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long addr, static int stap_find_vma_map_info_user(struct task_struct *tsk, void *user, unsigned long *vm_start, unsigned long *vm_end, - const char **name) + const char **path) { struct hlist_head *head; struct hlist_node *node; @@ -267,8 +283,8 @@ stap_find_vma_map_info_user(struct task_struct *tsk, void *user, *vm_start = found_entry->vm_start; if (vm_end != NULL) *vm_end = found_entry->vm_end; - if (name != NULL) - *name = found_entry->name; + if (path != NULL) + *path = found_entry->path; rc = 0; } read_unlock_irqrestore(&__stp_tf_vma_lock, flags); diff --git a/runtime/vma.c b/runtime/vma.c index d3b4bbe65..4c51cfcaf 100644 --- a/runtime/vma.c +++ b/runtime/vma.c @@ -112,6 +112,9 @@ static int _stp_vma_mmap_cb(struct stap_task_finder_target *tgt, int i, res; struct _stp_module *module = NULL; const char *name = (dentry != NULL) ? dentry->d_name.name : NULL; + + if (path == NULL || *path == '\0') /* unknown? */ + path = (char *)name; /* we'll copy this soon, in ..._add_vma_... */ #ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, @@ -136,7 +139,7 @@ static int _stp_vma_mmap_cb(struct stap_task_finder_target *tgt, atm. */ res = stap_add_vma_map_info(tsk->group_leader, addr, addr + length, - name, module); + path, module); /* Warn, but don't error out. */ if (res != 0) { _stp_warn ("Couldn't register module '%s' for pid %d (%d)\n", _stp_modules[i]->path, tsk->group_leader->pid, res); @@ -156,11 +159,11 @@ static int _stp_vma_mmap_cb(struct stap_task_finder_target *tgt, || _stp_target == tsk->group_leader->pid) { res = stap_add_vma_map_info(tsk->group_leader, addr, - addr + length, name, NULL); + addr + length, path, NULL); #ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, "registered '%s' for %d (res:%d)\n", - name, tsk->group_leader->pid, + path, tsk->group_leader->pid, res); #endif } diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp index b4b94d959..c7f3bebff 100644 --- a/testsuite/systemtap.context/usymbols.exp +++ b/testsuite/systemtap.context/usymbols.exp @@ -62,8 +62,8 @@ set testscript { } } -set output "handler: main_handler ($testexename) -handler: lib_handler (lib${testlibname}.so)" +set output "handler: main_handler ([pwd]/$testexename) +handler: lib_handler ([pwd]/lib${testlibname}.so)" # Used to need to run stap with both the exe and the libraries used as -d args. # Now use --ldd to pick up both exe and the library we just linked in. -- 2.43.5