summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--buildrun.cxx2
-rwxr-xr-xdtrace2
-rw-r--r--runtime/autoconf-asm-syscall.c2
-rw-r--r--runtime/loc2c-runtime.h11
-rw-r--r--runtime/stack.c8
-rw-r--r--runtime/sym.c3
-rw-r--r--runtime/syscall.h298
-rw-r--r--runtime/task_finder.c65
-rw-r--r--tapset/utrace.stp8
-rw-r--r--tapsets.cxx79
-rw-r--r--testsuite/lib/systemtap.exp4
-rw-r--r--testsuite/systemtap.base/bitfield.exp3
-rw-r--r--testsuite/systemtap.base/bitfield.stp46
-rw-r--r--testsuite/systemtap.base/labels.exp41
-rw-r--r--testsuite/systemtap.base/stmt_rel.exp4
-rw-r--r--testsuite/systemtap.base/uprobes_exe.c8
-rw-r--r--testsuite/systemtap.base/uprobes_lib.c3
-rw-r--r--testsuite/systemtap.base/uprobes_lib.exp13
-rw-r--r--testsuite/systemtap.base/uprobes_lib.stp10
-rw-r--r--testsuite/systemtap.base/uprobes_uname.exp46
-rw-r--r--testsuite/systemtap.base/uprobes_uname.stp7
-rwxr-xr-xtestsuite/systemtap.examples/network/nettop.stp8
-rw-r--r--translate.cxx45
23 files changed, 482 insertions, 234 deletions
diff --git a/buildrun.cxx b/buildrun.cxx
index 1eecb3f7..3c0d8f4b 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -168,6 +168,8 @@ compile_pass (systemtap_session& s)
#endif
output_autoconf(s, o, "autoconf-save-stack-trace.c",
"STAPCONF_KERNEL_STACKTRACE", NULL);
+ output_autoconf(s, o, "autoconf-asm-syscall.c",
+ "STAPCONF_ASM_SYSCALL_H", NULL);
o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl;
diff --git a/dtrace b/dtrace
index fd7b4b99..ca95b678 100755
--- a/dtrace
+++ b/dtrace
@@ -94,7 +94,7 @@ class provider:
########################################################################
def usage ():
- print "Usage " + sys.argv[0] + "[-h | -G] -s File.d -o File {Files}"
+ print "Usage " + sys.argv[0] + " [-h | -G] -s File.d -o File {Files}"
sys.exit(1)
def open_file (arg):
diff --git a/runtime/autoconf-asm-syscall.c b/runtime/autoconf-asm-syscall.c
new file mode 100644
index 00000000..bf7a273f
--- /dev/null
+++ b/runtime/autoconf-asm-syscall.c
@@ -0,0 +1,2 @@
+#include <asm/syscall.h>
+
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index eaf47cad..620e1615 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -29,11 +29,12 @@
& (((__typeof (base)) 1 << (nbits)) - 1))
#define store_bitfield(target, base, higherbits, nbits) \
- target = (target \
- &~ ((((__typeof (base)) 1 << (nbits)) - 1) \
- << (sizeof (base) * 8 - (higherbits) - (nbits))) \
- | ((__typeof (base)) (base) \
- << (sizeof (base) * 8 - (higherbits) - (nbits))))
+ target = ((target \
+ &~ ((((__typeof (target)) 1 << (nbits)) - 1) \
+ << (sizeof (target) * 8 - (higherbits) - (nbits)))) \
+ | ((((__typeof (target)) (base)) \
+ & (((__typeof (target)) 1 << (nbits)) - 1)) \
+ << (sizeof (target) * 8 - (higherbits) - (nbits))))
/* Given a DWARF register number, fetch its intptr_t (long) value from the
diff --git a/runtime/stack.c b/runtime/stack.c
index f6b1cd08..68fb9b1f 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -97,6 +97,12 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
&print_data);
}
#endif
+
+// Without KPROBES very little works atm.
+// But this file is unconditionally imported, while these two functions are only
+// used through context-unwind.stp.
+#if defined (CONFIG_KPROBES)
+
/** Prints the stack backtrace
* @param regs A pointer to the struct pt_regs.
*/
@@ -141,6 +147,8 @@ static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int ve
pb->len = 0;
}
+#endif /* CONFIG_KPROBES */
+
/** Prints the user stack backtrace
* @param str string
* @returns Same string as was input with trace info appended,
diff --git a/runtime/sym.c b/runtime/sym.c
index 835e1b46..a2cdd0ff 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -47,7 +47,7 @@ static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt,
#ifdef DEBUG_TASK_FINDER_VMA
_stp_dbug(__FUNCTION__, __LINE__,
"mmap_cb: tsk %d:%d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n",
- tsk->pid, tsk->tgid, path, addr, length, offset, flags);
+ tsk->pid, tsk->tgid, path, addr, length, offset, vm_flags);
#endif
if (path != NULL) {
for (i = 0; i < _stp_num_modules; i++) {
@@ -128,7 +128,6 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio
return 0;
}
-
/* Return module owner and, if sec != NULL, fills in closest section
of the address if found, return NULL otherwise.
XXX: needs to be address-space-specific. */
diff --git a/runtime/syscall.h b/runtime/syscall.h
index ae451070..6d22ba83 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -1,5 +1,6 @@
-/* syscall defines and inlines
- * Copyright (C) 2008 Red Hat Inc.
+/*
+ * syscall defines and inlines
+ * Copyright (C) 2008-2009 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
@@ -89,9 +90,17 @@
#error "Unimplemented architecture"
#endif
+#ifdef STAPCONF_ASM_SYSCALL_H
+
+/* If the system has asm/syscall.h, use defines from it. */
+#include <asm/syscall.h>
+
+#else /* !STAPCONF_ASM_SYSCALL_H */
+
+/* If the system doesn't have asm/syscall.h, use our defines. */
#if defined(__i386__) || defined(__x86_64__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
#if defined(STAPCONF_X86_UNIREGS)
return regs->orig_ax;
@@ -104,37 +113,37 @@ __stp_user_syscall_nr(struct pt_regs *regs)
#endif
#if defined(__powerpc__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return regs->gpr[0];
}
#endif
#if defined(__ia64__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return regs->r15;
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
- // might need to be 'orig_gpr2'
+ // might need to be 'orig_gpr2'
return regs->gprs[2];
}
#endif
#if defined(__i386__) || defined(__x86_64__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
#ifdef CONFIG_IA32_EMULATION
// This code works, but isn't what we need. Since
-// __stp_user_syscall_arg() doesn't sign-extend, a value passed in as
+// syscall_get_syscall_arg() doesn't sign-extend, a value passed in as
// an argument and then returned won't compare correctly anymore. So,
// for now, disable this code.
# if 0
@@ -145,158 +154,233 @@ __stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
# endif
#endif
#if defined(STAPCONF_X86_UNIREGS)
- return &regs->ax;
+ return regs->ax;
#elif defined(__x86_64__)
- return &regs->rax;
+ return regs->rax;
#elif defined (__i386__)
- return &regs->eax;
+ return regs->eax;
#endif
}
#endif
#if defined(__powerpc__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->gpr[3];
+ return regs->gpr[3];
}
#endif
#if defined(__ia64__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->r8;
+ return regs->r8;
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->gprs[2];
+ return regs->gprs[2];
}
#endif
#if defined(__i386__) || defined(__x86_64__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
-#if defined(__i386__)
- if (n > 5) {
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
}
+#if defined(__i386__)
#if defined(STAPCONF_X86_UNIREGS)
- return &regs->bx + n;
+ memcpy(args, &regs->bx + i, n * sizeof(args[0]));
#else
- return &regs->ebx + n;
+ memcpy(args, &regs->ebx + i, n * sizeof(args[0]));
#endif
#elif defined(__x86_64__)
#ifdef CONFIG_IA32_EMULATION
- if (test_tsk_thread_flag(task, TIF_IA32))
- switch (n) {
+ if (test_tsk_thread_flag(task, TIF_IA32)) {
+ switch (i) {
#if defined(STAPCONF_X86_UNIREGS)
- case 0: return &regs->bx;
- case 1: return &regs->cx;
- case 2: return &regs->dx;
- case 3: return &regs->si;
- case 4: return &regs->di;
- case 5: return &regs->bp;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->bx;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->cx;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->dx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->si;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->di;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->bp;
#else
- case 0: return &regs->rbx;
- case 1: return &regs->rcx;
- case 2: return &regs->rdx;
- case 3: return &regs->rsi;
- case 4: return &regs->rdi;
- case 5: return &regs->rbp;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->rbx;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->rcx;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->rdx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->rsi;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->rdi;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->rbp;
#endif
- default:
- _stp_error("syscall arg > 5");
- return NULL;
}
+ return;
+ }
#endif /* CONFIG_IA32_EMULATION */
- switch (n) {
+ switch (i) {
#if defined(STAPCONF_X86_UNIREGS)
- case 0: return &regs->di;
- case 1: return &regs->si;
- case 2: return &regs->dx;
- case 3: return &regs->r10;
- case 4: return &regs->r8;
- case 5: return &regs->r9;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->di;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->si;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->dx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->r10;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->r8;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->r9;
#else
- case 0: return &regs->rdi;
- case 1: return &regs->rsi;
- case 2: return &regs->rdx;
- case 3: return &regs->r10;
- case 4: return &regs->r8;
- case 5: return &regs->r9;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->rdi;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->rsi;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->rdx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->r10;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->r8;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->r9;
#endif
- default:
- _stp_error("syscall arg > 5");
- return NULL;
}
#endif /* CONFIG_X86_32 */
+ return;
}
#endif
#if defined(__powerpc__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
- switch (n) {
- case 0: return &regs->gpr[3];
- case 1: return &regs->gpr[4];
- case 2: return &regs->gpr[5];
- case 3: return &regs->gpr[6];
- case 4: return &regs->gpr[7];
- case 5: return &regs->gpr[8];
- default:
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
}
+ memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
}
#endif
#if defined(__ia64__)
-#define __stp_user_syscall_arg(task, regs, n) \
- ____stp_user_syscall_arg(task, regs, n, &c->unwaddr)
+#define syscall_get_arguments(task, regs, i, n, args) \
+ __ia64_syscall_get_arguments(task, regs, i, n, args, &c->unwaddr)
-static inline long *
-____stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n, unsigned long **cache)
+static inline void
+__ia64_syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args, unsigned long **cache)
{
- if (n > 5) {
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
+ }
+ switch (i) {
+ case 0:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 32, regs, cache);
+ case 1:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 33, regs, cache);
+ case 2:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 34, regs, cache);
+ case 3:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 35, regs, cache);
+ case 4:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 36, regs, cache);
+ case 5:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 37, regs, cache);
}
- return __ia64_fetch_register(n + 32, regs, cache);
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
- /* If we were returning a value, we could check for TIF_31BIT
- * here and cast the value with '(u32)' to make sure it got
- * down to 32bits. But, since we're returning an address,
- * there isn't much we can do. */
- switch (n) {
- case 0: return &regs->orig_gpr2;
- case 1: return &regs->gprs[3];
- case 2: return &regs->gprs[4];
- case 3: return &regs->gprs[5];
- case 4: return &regs->gprs[6];
- case 5: return &regs->args[0];
- default:
- _stp_error("syscall arg > 5");
- return NULL;
+ unsigned long mask = -1UL;
+
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
+ }
+#ifdef CONFIG_COMPAT
+ if (test_tsk_thread_flag(task, TIF_31BIT))
+ mask = 0xffffffff;
+#endif
+ switch (i) {
+ case 0:
+ if (!n--) break;
+ *args++ = regs->orig_gpr2 & mask;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->gprs[3] & mask;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->gprs[4] & mask;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->gprs[5] & mask;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->gprs[6] & mask;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->args[0] & mask;
}
}
#endif
+#endif /* !STAPCONF_ASM_SYSCALL_H */
#endif /* _SYSCALL_H_ */
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 69b6246b..fa6c296e 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -2,8 +2,9 @@
#define TASK_FINDER_C
#if ! defined(CONFIG_UTRACE)
-#error "Need CONFIG_UTRACE!"
-#endif
+/* Dummy definitions for use in sym.c */
+struct stap_task_finder_target { };
+#else
#include <linux/utrace.h>
@@ -178,7 +179,7 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
&& strcmp(tgt->pathname, new_tgt->pathname) == 0)
/* pid-based target (a specific pid or all
* pids) */
- || (new_tgt->pathlen == 0
+ || (new_tgt->pathlen == 0 && tgt->pathlen == 0
&& tgt->pid == new_tgt->pid))) {
found_node = 1;
break;
@@ -1064,11 +1065,9 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
#endif
{
struct stap_task_finder_target *tgt = engine->data;
- unsigned long syscall_no;
- unsigned long *rv_addr, rv;
- unsigned long *arg_addr, arg0;
- unsigned long arg1 = 0;
- unsigned long arg2 = 0;
+ long syscall_no;
+ unsigned long rv;
+ unsigned long args[3];
int rc;
struct mm_struct *mm;
struct vm_area_struct *vma;
@@ -1087,7 +1086,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
// See if syscall is one we're interested in.
//
// FIXME: do we need to handle mremap()?
- syscall_no = __stp_user_syscall_nr(regs);
+ syscall_no = syscall_get_nr(tsk, regs);
if (syscall_no != MMAP_SYSCALL_NO(tsk)
&& syscall_no != MMAP2_SYSCALL_NO(tsk)
&& syscall_no != MPROTECT_SYSCALL_NO(tsk)
@@ -1105,21 +1104,11 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
return UTRACE_RESUME;
// Get return value
- rv_addr = __stp_user_syscall_return_value(tsk, regs);
- if ((rc = __stp_get_user(rv, rv_addr)) != 0) {
- _stp_error("couldn't read syscall return value for pid %d: %d",
- tsk->pid, rc);
- return UTRACE_RESUME;
- }
+ rv = syscall_get_return_value(tsk, regs);
// We need the first syscall argument to see what address we
// were operating on.
- arg_addr = __stp_user_syscall_arg(tsk, regs, 0);
- if ((rc = __stp_get_user(arg0, arg_addr)) != 0) {
- _stp_error("couldn't read syscall arg 0 for pid %d: %d",
- tsk->pid, rc);
- return UTRACE_RESUME;
- }
+ syscall_get_arguments(tsk, regs, 0, 1, args);
#ifdef DEBUG_TASK_FINDER_VMA
_stp_dbug(__FUNCTION__, __LINE__,
@@ -1130,20 +1119,15 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
: ((syscall_no == MPROTECT_SYSCALL_NO(tsk)) ? "mprotect"
: ((syscall_no == MUNMAP_SYSCALL_NO(tsk)) ? "munmap"
: "UNKNOWN")))),
- arg0, rv);
+ args[0], rv);
#endif
__stp_tf_handler_start();
if (syscall_no == MUNMAP_SYSCALL_NO(tsk)) {
// We need the 2nd syscall argument for the length.
- arg_addr = __stp_user_syscall_arg(tsk, regs, 1);
- if ((rc = __stp_get_user(arg1, arg_addr)) != 0) {
- _stp_error("couldn't read syscall arg 1 for pid %d: %d",
- tsk->pid, rc);
- goto syscall_exit_done;
- }
+ syscall_get_arguments(tsk, regs, 1, 1, &args[1]);
// Call the callbacks
- __stp_call_munmap_callbacks(tgt, tsk, arg0, arg1);
+ __stp_call_munmap_callbacks(tgt, tsk, args[0], args[1]);
}
else if (syscall_no == MMAP_SYSCALL_NO(tsk)
|| syscall_no == MMAP2_SYSCALL_NO(tsk)) {
@@ -1164,24 +1148,13 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
}
}
else {
- // We need the 2nd syscall argument for the length.
- arg_addr = __stp_user_syscall_arg(tsk, regs, 1);
- if ((rc = __stp_get_user(arg1, arg_addr)) != 0) {
- _stp_error("couldn't read syscall arg 1 for pid %d: %d",
- tsk->pid, rc);
- goto syscall_exit_done;
- }
-
- // We need the 3nd syscall argument for the protection.
- arg_addr = __stp_user_syscall_arg(tsk, regs, 2);
- if ((rc = __stp_get_user(arg2, arg_addr)) != 0) {
- _stp_error("couldn't read syscall arg 2 for pid %d: %d",
- tsk->pid, rc);
- goto syscall_exit_done;
- }
+ // We need the 2nd syscall argument for the length and
+ // the 3rd argument for the protection.
+ syscall_get_arguments(tsk, regs, 1, 2, &args[1]);
// Call the callbacks
- __stp_call_mprotect_callbacks(tgt, tsk, arg0, arg1, arg2);
+ __stp_call_mprotect_callbacks(tgt, tsk, args[0], args[1],
+ args[2]);
}
syscall_exit_done:
@@ -1324,5 +1297,5 @@ stap_stop_task_finder(void)
debug_task_finder_report();
}
-
+#endif /* defined(CONFIG_UTRACE) */
#endif /* TASK_FINDER_C */
diff --git a/tapset/utrace.stp b/tapset/utrace.stp
index 34cb32c5..00f427e6 100644
--- a/tapset/utrace.stp
+++ b/tapset/utrace.stp
@@ -6,13 +6,15 @@
%}
function _utrace_syscall_nr:long () %{
- THIS->__retvalue = __stp_user_syscall_nr(CONTEXT->regs); /* pure */
+ THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs); /* pure */
%}
function _utrace_syscall_arg:long (n:long) %{
- THIS->__retvalue = *__stp_user_syscall_arg(current, CONTEXT->regs, (int)THIS->n); /* pure */
+ unsigned long arg = 0; /* pure */
+ syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg);
+ THIS->__retvalue = arg;
%}
function _utrace_syscall_return:long () %{
- THIS->__retvalue = *__stp_user_syscall_return_value(current, CONTEXT->regs); /* pure */
+ THIS->__retvalue = syscall_get_return_value(current, CONTEXT->regs); /* pure */
%}
diff --git a/tapsets.cxx b/tapsets.cxx
index 04402a27..c63151e1 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1339,7 +1339,12 @@ struct dwflpp
}
void
- iterate_over_cu_labels (string label_val, Dwarf_Die *cu, void *data,
+ iterate_over_cu_labels (string label_val,
+ string function,
+ Dwarf_Die *cu,
+ vector<derived_probe *> & results,
+ probe_point *base_loc,
+ void *data,
void (* callback)(const string &,
const char *,
int,
@@ -1364,14 +1369,30 @@ struct dwflpp
Dwarf_Attribute *attr = dwarf_attr (&die, DW_AT_name, &attr_mem);
int tag = dwarf_tag(&die);
const char *name = dwarf_formstring (attr);
- if (tag == DW_TAG_subprogram && name != 0)
+ if (name == 0)
+ continue;
+ switch (tag)
{
+ case DW_TAG_label:
+ break;
+ case DW_TAG_subprogram:
function_name = name;
+ default:
+ if (dwarf_haschildren (&die))
+ iterate_over_cu_labels (label_val, function, &die, results, base_loc, q, callback);
+ continue;
+ }
+
+ if (strcmp(function_name.c_str(), function.c_str()) == 0
+ || (name_has_wildcard(function)
+ && function_name_matches_pattern (function_name, function)))
+ {
}
- else if (tag == DW_TAG_label && name != 0
- && ((strncmp(name, sym, strlen(sym)) == 0)
- || (name_has_wildcard (sym)
- && function_name_matches_pattern (name, sym))))
+ else
+ continue;
+ if (strcmp(name, sym) == 0
+ || (name_has_wildcard(sym)
+ && function_name_matches_pattern (name, sym)))
{
const char *file = dwarf_decl_file (&die);
// Get the line number for this label
@@ -1403,19 +1424,18 @@ struct dwflpp
int nscopes = 0;
nscopes = dwarf_getscopes_die (&die, &scopes);
if (nscopes > 1)
- callback(function_name.c_str(), file,
- (int)dline, &scopes[1], stmt_addr, q);
- }
- if (dwarf_haschildren (&die) && tag != DW_TAG_structure_type
- && tag != DW_TAG_union_type)
- {
- iterate_over_cu_labels (label_val, &die, q, callback);
+ {
+ callback(function_name.c_str(), file,
+ (int)dline, &scopes[1], stmt_addr, q);
+ if (sess.listing_mode)
+ results.back()->locations[0]->components.push_back
+ (new probe_point::component(TOK_LABEL, new literal_string (name)));
+ }
}
}
while (dwarf_siblingof (&die, &die) == 0);
}
-
void collect_srcfiles_matching (string const & pattern,
set<char const *> & filtered_srcfiles)
{
@@ -1986,7 +2006,7 @@ struct dwflpp
Dwarf_Die *die_mem,
Dwarf_Attribute *attr_mem)
{
- Dwarf_Die *die = die_mem;
+ Dwarf_Die *die = NULL;
Dwarf_Die struct_die;
Dwarf_Attribute temp_attr;
@@ -1995,6 +2015,9 @@ struct dwflpp
if (vardie)
*die_mem = *vardie;
+ if (e->components.empty())
+ return die_mem;
+
static unsigned int func_call_level ;
static unsigned int dwarf_error_flag ; // indicates current error is dwarf error
static unsigned int dwarf_error_count ; // keeps track of no of dwarf errors
@@ -2011,6 +2034,7 @@ struct dwflpp
obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str());
#endif
+ die = die ? dwarf_formref_die (attr_mem, die_mem) : die_mem;
const int typetag = dwarf_tag (die);
switch (typetag)
{
@@ -2168,7 +2192,6 @@ struct dwflpp
/* Now iterate on the type in DIE's attribute. */
if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL)
throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), e->tok);
- die = dwarf_formref_die (attr_mem, die_mem);
}
return die;
}
@@ -2414,13 +2437,12 @@ struct dwflpp
/* Translate the ->bar->baz[NN] parts. */
- Dwarf_Die die_mem, *die = NULL;
- die = dwarf_formref_die (&attr_mem, &die_mem);
+ Dwarf_Die die_mem, *die = dwarf_formref_die (&attr_mem, &die_mem);
die = translate_components (&pool, &tail, pc, e,
die, &die_mem, &attr_mem);
if(!die)
{
- die = dwarf_formref_die (&attr_mem, &vardie);
+ die = dwarf_formref_die (&attr_mem, &die_mem);
stringstream alternatives;
if (die != NULL)
print_members(die,alternatives);
@@ -2496,17 +2518,19 @@ struct dwflpp
/* Translate the ->bar->baz[NN] parts. */
Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr (scope_die, DW_AT_type, &attr_mem);
-
- Dwarf_Die vardie_mem;
- Dwarf_Die *vardie = dwarf_formref_die (attr, &vardie_mem);
+ if (dwarf_attr_integrate (scope_die, DW_AT_type, &attr_mem) == NULL)
+ throw semantic_error("failed to retrieve return value type attribute for "
+ + string(dwarf_diename(scope_die) ?: "<unknown>")
+ + "(" + string(dwarf_diename(cu) ?: "<unknown>")
+ + ")",
+ e->tok);
- Dwarf_Die die_mem, *die = NULL;
+ Dwarf_Die die_mem, *die = dwarf_formref_die (&attr_mem, &die_mem);
die = translate_components (&pool, &tail, pc, e,
- vardie, &die_mem, &attr_mem);
+ die, &die_mem, &attr_mem);
if(!die)
{
- die = dwarf_formref_die (&attr_mem, vardie);
+ die = dwarf_formref_die (&attr_mem, &die_mem);
stringstream alternatives;
if (die != NULL)
print_members(die,alternatives);
@@ -4110,7 +4134,7 @@ query_cu (Dwarf_Die * cudie, void * arg)
{
// If we have a pattern string with target *label*, we
// have to look at labels in all the matched srcfiles.
- q->dw.iterate_over_cu_labels (q->label_val, q->dw.cu, q, query_statement);
+ q->dw.iterate_over_cu_labels (q->label_val, q->function, q->dw.cu, q->results, q->base_loc, q, query_statement);
}
else
{
@@ -6474,6 +6498,7 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline();
s.op->newline() << "/* ---- itrace probes ---- */";
+
s.op->newline() << "struct stap_itrace_probe {";
s.op->indent(1);
s.op->newline() << "struct stap_task_finder_target tgt;";
diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp
index 43116a85..019b1bf8 100644
--- a/testsuite/lib/systemtap.exp
+++ b/testsuite/lib/systemtap.exp
@@ -85,7 +85,7 @@ proc setup_server {} {
# Make sure that the necessary resources are available to run the client/server.
if {[installtest_p]} then {
- if {[exec /usr/bin/which stap-client-connect] == ""} then {
+ if {[catch {exec /usr/bin/which stap-client-connect} dummy]} then {
print "Unable to start a server: stap-client-connect is not found in PATH"
return 0
}
@@ -93,7 +93,7 @@ proc setup_server {} {
print "Unable to start a server: [exec pwd]/../stap-client-connect is not found"
return 0
}
- if {[exec /usr/bin/which avahi-publish-service] == ""} then {
+ if {[catch {exec /usr/bin/which avahi-publish-service} dummy]} then {
print "Unable to start a server: avahi-publish-service is not found in PATH"
return 0
}
diff --git a/testsuite/systemtap.base/bitfield.exp b/testsuite/systemtap.base/bitfield.exp
new file mode 100644
index 00000000..16451369
--- /dev/null
+++ b/testsuite/systemtap.base/bitfield.exp
@@ -0,0 +1,3 @@
+# test that bitfield r/w works correctly
+set test "bitfield"
+stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g
diff --git a/testsuite/systemtap.base/bitfield.stp b/testsuite/systemtap.base/bitfield.stp
new file mode 100644
index 00000000..c2ff4929
--- /dev/null
+++ b/testsuite/systemtap.base/bitfield.stp
@@ -0,0 +1,46 @@
+%{
+#include <linux/tcp.h>
+static struct tcphdr foo = {0};
+%}
+
+function get_ptr:long() %{ THIS->__retvalue = (long)&foo; /* pure */ %}
+function get_ack:long() %{ THIS->__retvalue = foo.ack; /* pure */ %}
+function get_urg:long() %{ THIS->__retvalue = foo.urg; /* pure */ %}
+
+function check:long(ack:long, urg:long) {
+ ptr = get_ptr()
+
+ /* set the bits with cast */
+ @cast(ptr, "tcphdr")->ack = ack
+ @cast(ptr, "tcphdr")->urg = urg
+
+ /* check that reading with embedded-C is ok */
+ real_ack = get_ack()
+ real_urg = get_urg()
+ errors = (ack != real_ack) + (urg != real_urg)
+
+ /* check that reading with a cast is ok */
+ cast_ack = @cast(ptr, "tcphdr")->ack
+ cast_urg = @cast(ptr, "tcphdr")->urg
+ errors += (ack != cast_ack) + (urg != cast_urg)
+
+ if (errors)
+ printf("bitfield had %d errors; expect(%d%d), real(%d%d), cast(%d%d)\n",
+ errors, ack, urg, real_ack, real_urg, cast_ack, cast_urg)
+
+ return errors
+}
+
+probe begin {
+ println("systemtap starting probe")
+
+ errors = check(0, 0)
+ errors += check(0, 1)
+ errors += check(1, 0)
+ errors += check(1, 1)
+
+ println("systemtap ending probe")
+ if (errors == 0)
+ println("systemtap test success")
+ exit()
+}
diff --git a/testsuite/systemtap.base/labels.exp b/testsuite/systemtap.base/labels.exp
index 2f79a502..88ed4619 100644
--- a/testsuite/systemtap.base/labels.exp
+++ b/testsuite/systemtap.base/labels.exp
@@ -10,15 +10,22 @@ set label_flags "additional_flags=-g"
set fp [open $label_srcpath "w"]
puts $fp "
int
+foo ()
+{
+init_an_int:
+ return 1;
+}
+int
main ()
{
sleep(5);
+ foo();
int a = 0;
int b = 0;
char *c;
init_an_int:
a = 2;
-init_another_int:
+init_an_int_again:
b = 3;
c = \"abc\";
ptr_inited:
@@ -30,8 +37,9 @@ close $fp
set label_stppath "[pwd]/labels.stp"
set fp [open $label_stppath "w"]
puts $fp "
-probe process(\"labels.x\").function(\"main*@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)}
-probe process(\"labels.x\").function(\"main*@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)}
+probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)}
+probe process(\"labels.x\").function(\"main@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)}
+probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_an_int\") {printf (\"init_an_int\\n\")}
"
close $fp
@@ -47,20 +55,35 @@ if { $res != "" } {
pass "compiling labels.c -g"
}
+# list of labels
+
+spawn stap -l "process(\"$label_exepath\").function(\"*\").label(\"*\")"
+
+wait
+expect {
+ -timeout 180
+ -re {process.*function.*labels.c:5...label..init_an_int.*process.*function.*labels.c:16...label..init_an_int.*process.*function.*labels.c:18...label..init_an_int_again} { incr ok; exp_continue }
+ timeout { fail "$test (timeout)" }
+ eof { }
+}
+
+if {$ok == 1} { pass "$test -l .label" } { fail "$test -l .label $ok" }
+
# label in an executable
+set ok 0
verbose -log "spawn stap -c $label_exepath $label_stppath"
spawn stap -c $label_exepath $label_stppath
wait
expect {
-timeout 180
- -re {VARS a=0x0 b=0x0.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue }
+ -re {VARS a=0x0 b=0x0.*init_an_int.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue }
timeout { fail "$test (timeout)" }
eof { }
}
-if {$ok == 1} { pass "$test exe .label" } { fail "$test exe .label" }
+if {$ok == 1} { pass "$test exe .label" } { fail "$test exe .label $ok" }
# address of label in an executable
@@ -68,7 +91,7 @@ set label_shpath "[pwd]/label.sh"
set fp [open $label_shpath "w"]
puts $fp "
readelf --debug-dump $label_exepath | awk \"
-/init_another_int/ {have_label=1}
+/init_an_int_again/ {have_label=1}
/DW_AT_low_pc/ {if (have_label) {print \$3;exit;}}
\"
"
@@ -103,7 +126,7 @@ if { $res != "" } {
# label in a shared object
-spawn stap -p2 -l "process\(\"$label_sopath\"\).function\(\"\*\"\).label\(\"init_another_int\"\)"
+spawn stap -p2 -l "process\(\"$label_sopath\"\).function\(\"\*\"\).label\(\"init_an_int_again\"\)"
expect {
-timeout 180
-re {process.*function} { incr ok; exp_continue }
@@ -111,7 +134,7 @@ expect {
eof { }
}
-if {$ok == 1} { pass "$test so .label" } { fail "$test so .label" }
+if {$ok == 1} { pass "$test so .label" } { fail "$test so .label $ok" }
# address of label in a shared object
@@ -119,7 +142,7 @@ set label_shpath "[pwd]/label.sh"
set fp [open $label_shpath "w"]
puts $fp "
readelf --debug-dump $label_sopath | awk \"
-/init_another_int/ {have_label=1}
+/init_an_int_again/ {have_label=1}
/DW_AT_low_pc/ {if (have_label) {print \$3;exit;}}
\"
"
diff --git a/testsuite/systemtap.base/stmt_rel.exp b/testsuite/systemtap.base/stmt_rel.exp
index ec12e484..619c91a5 100644
--- a/testsuite/systemtap.base/stmt_rel.exp
+++ b/testsuite/systemtap.base/stmt_rel.exp
@@ -33,7 +33,9 @@ expect {
eof { }
}
-if { $ok == 3 } {
+# bio_init drifts a bit in different kernels.
+# maybe 3, 4 or 15 lines in it.
+if { $ok >= 3 } {
pass "$test wildcard"
} else {
fail "$test wildcard ($ok)"
diff --git a/testsuite/systemtap.base/uprobes_exe.c b/testsuite/systemtap.base/uprobes_exe.c
index 447434c6..b4811335 100644
--- a/testsuite/systemtap.base/uprobes_exe.c
+++ b/testsuite/systemtap.base/uprobes_exe.c
@@ -15,13 +15,15 @@ int lib_main (void);
void
main_func (int foo)
{
- ; // nothing here...
+ if (foo > 1)
+ main_func (foo - 1);
+ else
+ lib_main();
}
int
main (int argc, char *argv[], char *envp[])
{
- main_func(1);
- lib_main();
+ main_func (3);
return 0;
}
diff --git a/testsuite/systemtap.base/uprobes_lib.c b/testsuite/systemtap.base/uprobes_lib.c
index c9d70625..25297b6b 100644
--- a/testsuite/systemtap.base/uprobes_lib.c
+++ b/testsuite/systemtap.base/uprobes_lib.c
@@ -10,7 +10,8 @@
void
lib_func (int bar)
{
- ; // nothing here...
+ if (bar > 1)
+ lib_func (bar - 1);
}
void
diff --git a/testsuite/systemtap.base/uprobes_lib.exp b/testsuite/systemtap.base/uprobes_lib.exp
index 63ef957a..313c01b6 100644
--- a/testsuite/systemtap.base/uprobes_lib.exp
+++ b/testsuite/systemtap.base/uprobes_lib.exp
@@ -29,11 +29,14 @@ if { $res != "" } {
pass "$test compile $testsrc"
}
-# XXX main_func needs another/extra test. Disabled for now.
-# Enable (and in uprobes_lib.stp) after PR9940 is fixed.
-# set ::result_string {main_func
-# lib_func}
-set ::result_string {lib_func}
+set ::result_string {main
+main_func
+main_func
+main_func
+lib_main
+lib_func
+lib_func
+lib_func}
# Only run on make installcheck
if {! [installtest_p]} { untested "$test"; return }
diff --git a/testsuite/systemtap.base/uprobes_lib.stp b/testsuite/systemtap.base/uprobes_lib.stp
index bc6cc249..459351a4 100644
--- a/testsuite/systemtap.base/uprobes_lib.stp
+++ b/testsuite/systemtap.base/uprobes_lib.stp
@@ -1,8 +1,14 @@
-/* - Not activated probe... Seems always skipped?
+probe process("uprobes_exe").function("main") {
+ printf("main\n");
+}
+
probe process("uprobes_exe").function("main_func") {
printf("main_func\n");
}
-*/
+
+probe process("libuprobes_lib.so").function("lib_main") {
+ printf("lib_main\n");
+}
probe process("libuprobes_lib.so").function("lib_func") {
printf("lib_func\n");
diff --git a/testsuite/systemtap.base/uprobes_uname.exp b/testsuite/systemtap.base/uprobes_uname.exp
new file mode 100644
index 00000000..65e1ff70
--- /dev/null
+++ b/testsuite/systemtap.base/uprobes_uname.exp
@@ -0,0 +1,46 @@
+set test "uprobes_uname"
+set testpath "$srcdir/$subdir"
+set testsrc "$testpath/uprobes_exe.c"
+set testsrclib "$testpath/uprobes_lib.c"
+set testexe "./uprobes_exe"
+set testlibname "uprobes_lib"
+set testlibdir "."
+set testso "$testlibdir/lib${testlibname}.so"
+set testflags "additional_flags=-g additional_flags=-O"
+set testlibflags "$testflags additional_flags=-fPIC additional_flags=-shared"
+set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir"
+
+# Compile our test program and library.
+set res [target_compile $testsrclib $testso executable $testlibflags]
+if { $res != "" } {
+ verbose "target_compile for $testso failed: $res" 2
+ fail "$test compile $testsrclib"
+ return
+} else {
+ pass "$test compile $testsrclib"
+}
+
+set res [target_compile $testsrc $testexe executable $maintestflags]
+if { $res != "" } {
+ verbose "target_compile failed: $res" 2
+ fail "$test compile $testsrc"
+ return
+} else {
+ pass "$test compile $testsrc"
+}
+
+set ::result_string {exe: main=main
+exe: main_func=main_func
+exe: main_func=main_func
+exe: main_func=main_func
+lib: lib_main=lib_main
+lib: lib_func=lib_func
+lib: lib_func=lib_func
+lib: lib_func=lib_func}
+
+# Only run on make installcheck
+if {! [installtest_p]} { untested "$test"; return }
+if {! [utrace_p]} { untested $test; return }
+stap_run2 $srcdir/$subdir/$test.stp -c $testexe
+
+#exec rm -f $testexe $testso
diff --git a/testsuite/systemtap.base/uprobes_uname.stp b/testsuite/systemtap.base/uprobes_uname.stp
new file mode 100644
index 00000000..a44d78d3
--- /dev/null
+++ b/testsuite/systemtap.base/uprobes_uname.stp
@@ -0,0 +1,7 @@
+probe process("uprobes_exe").function("*") {
+ printf("exe: %s=%s\n",probefunc(), usymname(uaddr()));
+}
+
+probe process("libuprobes_lib.so").function("*") {
+ printf("lib: %s=%s\n",probefunc(), usymname(uaddr()));
+}
diff --git a/testsuite/systemtap.examples/network/nettop.stp b/testsuite/systemtap.examples/network/nettop.stp
index b84e4882..e96548f1 100755
--- a/testsuite/systemtap.examples/network/nettop.stp
+++ b/testsuite/systemtap.examples/network/nettop.stp
@@ -19,11 +19,11 @@ function print_activity()
"PID", "UID", "DEV", "XMIT_PK", "RECV_PK",
"XMIT_KB", "RECV_KB", "COMMAND")
- foreach ([pid, dev, exec, uid] in ifrecv-) {
- ifmerged[pid, dev, exec, uid] = 1;
+ foreach ([pid, dev, exec, uid] in ifrecv) {
+ ifmerged[pid, dev, exec, uid] += @count(ifrecv[pid,dev,exec,uid]);
}
- foreach ([pid, dev, exec, uid] in ifxmit-) {
- ifmerged[pid, dev, exec, uid] = 1;
+ foreach ([pid, dev, exec, uid] in ifxmit) {
+ ifmerged[pid, dev, exec, uid] += @count(ifxmit[pid,dev,exec,uid]);
}
foreach ([pid, dev, exec, uid] in ifmerged-) {
n_xmit = @count(ifxmit[pid, dev, exec, uid])
diff --git a/translate.cxx b/translate.cxx
index 95986924..971c1498 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4516,7 +4516,7 @@ dump_unwindsyms (Dwfl_Module *m,
// In the future, we'll also care about data symbols.
int syments = dwfl_module_getsymtab(m);
- assert(syments);
+ dwfl_assert ("Getting symbol table for " + modname, syments >= 0);
//extract build-id from debuginfo file
int build_id_len = 0;
@@ -4562,6 +4562,10 @@ dump_unwindsyms (Dwfl_Module *m,
}
}
+ // Use end as sanity check when resolving symbol addresses.
+ Dwarf_Addr end;
+ dwfl_module_info (m, NULL, NULL, &end, NULL, NULL, NULL, NULL);
+
// Look up the relocation basis for symbols
int n = dwfl_module_relocations (m);
@@ -4576,10 +4580,11 @@ dump_unwindsyms (Dwfl_Module *m,
Dwarf_Addr extra_offset = 0;
- for (int i = 1 /* XXX: why not 0? */ ; i < syments; ++i)
+ for (int i = 0; i < syments; ++i)
{
GElf_Sym sym;
- const char *name = dwfl_module_getsym(m, i, &sym, NULL);
+ GElf_Word shndxp;
+ const char *name = dwfl_module_getsym(m, i, &sym, &shndxp);
if (name)
{
// NB: Yey, we found the kernel's _stext value.
@@ -4602,17 +4607,15 @@ dump_unwindsyms (Dwfl_Module *m,
clog << "Found kernel _stext extra offset 0x" << hex << extra_offset << dec << endl;
}
- // We only need the function symbols to identify kernel-mode
- // PC's, so we omit undefined or "fake" absolute addresses.
- // These fake absolute addresses occur in some older i386
- // kernels to indicate they are vDSO symbols, not real
- // functions in the kernel. We also omit symbols that have
- // suspicious addresses (before base).
+ // We are only interested in "real" symbols.
+ // We omit symbols that have suspicious addresses (before base,
+ // or after end).
if ((GELF_ST_TYPE (sym.st_info) == STT_FUNC ||
GELF_ST_TYPE (sym.st_info) == STT_OBJECT) // PR10000: also need .data
- && !(sym.st_shndx == SHN_UNDEF
- || sym.st_shndx == SHN_ABS
- || sym.st_value < base))
+ && !(sym.st_shndx == SHN_UNDEF // Value undefined,
+ || shndxp == (GElf_Word) -1 // in a non-allocated section,
+ || sym.st_value >= end // beyond current module,
+ || sym.st_value < base)) // before first section.
{
Dwarf_Addr sym_addr = sym.st_value;
const char *secname = NULL;
@@ -4637,6 +4640,16 @@ dump_unwindsyms (Dwfl_Module *m,
{
// This is a symbol within a (possibly relocatable)
// kernel image.
+
+ // We only need the function symbols to identify kernel-mode
+ // PC's, so we omit undefined or "fake" absolute addresses.
+ // These fake absolute addresses occur in some older i386
+ // kernels to indicate they are vDSO symbols, not real
+ // functions in the kernel. We also omit symbols that have
+ if (GELF_ST_TYPE (sym.st_info) == STT_FUNC
+ && sym.st_shndx == SHN_ABS)
+ continue;
+
secname = "_stext";
// NB: don't subtract session.sym_stext, which could be inconveniently NULL.
// Instead, sym_addr will get compensated later via extra_offset.
@@ -4696,10 +4709,10 @@ dump_unwindsyms (Dwfl_Module *m,
// There would be only a small benefit to warning. A user
// likely can't do anything about this; backtraces for the
// affected module would just get all icky heuristicy.
-#if 0
- c->session.print_warning ("No unwind data for " + modname
- + ", " + dwfl_errmsg (-1));
-#endif
+ // So only report in verbose mode.
+ if (c->session.verbose > 2)
+ c->session.print_warning ("No unwind data for " + modname
+ + ", " + dwfl_errmsg (-1));
}
for (unsigned secidx = 0; secidx < seclist.size(); secidx++)