summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-03-20 09:35:44 +0100
committerMark Wielaard <mjw@redhat.com>2009-03-20 09:35:44 +0100
commit9ba817408c6eb81d9ed470314cff1d2d412c4b68 (patch)
tree81cdd381dc4a9c8007102ce4465a7a2c6c016a4e
parent5e94ef56760c087784e485c35521a6e438cfc3e5 (diff)
parent0cf9ea606eb7677a1241595f7568dd4a6c243ef2 (diff)
downloadsystemtap-steved-9ba817408c6eb81d9ed470314cff1d2d412c4b68.tar.gz
systemtap-steved-9ba817408c6eb81d9ed470314cff1d2d412c4b68.tar.xz
systemtap-steved-9ba817408c6eb81d9ed470314cff1d2d412c4b68.zip
Merge branch 'master' into pr6866
-rw-r--r--Makefile.in1
-rw-r--r--NEWS5
-rw-r--r--buildrun.cxx1
-rw-r--r--doc/Makefile.in1
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.am6
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.in7
-rwxr-xr-x[-rw-r--r--]doc/Tapset_Reference_Guide/manpager.sh0
-rw-r--r--parse.cxx6
-rw-r--r--runtime/autoconf-find-task-pid.c6
-rw-r--r--runtime/itrace.c50
-rw-r--r--runtime/task_finder.c6
-rw-r--r--runtime/utrace_compatibility.h9
-rwxr-xr-xscripts/kernel-doc4
-rw-r--r--stapprobes.5.in13
-rw-r--r--systemtap.spec9
-rw-r--r--tapset/aux_syscalls.stp7
-rw-r--r--tapsets.cxx128
-rw-r--r--testsuite/systemtap.base/itrace.exp7
18 files changed, 187 insertions, 79 deletions
diff --git a/Makefile.in b/Makefile.in
index 73ef5bac..12a5e6ea 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -288,6 +288,7 @@ staplog_CPPFLAGS = @staplog_CPPFLAGS@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
diff --git a/NEWS b/NEWS
index 74fd1df5..fff8afc9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,10 @@
* What's new
+- In guru mode (-g), the kernel probing blacklist is disabled, leaving
+ only a subset - the kernel's own internal kprobe blacklist - to attempt
+ to filter out areas unsafe to probe. The differences may be enough to
+ probe more interrupt handlers.
+
- Variables unavailable in current context may be skipped by setting a
session level flag with command line option --skip-badvars now available.
This will simply substitute the otherwise error causing variable with a
diff --git a/buildrun.cxx b/buildrun.cxx
index b9d648ef..0e9e0e17 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -148,6 +148,7 @@ compile_pass (systemtap_session& s)
output_autoconf(s, o, "autoconf-vm-area.c", "STAPCONF_VM_AREA", NULL);
output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL);
output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL);
+ output_autoconf(s, o, "autoconf-find-task-pid.c", "STAPCONF_FIND_TASK_PID", NULL);
#if 0
/* NB: For now, the performance hit of probe_kernel_read/write (vs. our
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 93753666..e23a6699 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -163,6 +163,7 @@ staplog_CPPFLAGS = @staplog_CPPFLAGS@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
PDF_FILES = tutorial.pdf langref.pdf
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.am b/doc/SystemTap_Tapset_Reference/Makefile.am
index 9e7d2069..68dfd971 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.am
+++ b/doc/SystemTap_Tapset_Reference/Makefile.am
@@ -2,7 +2,7 @@
## process this file with automake to produce Makefile.in
DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap
-MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man5
+MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man3stap
HTML_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap/tapsets
@@ -36,7 +36,7 @@ tapsets.pdf: tapsets.xml
xmlto pdf tapsets.xml
stamp-mandocs: tapsets.xml
- xmlto man -o man5 tapsets.xml
+ xmlto man -o man3stap tapsets.xml
touch stamp-mandocs
#FIXME need to figure out where to install things appropriately
@@ -45,7 +45,7 @@ install-data-hook:
$(MKDIR_P) $(DOC_INSTALL_DIR)
$(INSTALL_DATA) tapsets.pdf $(DOC_INSTALL_DIR)
$(MKDIR_P) $(MAN_INSTALL_DIR)
- $(INSTALL_DATA) man5/* $(MAN_INSTALL_DIR)
+ $(INSTALL_DATA) man3stap/* $(MAN_INSTALL_DIR)
$(MKDIR_P) $(HTML_INSTALL_DIR)
$(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR)
endif
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in
index 84d2114c..2f8a5294 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.in
+++ b/doc/SystemTap_Tapset_Reference/Makefile.in
@@ -166,10 +166,11 @@ staplog_CPPFLAGS = @staplog_CPPFLAGS@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap
-MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man5
+MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man3stap
HTML_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap/tapsets
SRCTREE = $(abs_top_srcdir)/
DOCPROC = $(abs_builddir)/docproc
@@ -429,7 +430,7 @@ uninstall-am:
@BUILD_REFDOCS_TRUE@ xmlto pdf tapsets.xml
@BUILD_REFDOCS_TRUE@stamp-mandocs: tapsets.xml
-@BUILD_REFDOCS_TRUE@ xmlto man -o man5 tapsets.xml
+@BUILD_REFDOCS_TRUE@ xmlto man -o man3stap tapsets.xml
@BUILD_REFDOCS_TRUE@ touch stamp-mandocs
#FIXME need to figure out where to install things appropriately
@@ -438,7 +439,7 @@ uninstall-am:
@BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR)
@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets.pdf $(DOC_INSTALL_DIR)
@BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(MAN_INSTALL_DIR)
-@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man5/* $(MAN_INSTALL_DIR)
+@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man3stap/* $(MAN_INSTALL_DIR)
@BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(HTML_INSTALL_DIR)
@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR)
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh
index 0051d208..0051d208 100644..100755
--- a/doc/Tapset_Reference_Guide/manpager.sh
+++ b/doc/Tapset_Reference_Guide/manpager.sh
diff --git a/parse.cxx b/parse.cxx
index ac7e652c..a26d594c 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -2341,6 +2341,12 @@ parser::parse_symbol ()
cop->operand = parse_expression ();
expect_op(",");
expect_unknown(tok_string, cop->type);
+ // types never start with "struct<space>" or "union<space>",
+ // so gobble it up.
+ if (cop->type.compare(0, 7, "struct ") == 0)
+ cop->type = cop->type.substr(7);
+ if (cop->type.compare(0, 6, "union ") == 0)
+ cop->type = cop->type.substr(6);
if (peek_op (","))
{
next();
diff --git a/runtime/autoconf-find-task-pid.c b/runtime/autoconf-find-task-pid.c
new file mode 100644
index 00000000..549d5ac3
--- /dev/null
+++ b/runtime/autoconf-find-task-pid.c
@@ -0,0 +1,6 @@
+#include <linux/sched.h>
+
+void foo (pid_t k) {
+ struct task_struct *tsk = find_task_by_pid (k);
+ (void) tsk;
+}
diff --git a/runtime/itrace.c b/runtime/itrace.c
index ed32b0bc..3d9ded2f 100644
--- a/runtime/itrace.c
+++ b/runtime/itrace.c
@@ -1,6 +1,7 @@
/*
* user space instruction tracing
* Copyright (C) 2005, 2006, 2007, 2008, 2009 IBM Corp.
+ * Copyright (C) 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
@@ -19,6 +20,7 @@
#include <linux/utrace.h>
#include <asm/string.h>
#include "uprobes/uprobes.h"
+#include "utrace_compatibility.h"
#ifndef put_task_struct
#define put_task_struct(t) \
@@ -55,7 +57,7 @@ struct itrace_info {
struct list_head link;
};
-static u32 debug = 1;
+static u32 debug = 0 /* 1 */;
static LIST_HEAD(usr_itrace_info);
static spinlock_t itrace_lock;
@@ -118,10 +120,15 @@ static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void
return buf - old_buf;
}
+#ifdef UTRACE_ORIG_VERSION
+static u32 usr_itrace_report_quiesce(struct utrace_attached_engine *engine,
+ struct task_struct *tsk)
+#else
static u32 usr_itrace_report_quiesce(enum utrace_resume_action action,
struct utrace_attached_engine *engine,
struct task_struct *tsk,
unsigned long event)
+#endif
{
int status;
struct itrace_info *ui;
@@ -129,10 +136,23 @@ static u32 usr_itrace_report_quiesce(enum utrace_resume_action action,
ui = rcu_dereference(engine->data);
WARN_ON(!ui);
+#ifdef UTRACE_ORIG_VERSION
+ return (ui->step_flag); // XXX XXX XXX
+#else
return (event == 0 ? ui->step_flag : UTRACE_RESUME);
+#endif
}
+#ifdef UTRACE_ORIG_VERSION
+static u32 usr_itrace_report_signal(
+ struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs,
+ u32 action, siginfo_t *info,
+ const struct k_sigaction *orig_ka,
+ struct k_sigaction *return_ka)
+#else
static u32 usr_itrace_report_signal(u32 action,
struct utrace_attached_engine *engine,
struct task_struct *tsk,
@@ -140,6 +160,7 @@ static u32 usr_itrace_report_signal(u32 action,
siginfo_t *info,
const struct k_sigaction *orig_ka,
struct k_sigaction *return_ka)
+#endif
{
struct itrace_info *ui;
u32 return_flags;
@@ -174,16 +195,31 @@ static u32 usr_itrace_report_signal(u32 action,
return return_flags;
}
+
+
+#ifdef UTRACE_ORIG_VERSION
+static u32 usr_itrace_report_clone(
+ struct utrace_attached_engine *engine,
+ struct task_struct *parent,
+ unsigned long clone_flags,
+ struct task_struct *child)
+#else
static u32 usr_itrace_report_clone(enum utrace_resume_action action,
struct utrace_attached_engine *engine,
struct task_struct *parent, unsigned long clone_flags,
struct task_struct *child)
+#endif
{
return UTRACE_RESUME;
}
+#ifdef UTRACE_ORIG_VERSION
+static u32 usr_itrace_report_death(struct utrace_attached_engine *e,
+ struct task_struct *tsk)
+#else
static u32 usr_itrace_report_death(struct utrace_attached_engine *e,
struct task_struct *tsk, bool group_dead, int signal)
+#endif
{
struct itrace_info *ui = rcu_dereference(e->data);
WARN_ON(!ui);
@@ -275,8 +311,13 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe
struct itrace_info *ui;
struct task_struct *tsk;
+ spin_lock_init(&itrace_lock);
rcu_read_lock();
+#ifdef STAPCONF_FIND_TASK_PID
+ tsk = find_task_by_pid(tid);
+#else
tsk = find_task_by_vpid(tid);
+#endif
if (!tsk) {
printk(KERN_ERR "usr_itrace_init: Cannot find process %d\n", tid);
rcu_read_unlock();
@@ -293,11 +334,6 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe
put_task_struct(tsk);
rcu_read_unlock();
- spin_lock_init(&itrace_lock);
-
- /* set initial state */
- spin_lock(&itrace_lock);
- spin_unlock(&itrace_lock);
printk(KERN_INFO "usr_itrace_init: completed for tid = %d\n", tid);
return 0;
@@ -314,7 +350,6 @@ void static remove_usr_itrace_info(struct itrace_info *ui)
if (debug)
printk(KERN_INFO "remove_usr_itrace_info: tid=%d\n", ui->tid);
- spin_lock(&itrace_lock);
if (ui->tsk && ui->engine) {
status = utrace_control(ui->tsk, ui->engine, UTRACE_DETACH);
if (status < 0 && status != -ESRCH && status != -EALREADY)
@@ -322,6 +357,7 @@ void static remove_usr_itrace_info(struct itrace_info *ui)
"utrace_control(UTRACE_DETACH) returns %d\n",
status);
}
+ spin_lock(&itrace_lock);
list_del(&ui->link);
spin_unlock(&itrace_lock);
kfree(ui);
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 1db2bc2a..cc24dc10 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -992,6 +992,7 @@ __stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
static void
__stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt,
struct task_struct *tsk,
+ int map_p,
struct vm_area_struct *vma)
{
char *mmpath_buf;
@@ -1018,7 +1019,7 @@ __stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt,
rc, (int)tsk->pid);
}
else {
- __stp_call_vm_callbacks(tgt, tsk, 1, mmpath,
+ __stp_call_vm_callbacks(tgt, tsk, map_p, mmpath,
vma->vm_start, vma->vm_end,
(vma->vm_pgoff << PAGE_SHIFT));
}
@@ -1111,7 +1112,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
down_read(&mm->mmap_sem);
vma = __stp_find_file_based_vma(mm, rv);
if (vma != NULL) {
- __stp_call_vm_callbacks_with_vma(tgt, tsk, vma);
+ __stp_call_vm_callbacks_with_vma(tgt, tsk, 0, vma);
}
up_read(&mm->mmap_sem);
mmput(mm);
@@ -1184,6 +1185,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
&& vma->vm_end <= entry->vm_end) {
__stp_call_vm_callbacks_with_vma(tgt,
tsk,
+ 1,
vma);
if (vma->vm_end >= entry->vm_end)
break;
diff --git a/runtime/utrace_compatibility.h b/runtime/utrace_compatibility.h
index 00b841d2..4a70da42 100644
--- a/runtime/utrace_compatibility.h
+++ b/runtime/utrace_compatibility.h
@@ -1,6 +1,6 @@
/*
* utrace compatibility defines and inlines
- * Copyright (C) 2008 Red Hat Inc.
+ * 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
@@ -28,6 +28,8 @@ enum utrace_resume_action {
UTRACE_STOP = UTRACE_ACTION_QUIESCE,
UTRACE_RESUME = UTRACE_ACTION_RESUME,
UTRACE_DETACH = UTRACE_ACTION_DETACH,
+ UTRACE_SINGLESTEP = UTRACE_ACTION_SINGLESTEP,
+ UTRACE_BLOCKSTEP = UTRACE_ACTION_BLOCKSTEP,
};
static inline struct utrace_attached_engine *
@@ -48,6 +50,11 @@ utrace_control(struct task_struct *target,
case UTRACE_STOP:
return utrace_set_flags(target, engine,
(engine->flags | UTRACE_ACTION_QUIESCE));
+ case UTRACE_SINGLESTEP:
+ case UTRACE_BLOCKSTEP:
+ return utrace_set_flags(target, engine,
+ engine->flags | action);
+
default:
return -EINVAL;
}
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index add4ba3c..9947882d 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -981,7 +981,7 @@ sub output_probe_xml(%) {
print "</refentryinfo>\n";
print "<refmeta>\n";
print " <refentrytitle><phrase>".$args{'probe'}."</phrase></refentrytitle>\n";
- print " <manvolnum>5</manvolnum>\n";
+ print " <manvolnum>3stap</manvolnum>\n";
# print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
print "</refmeta>\n";
print "<refnamediv>\n";
@@ -1039,7 +1039,7 @@ sub output_sfunction_xml(%) {
print "</refentryinfo>\n";
print "<refmeta>\n";
print " <refentrytitle><phrase>".$args{'sfunction'}."</phrase></refentrytitle>\n";
- print " <manvolnum>5</manvolnum>\n";
+ print " <manvolnum>3stap</manvolnum>\n";
# print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
print "</refmeta>\n";
print "<refnamediv>\n";
diff --git a/stapprobes.5.in b/stapprobes.5.in
index 70d045c4..f4a872cb 100644
--- a/stapprobes.5.in
+++ b/stapprobes.5.in
@@ -407,8 +407,10 @@ process.syscall
process(PID).syscall.return
process("PATH").syscall.return
process.syscall.return
-process(PID).itrace
-process("PATH").itrace
+process(PID).insn
+process("PATH").insn
+process(PID).insn.block
+process("PATH").insn.block
process("PATH").mark("LABEL")
.ESAMPLE
.PP
@@ -443,8 +445,11 @@ in the
.BR $return
context variable.
A
-.B .itrace
-probe gets called for every single step of the process described by PID or PATH.
+.B .insn
+probe gets called for every single-stepped instruction of the process described by PID or PATH.
+A
+.B .insn.block
+probe gets called for every block-stepped instruction of the process described by PID or PATH.
A
.B .mark
probe gets called via a static probe which is defined in the
diff --git a/systemtap.spec b/systemtap.spec
index 7277f92a..540a9d93 100644
--- a/systemtap.spec
+++ b/systemtap.spec
@@ -1,4 +1,3 @@
-%{!?release: %define release 1}
%{!?with_sqlite: %define with_sqlite 1}
%{!?with_docs: %define with_docs 1}
%{!?with_crash: %define with_crash 0}
@@ -6,9 +5,9 @@
%{!?elfutils_version: %define elfutils_version 0.127}
Name: systemtap
-# for version, see also configure.ac
Version: 0.9
-Release: %{release}%{?dist}
+Release: 3%{?dist}
+# for version, see also configure.ac
Summary: Instrumentation System
Group: Development/System
License: GPLv2+
@@ -246,6 +245,7 @@ exit 0
%if %{with_docs}
%doc docs.installed/*.pdf
%doc docs.installed/tapsets
+%{_mandir}/man3stap/*
%endif
%{_bindir}/stap
@@ -317,6 +317,9 @@ exit 0
%changelog
+* Wed Mar 18 2009 Will Cohen <wcohen@redhat.com> - 0.9-2
+- Add location of man pages.
+
* Tue Feb 17 2009 Frank Ch. Eigler <fche@redhat.com> - 0.9-1
- Upstream release.
diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp
index d2e43903..87ea4e04 100644
--- a/tapset/aux_syscalls.stp
+++ b/tapset/aux_syscalls.stp
@@ -322,17 +322,10 @@ function _struct_sockaddr_u:string(uaddr:long, len:long)
}
else if ((sa->sa_family == AF_PACKET)&&(len == sizeof(struct sockaddr_ll)))
{
- /* FIXME. This needs tested */
struct sockaddr_ll *sll = (struct sockaddr_ll *)buf;
-#if defined(__powerpc__) || defined(__ia64__) || defined(__s390x__)
- snprintf(str, strlen, "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%lx}",
- (int)sll->sll_protocol, sll->sll_ifindex, (int)sll->sll_hatype, (int)sll->sll_pkttype,
- (int)sll->sll_halen, *(uint64_t *)sll->sll_addr);
-#else
snprintf(str, strlen, "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%llx}",
(int)sll->sll_protocol, sll->sll_ifindex, (int)sll->sll_hatype, (int)sll->sll_pkttype,
(int)sll->sll_halen, *(uint64_t *)sll->sll_addr);
-#endif
}
else
{
diff --git a/tapsets.cxx b/tapsets.cxx
index 89e011c4..d7b55e33 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -3521,9 +3521,17 @@ dwarf_query::blacklisted_p(const string& funcname,
if (! (goodfn && goodfile))
{
- if (sess.verbose>1)
- clog << " skipping - blacklisted";
- return true;
+ if (sess.guru_mode)
+ {
+ if (sess.verbose>1)
+ clog << " guru mode enabled - ignoring blacklist";
+ }
+ else
+ {
+ if (sess.verbose>1)
+ clog << " skipping - blacklisted";
+ return true;
+ }
}
// This probe point is not blacklisted.
@@ -5059,7 +5067,8 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
// cast_op to the next pass. We hope that this value ends
// up not being referenced after all, so it can be optimized out
// quietly.
- semantic_error* er = new semantic_error ("type definition not found", e->tok);
+ string msg = "type definition '" + e->type + "' not found";
+ semantic_error* er = new semantic_error (msg, e->tok);
// NB: we can have multiple errors, since a @cast
// may be expanded in several different contexts:
// function ("*") { @cast(...) }
@@ -6240,6 +6249,9 @@ task_finder_derived_probe_group::emit_module_exit (systemtap_session& s)
// ------------------------------------------------------------------------
+static string TOK_INSN("insn");
+static string TOK_BLOCK("block");
+
struct itrace_derived_probe: public derived_probe
{
bool has_path;
@@ -6314,7 +6326,7 @@ struct itrace_builder: public derived_probe_builder
// XXX: PR 6445 needs !has_path && !has_pid support
assert (has_path || has_pid);
- single_step = 1;
+ single_step = ! has_null_param (parameters, TOK_BLOCK);
// If we have a path, we need to validate it.
if (has_path)
@@ -9269,10 +9281,10 @@ mark_builder::build(systemtap_session & sess,
struct tracepoint_arg
{
- string name, c_type;
- bool used, isptr;
+ string name, c_type, typecast;
+ bool usable, used, isptr;
Dwarf_Die type_die;
- tracepoint_arg(): used(false), isptr(false) {}
+ tracepoint_arg(): usable(false), used(false), isptr(false) {}
};
struct tracepoint_derived_probe: public derived_probe
@@ -9324,7 +9336,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
// search for a tracepoint parameter matching this name
tracepoint_arg *arg = NULL;
for (unsigned i = 0; i < args.size(); ++i)
- if (args[i].name == argname)
+ if (args[i].usable && args[i].name == argname)
{
arg = &args[i];
arg->used = true;
@@ -9372,6 +9384,9 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
if (lvalue && (!dw.sess.guru_mode || e->components.empty()))
throw semantic_error("write to tracepoint variable '" + e->base_name
+ "' not permitted", e->tok);
+ // XXX: if a struct/union arg is passed by value, then writing to its fields
+ // is also meaningless until you dereference past a pointer member. It's
+ // harder to detect and prevent that though...
if (e->components.empty())
{
@@ -9543,6 +9558,8 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
for (unsigned i = 0; i < args.size(); ++i)
{
+ if (!args[i].usable)
+ continue;
if (i > 0)
pf->raw_components += " ";
pf->raw_components += args[i].name;
@@ -9625,32 +9642,39 @@ tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s,
static bool
dwarf_type_name(Dwarf_Die& type_die, string& c_type)
{
- // if this die has a direct name, then we're done
- const char *diename = dwarf_diename_integrate(&type_die);
- if (diename != NULL)
+ // if we've gotten down to a basic type, then we're done
+ bool done = true;
+ switch (dwarf_tag(&type_die))
{
- switch (dwarf_tag(&type_die))
- {
- case DW_TAG_structure_type:
- c_type.append("struct ");
- break;
- case DW_TAG_union_type:
- c_type.append("union ");
- break;
- }
- c_type.append(diename);
+ case DW_TAG_structure_type:
+ c_type.append("struct ");
+ break;
+ case DW_TAG_union_type:
+ c_type.append("union ");
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_base_type:
+ break;
+ default:
+ done = false;
+ break;
+ }
+ if (done)
+ {
+ c_type.append(dwarf_diename_integrate(&type_die));
return true;
}
// otherwise, this die is a type modifier.
// recurse into the referent type
+ // if it can't be named, just call it "void"
Dwarf_Attribute subtype_attr;
Dwarf_Die subtype_die;
if (!dwarf_attr_integrate(&type_die, DW_AT_type, &subtype_attr)
|| !dwarf_formref_die(&subtype_attr, &subtype_die)
|| !dwarf_type_name(subtype_die, c_type))
- return false;
+ c_type = "void";
const char *suffix = NULL;
switch (dwarf_tag(&type_die))
@@ -9671,33 +9695,47 @@ dwarf_type_name(Dwarf_Die& type_die, string& c_type)
return false;
}
c_type.append(suffix);
+
+ // XXX HACK! The va_list isn't usable as found in the debuginfo...
+ if (c_type == "struct __va_list_tag*")
+ c_type = "va_list";
+
return true;
}
static bool
-resolve_tracepoint_arg_type(Dwarf_Die& type_die, bool& isptr)
+resolve_tracepoint_arg_type(tracepoint_arg& arg)
{
Dwarf_Attribute type_attr;
- switch (dwarf_tag(&type_die))
+ switch (dwarf_tag(&arg.type_die))
{
case DW_TAG_typedef:
case DW_TAG_const_type:
case DW_TAG_volatile_type:
// iterate on the referent type
- return (dwarf_attr_integrate(&type_die, DW_AT_type, &type_attr)
- && dwarf_formref_die(&type_attr, &type_die)
- && resolve_tracepoint_arg_type(type_die, isptr));
+ return (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr)
+ && dwarf_formref_die(&type_attr, &arg.type_die)
+ && resolve_tracepoint_arg_type(arg));
case DW_TAG_base_type:
// base types will simply be treated as script longs
- isptr = false;
+ arg.isptr = false;
return true;
case DW_TAG_pointer_type:
- // pointers can be either script longs,
- // or dereferenced with their referent type
- isptr = true;
- return (dwarf_attr_integrate(&type_die, DW_AT_type, &type_attr)
- && dwarf_formref_die(&type_attr, &type_die));
+ // pointers can be treated as script longs,
+ // and if we know their type, they can also be dereferenced
+ if (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr)
+ && dwarf_formref_die(&type_attr, &arg.type_die))
+ arg.isptr = true;
+ arg.typecast = "(intptr_t)";
+ return true;
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ // for structs/unions which are passed by value, we turn it into
+ // a pointer that can be dereferenced.
+ arg.isptr = true;
+ arg.typecast = "(intptr_t)&";
+ return true;
default:
// should we consider other types too?
return false;
@@ -9721,12 +9759,12 @@ tracepoint_derived_probe::build_args(dwflpp& dw, Dwarf_Die& func_die)
Dwarf_Attribute type_attr;
if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr)
|| !dwarf_formref_die (&type_attr, &tparg.type_die)
- || !dwarf_type_name(tparg.type_die, tparg.c_type)
- || !resolve_tracepoint_arg_type(tparg.type_die, tparg.isptr))
+ || !dwarf_type_name(tparg.type_die, tparg.c_type))
throw semantic_error ("cannot get type of tracepoint '"
+ tracepoint_name + "' parameter '"
+ tparg.name + "'");
+ tparg.usable = resolve_tracepoint_arg_type(tparg);
args.push_back(tparg);
if (sess.verbose > 4)
clog << "found parameter for tracepoint '" << tracepoint_name
@@ -9739,8 +9777,9 @@ tracepoint_derived_probe::build_args(dwflpp& dw, Dwarf_Die& func_die)
void
tracepoint_derived_probe::printargs(std::ostream &o) const
{
- for (unsigned i = 0; i < args.size(); ++i)
- o << " $" << args[i].name << ":" << args[i].c_type;
+ for (unsigned i = 0; i < args.size(); ++i)
+ if (args[i].usable)
+ o << " $" << args[i].name << ":" << args[i].c_type;
}
void
@@ -9778,6 +9817,8 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s)
// don't provide any sort of context pointer.
s.op->newline() << "#include <" << p->header << ">";
s.op->newline() << "static void enter_tracepoint_probe_" << i << "(";
+ if (p->args.size() == 0)
+ s.op->line() << "void";
for (unsigned j = 0; j < p->args.size(); ++j)
{
if (j > 0)
@@ -9796,8 +9837,7 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s)
{
s.op->newline() << "c->locals[0]." << p->name << ".__tracepoint_arg_"
<< p->args[j].name << " = (int64_t)";
- if (p->args[j].isptr)
- s.op->line() << "(intptr_t)";
+ s.op->line() << p->args[j].typecast;
s.op->line() << "__tracepoint_arg_" << p->args[j].name << ";";
}
s.op->newline() << p->name << " (c);";
@@ -10812,9 +10852,13 @@ register_standard_tapsets(systemtap_session & s)
->bind(new utrace_builder ());
// itrace user-space probes
- s.pattern_root->bind_str(TOK_PROCESS)->bind("itrace")
+ s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN)
+ ->bind(new itrace_builder ());
+ s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN)
+ ->bind(new itrace_builder ());
+ s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
->bind(new itrace_builder ());
- s.pattern_root->bind_num(TOK_PROCESS)->bind("itrace")
+ s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
->bind(new itrace_builder ());
// marker-based parts
diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp
index f19af977..e215bfe7 100644
--- a/testsuite/systemtap.base/itrace.exp
+++ b/testsuite/systemtap.base/itrace.exp
@@ -1,8 +1,5 @@
# itrace test
-# temporarily disabled
-return
-
# Initialize variables
set utrace_support_found 0
@@ -11,7 +8,7 @@ set exepath "[pwd]/ls_[pid]"
set itrace1_script {
global instrs = 0
probe begin { printf("systemtap starting probe\n") }
- probe process("%s").itrace
+ probe process("%s").insn
{
instrs += 1
if (instrs == 5)
@@ -28,7 +25,7 @@ set itrace1_script_output "itraced = 5\r\n"
set itrace2_script {
global instrs = 0, itrace_on = 0, start_timer = 0
probe begin { start_timer = 1; printf("systemtap starting probe\n") }
- probe process("%s").itrace if (itrace_on)
+ probe process("%s").insn if (itrace_on)
{
instrs += 1
if (instrs == 5)