summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-04-08 12:03:08 -0400
committerDave Brolley <brolley@redhat.com>2009-04-08 12:03:08 -0400
commit2f7ba4b8416eae26971da68fdc14aa8560a7939c (patch)
treed5b4383e43bc108d9f76d30addfd857b6bf8dc62
parent83d18bfb001f334309163e54d6c5bd28a1829035 (diff)
parent3dd58c2ac312fc16aa38124987081adbd6697629 (diff)
downloadsystemtap-steved-2f7ba4b8416eae26971da68fdc14aa8560a7939c.tar.gz
systemtap-steved-2f7ba4b8416eae26971da68fdc14aa8560a7939c.tar.xz
systemtap-steved-2f7ba4b8416eae26971da68fdc14aa8560a7939c.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.in3
-rwxr-xr-xdoc/Tapset_Reference_Guide/publicanize.sh107
-rw-r--r--elaborate.cxx3
-rw-r--r--elaborate.h5
-rw-r--r--runtime/sym.c75
-rw-r--r--runtime/task_finder.c491
-rw-r--r--staptree.h1
-rw-r--r--tapset/context-symbols.stp4
-rw-r--r--tapset/context.stp25
-rw-r--r--tapset/ucontext-symbols.stp52
-rw-r--r--tapsets.cxx290
-rwxr-xr-xtestsuite/buildok/uaddr.stp8
-rwxr-xr-xtestsuite/buildok/usymdata.stp8
-rwxr-xr-xtestsuite/buildok/usymname.stp8
-rw-r--r--testsuite/systemtap.context/usymbols.exp5
-rwxr-xr-xtestsuite/systemtap.examples/network/nettop.stp8
-rw-r--r--translate.cxx14
18 files changed, 626 insertions, 484 deletions
diff --git a/Makefile.am b/Makefile.am
index 80b54754..f6f9fff0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -126,7 +126,8 @@ if BUILD_SERVER
install-exec-local: install-scripts
PHONIES += install-scripts
-install-scripts:
+# scripts should be installed before this rule is run
+install-scripts: install-binSCRIPTS
for f in $(bin_SCRIPTS); do \
sed -i -e "/INSTALL-HOOK/d;s,exec_prefix=,exec_prefix=$(exec_prefix)/bin/,;s,sysconfdir=.*,sysconfdir=$(sysconfdir)," $(DESTDIR)$(bindir)/$$f; \
done
diff --git a/Makefile.in b/Makefile.in
index 23685917..dfa2b593 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1542,7 +1542,8 @@ cscope:
@BUILD_ELFUTILS_TRUE@install-exec-local: install-elfutils
@BUILD_SERVER_TRUE@install-exec-local: install-scripts
-@BUILD_SERVER_TRUE@install-scripts:
+# scripts should be installed before this rule is run
+@BUILD_SERVER_TRUE@install-scripts: install-binSCRIPTS
@BUILD_SERVER_TRUE@ for f in $(bin_SCRIPTS); do \
@BUILD_SERVER_TRUE@ sed -i -e "/INSTALL-HOOK/d;s,exec_prefix=,exec_prefix=$(exec_prefix)/bin/,;s,sysconfdir=.*,sysconfdir=$(sysconfdir)," $(DESTDIR)$(bindir)/$$f; \
@BUILD_SERVER_TRUE@ done
diff --git a/doc/Tapset_Reference_Guide/publicanize.sh b/doc/Tapset_Reference_Guide/publicanize.sh
index d4da6e02..0d1b134e 100755
--- a/doc/Tapset_Reference_Guide/publicanize.sh
+++ b/doc/Tapset_Reference_Guide/publicanize.sh
@@ -1,26 +1,74 @@
#!/bin/bash
+INFILE="../SystemTap_Tapset_Reference/tapsets.xml"
+OUTFILE="en-US/Tapset_Reference_Guide.xml"
+TMPFILE='mktemp' || exit 1
+TMPFILE2='mktemp' || exit 1
-#copy the automated tapsets.xml
-cp ../SystemTap_Tapset_Reference/tapsets.xml temp.xml ;
+do_help()
+{
+ echo "publicanize.sh: usage:
+ -?/--help this message
+ -i/--input=file input file name
+ -o/--output=file output file name
+" >&2
+}
+
+
+#process optional arguments -i -o
+while [ "$#" -ne 0 ]
+do
+ arg=`printf %s $1 | awk -F= '{print $1}'`
+ val=`printf %s $1 | awk -F= '{print $2}'`
+ shift
+ if test -z "$val"; then
+ local possibleval=$1
+ printf %s $1 "$possibleval" | grep ^- >/dev/null 2>&1
+ if test "$?" != "0"; then
+ val=$possibleval
+ if [ "$#" -ge 1 ]; then
+ shift
+ fi
+ fi
+ fi
+
+ case "$arg" in
+ -i|--input)
+ INFILE=$val
+ ;;
+ -o|--output)
+ OUTFILE=$val
+ ;;
+ -\?|--help)
+ do_help
+ exit 0
+ ;;
+ *)
+ echo "Unknown option \"$arg\". See opcontrol --help" >&2
+ exit 1
+ ;;
+ esac
+done
+
+
+#copy the generated tapsets.xml
+cp $INFILE $TMPFILE || exit 1
#remove all excess whitespace
-sed -i -e 's/^\s*//g' temp.xml ;
+sed -i -e 's/^\s*//g' $TMPFILE
-#remove marked Intro (starthere to endhere), then copy it to en-US
-sed '/starthere/,/endhere/d' temp.xml > Tapset_Reference_Guide.xml
-cp Tapset_Reference_Guide.xml en-US/Tapset_Reference_Guide.xml;
-rm Tapset_Reference_Guide.xml
+#remove marked Intro (starthere to endhere)
+sed -i -e '/starthere/,/endhere/d' $TMPFILE
#re-convert programlisting tags
-sed -i -e 's/&lt;programlisting&gt;/<programlisting>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/programlisting&gt;/<\/programlisting>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;programlisting&gt;/<programlisting>/g' $TMPFILE
+sed -i -e 's/&lt;\/programlisting&gt;/<\/programlisting>/g' $TMPFILE
#replace header
-cat en-US/Tapset_Reference_Guide.xml |
+cat $TMPFILE |
perl -p -e 'undef $/;s|<bookinfo>\n<title>SystemTap Tapset Reference Manual</title>|<xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="Preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|msg' |
-perl -p -e 'undef $/;s|<authorgroup>\n<author>\n<firstname>William</firstname>\n<surname>Cohen</surname>\n<contrib></contrib>\n<affiliation>\n<address>\n<email>wcohen\@redhat.com</email>\n</address>\n</affiliation>\n</author>\n</authorgroup>||msg' |
-perl -p -e 'undef $/;s|<copyright>\n<year>2008, 2009</year>\n<holder>Red Hat, Inc.</holder>\n</copyright>||msg' |
+perl -p -e 'undef $/;s|<authorgroup>\n<author>\n<othername>SystemTap</othername>\n<contrib>Hackers</contrib>\n</author>\n</authorgroup>||msg' |
+perl -p -e 'undef $/;s|<copyright>\n<year>2008-2009</year>\n<holder>Red Hat, Inc. and others</holder>\n</copyright>||msg' |
perl -p -e 'undef $/;s|<legalnotice>\n<para>\nThis documentation is free software\; you can redistribute\nit and/or modify it under the terms of the GNU General Public\nLicense version 2 as published by the Free Software Foundation.\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\nThis program is distributed in the hope that it will be\nuseful, but WITHOUT ANY WARRANTY; without even the implied\nwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nSee the GNU General Public License for more details.\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\nYou should have received a copy of the GNU General Public\nLicense along with this program; if not, write to the Free\nSoftware Foundation, Inc., 59 Temple Place, Suite 330, Boston,\nMA 02111-1307 USA\n</para>||msg' |
@@ -32,34 +80,33 @@ perl -p -e 'undef $/;s|<programlisting>\n|<programlisting>\n<emphasis>function <
perl -p -e 'undef $/;s|<para>\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\n\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\n<programlisting>|<programlisting>|msg' |
-perl -p -e 'undef $/;s|</programlisting>\n</para>|</programlisting>|msg' > clean.xml
+perl -p -e 'undef $/;s|</programlisting>\n</para>|</programlisting>|msg' > $TMPFILE2
#replace Intro with my own
-perl -p -i -e 's|<!--markerforxi-->|<xi:include href="Introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="Tapset_Dev_Guide.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' clean.xml
+perl -p -i -e 's|<!--markerforxi-->|<xi:include href="Introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="Tapset_Dev_Guide.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' $TMPFILE2
#for tapset name format section
-#perl -p -i -e 'undef $/;s|<screen>\nname:return \(parameters\)\ndefinition\n</screen>|<screen>\n<replaceable>function/probe</replaceable> tapset_name:return \(parameters\)\n</screen>|msg' clean.xml
-#perl -p -i -e 's|<para>In this guide, tapset definitions appear in the following format:</para>|<para>In this guide, the synopsis of each tapset appears in the following format:</para>|g' clean.xml
-#perl -p -i -e 's|<!-- markerforxi pls dont remove -->|<xi:include href="tapsetnameformat-lastpara.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="refentry-example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' clean.xml
+#perl -p -i -e 'undef $/;s|<screen>\nname:return \(parameters\)\ndefinition\n</screen>|<screen>\n<replaceable>function/probe</replaceable> tapset_name:return \(parameters\)\n</screen>|msg' $TMPFILE2
+#perl -p -i -e 's|<para>In this guide, tapset definitions appear in the following format:</para>|<para>In this guide, the synopsis of each tapset appears in the following format:</para>|g' $TMPFILE2
+#perl -p -i -e 's|<!-- markerforxi pls dont remove -->|<xi:include href="tapsetnameformat-lastpara.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="refentry-example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' $TMPFILE2
-cp clean.xml en-US/Tapset_Reference_Guide.xml
-rm clean.xml
-
# statements change synopsis tags, as they are still currently unfixed in publican-redhat
-sed -i -e 's/refsynopsisdiv>/refsect1>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/refsect1>/refsection>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/synopsis>/programlisting>\n/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/refsynopsisdiv>/refsect1>/g' $TMPFILE2
+sed -i -e 's/refsect1>/refsection>/g' $TMPFILE2
+sed -i -e 's/synopsis>/programlisting>\n/g' $TMPFILE2
# re-convert tags
-sed -i -e 's/&lt;emphasis&gt;/<emphasis>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/emphasis&gt;/<\/emphasis>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;emphasis&gt;/<emphasis>/g' $TMPFILE2
+sed -i -e 's/&lt;\/emphasis&gt;/<\/emphasis>/g' $TMPFILE2
-sed -i -e 's/&lt;remark&gt;/<remark>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/remark&gt;/<\/remark>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;remark&gt;/<remark>/g' $TMPFILE2
+sed -i -e 's/&lt;\/remark&gt;/<\/remark>/g' $TMPFILE2
-sed -i -e 's/&lt;command&gt;/<command>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/command&gt;/<\/command>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;command&gt;/<command>/g' $TMPFILE2
+sed -i -e 's/&lt;\/command&gt;/<\/command>/g' $TMPFILE2
#useful marker script; moves content between starthere and endhere to file target
-#sed -n '/starthere/,/endhere/ s/.*/&/w target' Tapset_Reference_Guide.xml \ No newline at end of file
+#sed -n '/starthere/,/endhere/ s/.*/&/w target' $TMPFILE2
+
+mv $TMPFILE2 $OUTFILE
diff --git a/elaborate.cxx b/elaborate.cxx
index 34e6ab16..323261c7 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -3392,6 +3392,9 @@ typeresolution_info::visit_symbol (symbol* e)
void
typeresolution_info::visit_target_symbol (target_symbol* e)
{
+ if (!e->probe_context_var.empty())
+ return;
+
// This occurs only if a target symbol was not resolved over in
// tapset.cxx land, that error was properly suppressed, and the
// later unused-expression-elimination pass didn't get rid of it
diff --git a/elaborate.h b/elaborate.h
index 0ad5b4b2..d927177b 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -129,6 +129,11 @@ struct derived_probe: public probe
void printsig_nested (std::ostream &o) const;
virtual void collect_derivation_chain (std::vector<probe*> &probes_list);
+ virtual void print_dupe_stamp(std::ostream&) {}
+ // To aid duplication elimination, print a stamp which uniquely identifies
+ // the code that will be added to the probe body. (Doesn't need to be the
+ // actual code...)
+
virtual void emit_probe_context_vars (translator_output*) {}
// From within unparser::emit_common_header, add any extra variables
// to this probe's context locals.
diff --git a/runtime/sym.c b/runtime/sym.c
index ecd64fee..835e1b46 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -13,6 +13,7 @@
#define _STP_SYM_C_
#include "string.c"
+#include "task_finder_vma.c"
/** @file sym.c
* @addtogroup sym Symbolic Functions
@@ -20,38 +21,60 @@
* @{
*/
+static void _stp_sym_init(void)
+{
+ static int initialized = 0;
+ if (! initialized) {
+ __stp_tf_vma_initialize();
+ initialized = 1;
+ }
+}
+
/* Callback that needs to be registered (in tapsets.cxx for
emit_module_init) for every user task path or pid for which we
might need symbols or unwind info. */
-static int _stp_tf_vm_cb(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- int map_p, char *vm_path,
- unsigned long vm_start, unsigned long vm_end,
- unsigned long vm_pgoff)
+static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ char *path,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long offset,
+ unsigned long vm_flags)
{
- int i;
+ int i;
+ struct _stp_module *module = NULL;
+
#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);
+ _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);
#endif
- if (map_p)
- {
- struct _stp_module *module = NULL;
- if (vm_path != NULL)
- for (i = 0; i < _stp_num_modules; i++)
- if (strcmp(vm_path, _stp_modules[i]->path) == 0)
- {
+ if (path != NULL) {
+ for (i = 0; i < _stp_num_modules; i++) {
+ if (strcmp(path, _stp_modules[i]->path) == 0)
+ {
#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: matched path %s to module\n", vm_path);
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "vm_cb: matched path %s to module\n",
+ 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);
+ module = _stp_modules[i];
+ break;
+ }
+ }
+ }
+ stap_add_vma_map_info(tsk->group_leader, addr, addr + length, offset,
+ module);
+ return 0;
+}
- return 0;
+static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length)
+{
+ stap_remove_vma_map_info(tsk->group_leader, addr, addr + length, 0);
+ return 0;
}
/* XXX: this needs to be address-space-specific. */
@@ -122,7 +145,7 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
if (task)
{
unsigned long vm_start = 0;
- if (stap_find_vma_map_info(task, addr,
+ if (stap_find_vma_map_info(task->group_leader, addr,
&vm_start, NULL,
NULL, &user) == 0)
if (user != NULL)
@@ -357,8 +380,8 @@ static void _stp_symbol_snprint(char *str, size_t len, unsigned long address,
task);
if (name) {
if (add_mod && modname && *modname)
- _stp_printf("%s %s+%#lx/%#lx\n",
- name, modname, offset, size);
+ _stp_snprintf(str, len, "%s %s+%#lx/%#lx",
+ name, modname, offset, size);
else
strlcpy(str, name, len);
} else
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 3507c669..69b6246b 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -2,32 +2,8 @@
#define TASK_FINDER_C
#if ! defined(CONFIG_UTRACE)
-/* Dummy definitions for use in sym.c */
-struct stap_task_finder_target { };
-
-static int
-stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
- unsigned long vm_end, unsigned long vm_pgoff,
- void *user)
-{
- return 0;
-}
-
-static int
-stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
- unsigned long vm_end, unsigned long vm_pgoff)
-{
- return 0;
-}
-
-static int
-stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
- unsigned long *vm_start, unsigned long *vm_end,
- unsigned long *vm_pgoff, void **user)
-{
- return ESRCH;
-}
-#else
+#error "Need CONFIG_UTRACE!"
+#endif
#include <linux/utrace.h>
@@ -42,7 +18,6 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
#include "syscall.h"
#include "utrace_compatibility.h"
-#include "task_finder_vma.c"
static LIST_HEAD(__stp_task_finder_list);
@@ -86,12 +61,26 @@ typedef int (*stap_task_finder_callback)(struct stap_task_finder_target *tgt,
int register_p,
int process_p);
-typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- int map_p, char *vm_path,
- unsigned long vm_start,
- unsigned long vm_end,
- unsigned long vm_pgoff);
+typedef int
+(*stap_task_finder_mmap_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ char *path,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long offset,
+ unsigned long vm_flags);
+typedef int
+(*stap_task_finder_munmap_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length);
+
+typedef int
+(*stap_task_finder_mprotect_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length,
+ int prot);
struct stap_task_finder_target {
/* private: */
@@ -100,14 +89,18 @@ struct stap_task_finder_target {
struct list_head callback_list;
struct utrace_engine_ops ops;
unsigned engine_attached:1;
- unsigned vm_events:1;
+ unsigned mmap_events:1;
+ unsigned munmap_events:1;
+ unsigned mprotect_events:1;
size_t pathlen;
/* public: */
const char *pathname;
pid_t pid;
stap_task_finder_callback callback;
- stap_task_finder_vm_callback vm_callback;
+ stap_task_finder_mmap_callback mmap_callback;
+ stap_task_finder_munmap_callback munmap_callback;
+ stap_task_finder_mprotect_callback mprotect_callback;
};
#ifdef UTRACE_ORIG_VERSION
@@ -135,19 +128,6 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
#ifdef UTRACE_ORIG_VERSION
static u32
-__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs);
-#else
-static u32
-__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
- struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs);
-#endif
-
-#ifdef UTRACE_ORIG_VERSION
-static u32
__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
struct task_struct *tsk,
struct pt_regs *regs);
@@ -179,12 +159,12 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
// Make sure everything is initialized properly.
new_tgt->engine_attached = 0;
- new_tgt->vm_events = 0;
+ new_tgt->mmap_events = 0;
+ new_tgt->munmap_events = 0;
+ new_tgt->mprotect_events = 0;
memset(&new_tgt->ops, 0, sizeof(new_tgt->ops));
new_tgt->ops.report_death = &__stp_utrace_task_finder_target_death;
new_tgt->ops.report_quiesce = &__stp_utrace_task_finder_target_quiesce;
- new_tgt->ops.report_syscall_entry = \
- &__stp_utrace_task_finder_target_syscall_entry;
new_tgt->ops.report_syscall_exit = \
&__stp_utrace_task_finder_target_syscall_exit;
@@ -216,9 +196,13 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
// Add this target to the callback list for this task.
list_add_tail(&new_tgt->callback_list, &tgt->callback_list_head);
- // If the new target has a vm_callback, remember this.
- if (new_tgt->vm_callback != NULL)
- tgt->vm_events = 1;
+ // If the new target has any m* callbacks, remember this.
+ if (new_tgt->mmap_callback != NULL)
+ tgt->mmap_events = 1;
+ if (new_tgt->munmap_callback != NULL)
+ tgt->munmap_events = 1;
+ if (new_tgt->mprotect_callback != NULL)
+ tgt->mprotect_events = 1;
return 0;
}
@@ -401,15 +385,14 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
/*
* __STP_TASK_BASE_EVENTS: base events for stap_task_finder_target's
- * without vm_callback's
+ * without map callback's
*
* __STP_TASK_VM_BASE_EVENTS: base events for
- * stap_task_finder_target's with vm_callback's
+ * stap_task_finder_target's with map callback's
*/
#define __STP_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH))
#define __STP_TASK_VM_BASE_EVENTS (__STP_TASK_BASE_EVENTS \
- | UTRACE_EVENT(SYSCALL_ENTRY)\
| UTRACE_EVENT(SYSCALL_EXIT))
/*
@@ -421,8 +404,10 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
#define __STP_ATTACHED_TASK_EVENTS (__STP_TASK_BASE_EVENTS \
| UTRACE_EVENT(QUIESCE))
-#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \
- ((tgt)->vm_events ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS)
+#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \
+ (((tgt)->mmap_events || (tgt)->munmap_events \
+ || (tgt)->mprotect_events) \
+ ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS)
static int
__stp_utrace_attach(struct task_struct *tsk,
@@ -538,11 +523,113 @@ __stp_call_callbacks(struct stap_task_finder_target *tgt,
}
}
+static void
+__stp_call_mmap_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, char *path,
+ unsigned long addr, unsigned long length,
+ unsigned long offset, unsigned long vm_flags)
+{
+ struct list_head *cb_node;
+ int rc;
+
+ if (tgt == NULL || tsk == NULL)
+ return;
+
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "pid %d, a/l/o/p/path 0x%lx 0x%lx 0x%lx %c%c%c%c %s\n",
+ tsk->pid, addr, length, offset,
+ vm_flags & VM_READ ? 'r' : '-',
+ vm_flags & VM_WRITE ? 'w' : '-',
+ vm_flags & VM_EXEC ? 'x' : '-',
+ vm_flags & VM_MAYSHARE ? 's' : 'p',
+ path);
+#endif
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+
+ cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL || cb_tgt->mmap_callback == NULL)
+ continue;
+
+ rc = cb_tgt->mmap_callback(cb_tgt, tsk, path, addr, length,
+ offset, vm_flags);
+ if (rc != 0) {
+ _stp_error("mmap callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
+ }
+}
+
+static void
+__stp_call_mmap_callbacks_with_vma(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ struct vm_area_struct *vma)
+{
+ char *mmpath_buf;
+ char *mmpath;
+ int rc;
+
+ // Allocate space for a path
+ mmpath_buf = _stp_kmalloc(PATH_MAX);
+ if (mmpath_buf == NULL) {
+ _stp_error("Unable to allocate space for path");
+ return;
+ }
+
+ // Grab the path associated with this vma.
+#ifdef STAPCONF_DPATH_PATH
+ mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX);
+#else
+ mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
+ mmpath_buf, PATH_MAX);
+#endif
+ if (mmpath == NULL || IS_ERR(mmpath)) {
+ rc = -PTR_ERR(mmpath);
+ _stp_error("Unable to get path (error %d) for pid %d",
+ rc, (int)tsk->pid);
+ }
+ else {
+ __stp_call_mmap_callbacks(tgt, tsk, mmpath, vma->vm_start,
+ vma->vm_end - vma->vm_start,
+ (vma->vm_pgoff << PAGE_SHIFT),
+ vma->vm_flags);
+ }
+ _stp_kfree(mmpath_buf);
+}
+
+static inline void
+__stp_call_munmap_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, unsigned long addr,
+ unsigned long length)
+{
+ struct list_head *cb_node;
+ int rc;
+
+ if (tgt == NULL || tsk == NULL)
+ return;
+
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+
+ cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL || cb_tgt->munmap_callback == NULL)
+ continue;
+
+ rc = cb_tgt->munmap_callback(cb_tgt, tsk, addr, length);
+ if (rc != 0) {
+ _stp_error("munmap callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
+ }
+}
+
static inline void
-__stp_call_vm_callbacks(struct stap_task_finder_target *tgt,
- struct task_struct *tsk, int map_p, char *vm_path,
- unsigned long vm_start, unsigned long vm_end,
- unsigned long vm_pgoff)
+__stp_call_mprotect_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, unsigned long addr,
+ unsigned long length, int prot)
{
struct list_head *cb_node;
int rc;
@@ -555,13 +642,13 @@ __stp_call_vm_callbacks(struct stap_task_finder_target *tgt,
cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
callback_list);
- if (cb_tgt == NULL || cb_tgt->vm_callback == NULL)
+ if (cb_tgt == NULL || cb_tgt->mprotect_callback == NULL)
continue;
- rc = cb_tgt->vm_callback(cb_tgt, tsk, map_p, vm_path,
- vm_start, vm_end, vm_pgoff);
+ rc = cb_tgt->mprotect_callback(cb_tgt, tsk, addr, length,
+ prot);
if (rc != 0) {
- _stp_error("vm callback for %d failed: %d",
+ _stp_error("mprotect callback for %d failed: %d",
(int)tsk->pid, rc);
}
}
@@ -888,16 +975,16 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
__stp_call_callbacks(tgt, tsk, 1, (tsk->pid == tsk->tgid));
/* If this is just a thread other than the thread group leader,
- don't bother inform vm_callback clients about its memory map,
+ don't bother inform map callback clients about its memory map,
since they will simply duplicate each other. */
- if (tgt->vm_events == 1 && tsk->tgid == tsk->pid) {
+ if (tgt->mmap_events == 1 && tsk->tgid == tsk->pid) {
struct mm_struct *mm;
char *mmpath_buf;
char *mmpath;
struct vm_area_struct *vma;
int rc;
- /* Call the vm_callback for every vma associated with
+ /* Call the mmap_callback for every vma associated with
* a file. */
mm = get_task_mm(tsk);
if (! mm)
@@ -924,12 +1011,13 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
mmpath_buf, PATH_MAX);
#endif
if (mmpath) {
- __stp_call_vm_callbacks(tgt, tsk, 1,
- mmpath,
- vma->vm_start,
- vma->vm_end,
- (vma->vm_pgoff
- << PAGE_SHIFT));
+ __stp_call_mmap_callbacks(tgt, tsk,
+ mmpath,
+ vma->vm_start,
+ vma->vm_end - vma->vm_start,
+ (vma->vm_pgoff
+ << PAGE_SHIFT),
+ vma->vm_flags);
}
else {
_stp_dbug(__FUNCTION__, __LINE__,
@@ -964,112 +1052,6 @@ __stp_find_file_based_vma(struct mm_struct *mm, unsigned long addr)
#ifdef UTRACE_ORIG_VERSION
static u32
-__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
-#else
-static u32
-__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
- struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
-#endif
-{
- struct stap_task_finder_target *tgt = engine->data;
- unsigned long syscall_no;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
- unsigned long *arg0_addr, arg0;
- int rc;
-#if defined(__ia64__)
- struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
-#endif
-
- if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
- debug_task_finder_detach();
- return UTRACE_DETACH;
- }
-
- if (tgt == NULL || tgt->vm_events == 0)
- return UTRACE_RESUME;
-
- // See if syscall is one we're interested in.
- //
- // FIXME: do we need to handle mremap()?
- syscall_no = __stp_user_syscall_nr(regs);
- if (syscall_no != MMAP_SYSCALL_NO(tsk)
- && syscall_no != MMAP2_SYSCALL_NO(tsk)
- && syscall_no != MPROTECT_SYSCALL_NO(tsk)
- && syscall_no != MUNMAP_SYSCALL_NO(tsk))
- return UTRACE_RESUME;
-
- __stp_tf_handler_start();
-
- // We need the first syscall argument to see what address
- // we're operating on.
- arg0_addr = __stp_user_syscall_arg(tsk, regs, 0);
- if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) {
- _stp_error("couldn't read syscall arg 0 for pid %d: %d",
- tsk->pid, rc);
- }
- else if (arg0 != (unsigned long)NULL) {
- mm = get_task_mm(tsk);
- if (mm) {
- down_read(&mm->mmap_sem);
-
- // If we can find a matching vma associated
- // with a file, save off its details.
- vma = __stp_find_file_based_vma(mm, arg0);
- if (vma != NULL) {
- __stp_tf_add_vma(tsk, arg0, vma);
- }
-
- up_read(&mm->mmap_sem);
- mmput(mm);
- }
- }
- __stp_tf_handler_end();
- return UTRACE_RESUME;
-}
-
-static void
-__stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- struct vm_area_struct *vma)
-{
- char *mmpath_buf;
- char *mmpath;
- int rc;
-
- // Allocate space for a path
- mmpath_buf = _stp_kmalloc(PATH_MAX);
- if (mmpath_buf == NULL) {
- _stp_error("Unable to allocate space for path");
- return;
- }
-
- // Grab the path associated with this vma.
-#ifdef STAPCONF_DPATH_PATH
- mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX);
-#else
- mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
- mmpath_buf, PATH_MAX);
-#endif
- if (mmpath == NULL || IS_ERR(mmpath)) {
- rc = -PTR_ERR(mmpath);
- _stp_error("Unable to get path (error %d) for pid %d",
- rc, (int)tsk->pid);
- }
- else {
- __stp_call_vm_callbacks(tgt, tsk, 1, mmpath,
- vma->vm_start, vma->vm_end,
- (vma->vm_pgoff << PAGE_SHIFT));
- }
- _stp_kfree(mmpath_buf);
-}
-
-#ifdef UTRACE_ORIG_VERSION
-static u32
__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
struct task_struct *tsk,
struct pt_regs *regs)
@@ -1084,11 +1066,12 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
struct stap_task_finder_target *tgt = engine->data;
unsigned long syscall_no;
unsigned long *rv_addr, rv;
- unsigned long *arg0_addr, arg0;
+ unsigned long *arg_addr, arg0;
+ unsigned long arg1 = 0;
+ unsigned long arg2 = 0;
int rc;
struct mm_struct *mm;
struct vm_area_struct *vma;
- struct __stp_tf_vma_entry *entry = NULL;
#if defined(__ia64__)
struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
#endif
@@ -1098,7 +1081,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
return UTRACE_DETACH;
}
- if (tgt == NULL || tgt->vm_events == 0)
+ if (tgt == NULL)
return UTRACE_RESUME;
// See if syscall is one we're interested in.
@@ -1111,6 +1094,16 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
&& syscall_no != MUNMAP_SYSCALL_NO(tsk))
return UTRACE_RESUME;
+ // The syscall is one we're interested in, but do we have a
+ // handler for it?
+ if (((syscall_no == MMAP_SYSCALL_NO(tsk)
+ || syscall_no == MMAP2_SYSCALL_NO(tsk)) && tgt->mmap_events == 0)
+ || (syscall_no == MPROTECT_SYSCALL_NO(tsk)
+ && tgt->mprotect_events == 0)
+ || (syscall_no == MUNMAP_SYSCALL_NO(tsk)
+ && tgt->munmap_events == 0))
+ return UTRACE_RESUME;
+
// Get return value
rv_addr = __stp_user_syscall_return_value(tsk, regs);
if ((rc = __stp_get_user(rv, rv_addr)) != 0) {
@@ -1121,8 +1114,8 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
// We need the first syscall argument to see what address we
// were operating on.
- arg0_addr = __stp_user_syscall_arg(tsk, regs, 0);
- if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) {
+ 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;
@@ -1141,105 +1134,57 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
#endif
__stp_tf_handler_start();
- // Try to find the vma info we might have saved.
- if (arg0 != (unsigned long)NULL)
- entry = __stp_tf_get_vma_entry(tsk, arg0);
+ 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;
+ }
+ // Call the callbacks
+ __stp_call_munmap_callbacks(tgt, tsk, arg0, arg1);
+ }
+ else if (syscall_no == MMAP_SYSCALL_NO(tsk)
+ || syscall_no == MMAP2_SYSCALL_NO(tsk)) {
- // If entry is NULL, this means we didn't find a file based
- // vma to store in the syscall_entry routine. This could mean
- // we just created a new vma.
- if (entry == NULL) {
mm = get_task_mm(tsk);
if (mm) {
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);
+
+ // Call the callbacks
+ if (vma) {
+ __stp_call_mmap_callbacks_with_vma(tgt, tsk,
+ vma);
}
+
up_read(&mm->mmap_sem);
mmput(mm);
}
}
- // If we found saved vma information, try to match it up with
- // what currently exists.
else {
-#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "** found stored vma 0x%lx/0x%lx/0x%lx!\n",
- entry->vm_start, entry->vm_end, entry->vm_pgoff);
-#endif
- mm = get_task_mm(tsk);
- if (mm) {
- down_read(&mm->mmap_sem);
- vma = __stp_find_file_based_vma(mm, entry->vm_start);
-
- // We couldn't find the vma at all. The
- // original vma was deleted.
- if (vma == NULL) {
- // FIXME: We'll need to figure out to
- // retrieve the path of a deleted
- // vma.
-
- __stp_call_vm_callbacks(tgt, tsk, 0, NULL,
- entry->vm_start,
- entry->vm_end,
- (entry->vm_pgoff
- << PAGE_SHIFT));
- }
-
- // If nothing has changed, there is no
- // need to call the callback.
- else if (vma->vm_start == entry->vm_start
- && vma->vm_end == entry->vm_end
- && vma->vm_pgoff == entry->vm_pgoff) {
- // do nothing
- }
+ // 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;
+ }
- // The original vma has been changed. It is
- // possible that calling mprotect (e.g.) split
- // up an existing vma into 2 or 3 new vma's
- // (assuming it protected a portion of the
- // original vma at the beginning, middle, or
- // end). Try to determine what happened.
- else {
- unsigned long tmp;
-
- // First report that the original vma
- // is gone.
- //
- // FIXME: We'll need to figure out to
- // retrieve the path of a deleted
- // vma.
- __stp_call_vm_callbacks(tgt, tsk, 0, NULL,
- entry->vm_start,
- entry->vm_end,
- (entry->vm_pgoff
- << PAGE_SHIFT));
-
- // Now find all the new vma's that
- // made up the original vma's address
- // space and call the callback on each
- // new vma.
- tmp = entry->vm_start;
- while (((vma = __stp_find_file_based_vma(mm,
- tmp))
- != NULL)
- && vma->vm_end <= entry->vm_end) {
- __stp_call_vm_callbacks_with_vma(tgt,
- tsk,
- vma);
- if (vma->vm_end >= entry->vm_end)
- break;
- tmp = vma->vm_end;
- }
- }
- up_read(&mm->mmap_sem);
- mmput(mm);
+ // 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;
}
- // Cleanup by deleting the saved vma info.
- __stp_tf_remove_vma_entry(entry);
+ // Call the callbacks
+ __stp_call_mprotect_callbacks(tgt, tsk, arg0, arg1, arg2);
}
+
+syscall_exit_done:
__stp_tf_handler_end();
return UTRACE_RESUME;
}
@@ -1264,8 +1209,6 @@ stap_start_task_finder(void)
return ENOMEM;
}
- __stp_tf_vma_initialize();
-
atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING);
rcu_read_lock();
@@ -1382,6 +1325,4 @@ stap_stop_task_finder(void)
}
-#endif /* defined(CONFIG_UTRACE) */
-
#endif /* TASK_FINDER_C */
diff --git a/staptree.h b/staptree.h
index 5125cd85..7e9506bb 100644
--- a/staptree.h
+++ b/staptree.h
@@ -231,6 +231,7 @@ struct target_symbol: public symbol
};
std::string base_name;
std::vector<std::pair<component_type, std::string> > components;
+ std::string probe_context_var;
semantic_error* saved_conversion_error;
target_symbol(): saved_conversion_error (0) {}
void print (std::ostream& o) const;
diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp
index 66d9fea2..783f1b7b 100644
--- a/tapset/context-symbols.stp
+++ b/tapset/context-symbols.stp
@@ -128,7 +128,7 @@ function modname:string (addr: long) %{ /* pure */
*/
function symname:string (addr: long) %{ /* pure */
_stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
- current, 0);
+ NULL, 0);
%}
/**
@@ -143,5 +143,5 @@ function symname:string (addr: long) %{ /* pure */
*/
function symdata:string (addr: long) %{ /* pure */
_stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
- current, 1);
+ NULL, 1);
%}
diff --git a/tapset/context.stp b/tapset/context.stp
index 9f4be0e6..36d68c8d 100644
--- a/tapset/context.stp
+++ b/tapset/context.stp
@@ -11,6 +11,11 @@
//provide information such as a backtrace to where the event occured and the current register values for the
//processor.
// </tapsetdescription>
+
+%{
+#include <asm/processor.h>
+%}
+
/**
* sfunction print_regs - Print a register dump.
*/
@@ -227,3 +232,23 @@ function stack_unused:long () %{ /* pure */
THIS->__retvalue = (long)&a & (THREAD_SIZE-1);
%}
+/**
+ * sfunction uaddr - User space address of current running task.
+ *
+ * Description: Returns the address in userspace that the current
+ * task was at when the probe occured. When the current running task
+ * isn't a user space thread, or the address cannot be found, zero
+ * is returned.
+ */
+function uaddr:long () %{ /* pure */
+ int64_t addr = 0;
+ if (current->mm)
+ {
+ struct pt_regs *uregs;
+ uregs = task_pt_regs(current);
+ if (uregs)
+ addr = (int64_t) REG_IP(uregs);
+ }
+ THIS->__retvalue = addr;
+%}
+
diff --git a/tapset/ucontext-symbols.stp b/tapset/ucontext-symbols.stp
new file mode 100644
index 00000000..3813a8bf
--- /dev/null
+++ b/tapset/ucontext-symbols.stp
@@ -0,0 +1,52 @@
+// User context symbols tapset
+// 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
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+// <tapsetdescription>
+// User context symbol functions provide additional information about
+// addresses from an application. These functions can provide
+// information about the user space map (library) that the event occured or
+// the function symbol of an address.
+// </tapsetdescription>
+
+%{
+#ifndef STP_NEED_SYMBOL_DATA
+#define STP_NEED_SYMBOL_DATA 1
+#endif
+#ifndef STP_NEED_VMA_TRACKER
+#define STP_NEED_VMA_TRACKER 1
+#endif
+%}
+
+/**
+ * sfunction usymname - Return the symbol of an address in the current task.
+ * @addr: The address to translate.
+ *
+ * Description: Returns the (function) symbol name associated with the
+ * given address if known. If not known it will return the hex string
+ * representation of addr.
+ */
+function usymname:string (addr: long) %{ /* pure */
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
+ current, 0);
+%}
+
+/**
+ * sfunction usymdata - Return the symbol and module offset of an address.
+ * @addr: The address to translate.
+ *
+ * Description: Returns the (function) symbol name associated with the
+ * given address in the current task if known, plus the module name
+ * (between brackets) and the offset inside the module (shared library),
+ * plus the size of the symbol function. If any element is not known it
+ * will be ommitted and if the symbol name is unknown it will return the
+ * hex string for the given address.
+ */
+function usymdata:string (addr: long) %{ /* pure */
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
+ current, 1);
+%}
diff --git a/tapsets.cxx b/tapsets.cxx
index f6d73714..04402a27 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1796,6 +1796,7 @@ struct dwflpp
find_variable_and_frame_base (Dwarf_Die *scope_die,
Dwarf_Addr pc,
string const & local,
+ const target_symbol *e,
Dwarf_Die *vardie,
Dwarf_Attribute *fb_attr_mem)
{
@@ -1823,7 +1824,8 @@ struct dwflpp
+ (dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + (dwarf_diename(cu) ?: "<unknown>")
+ ")"))
- + " while searching for local '" + local + "'");
+ + " while searching for local '" + local + "'",
+ e->tok);
}
int declaring_scope = dwarf_getscopevar (scopes, nscopes,
@@ -1841,7 +1843,8 @@ struct dwflpp
+ (dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + (dwarf_diename(cu) ?: "<unknown>")
+ ")"))
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
for (int inner = 0; inner < nscopes; ++inner)
@@ -1868,7 +1871,8 @@ struct dwflpp
translate_location(struct obstack *pool,
Dwarf_Attribute *attr, Dwarf_Addr pc,
Dwarf_Attribute *fb_attr,
- struct location **tail)
+ struct location **tail,
+ const target_symbol *e)
{
Dwarf_Op *expr;
size_t len;
@@ -1887,12 +1891,13 @@ struct dwflpp
/* Fall through. */
case 0: /* Shouldn't happen. */
- throw semantic_error ("not accessible at this address");
+ throw semantic_error ("not accessible at this address", e->tok);
default: /* Shouldn't happen. */
case -1:
throw semantic_error (string ("dwarf_getlocation_addr failed") +
- string (dwarf_errmsg (-1)));
+ string (dwarf_errmsg (-1)),
+ e->tok);
}
return c_translate_location (pool, &loc2c_error, this,
@@ -1976,8 +1981,7 @@ struct dwflpp
translate_components(struct obstack *pool,
struct location **tail,
Dwarf_Addr pc,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
Dwarf_Die *vardie,
Dwarf_Die *die_mem,
Dwarf_Attribute *attr_mem)
@@ -1996,7 +2000,7 @@ struct dwflpp
static unsigned int dwarf_error_count ; // keeps track of no of dwarf errors
static semantic_error saved_dwarf_error("");
- while (i < components.size())
+ while (i < e->components.size())
{
/* XXX: This would be desirable, but we don't get the target_symbol token,
and printing that gives us the file:line number too early anyway. */
@@ -2017,8 +2021,8 @@ struct dwflpp
break;
case DW_TAG_pointer_type:
- if (components[i].first == target_symbol::comp_literal_array_index)
- throw semantic_error ("cannot index pointer");
+ if (e->components[i].first == target_symbol::comp_literal_array_index)
+ throw semantic_error ("cannot index pointer", e->tok);
// XXX: of course, we should support this the same way C does,
// by explicit pointer arithmetic etc. PR4166.
@@ -2026,16 +2030,17 @@ struct dwflpp
break;
case DW_TAG_array_type:
- if (components[i].first == target_symbol::comp_literal_array_index)
+ if (e->components[i].first == target_symbol::comp_literal_array_index)
{
c_translate_array (pool, 1, 0 /* PR9768 */, die, tail,
- NULL, lex_cast<Dwarf_Word>(components[i].second));
+ NULL, lex_cast<Dwarf_Word>(e->components[i].second));
++i;
}
else
throw semantic_error("bad field '"
- + components[i].second
- + "' for array type");
+ + e->components[i].second
+ + "' for array type",
+ e->tok);
break;
case DW_TAG_structure_type:
@@ -2046,7 +2051,8 @@ struct dwflpp
Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die));
if (tmpdie == NULL)
throw semantic_error ("unresolved struct "
- + string (dwarf_diename_integrate (die) ?: "<anonymous>"));
+ + string (dwarf_diename_integrate (die) ?: "<anonymous>"),
+ e->tok);
*die_mem = *tmpdie;
}
switch (dwarf_child (die, die_mem))
@@ -2057,7 +2063,8 @@ struct dwflpp
default: /* Shouldn't happen */
throw semantic_error (string (typetag == DW_TAG_union_type ? "union" : "struct")
+ string (dwarf_diename_integrate (die) ?: "<anonymous>")
- + string (dwarf_errmsg (-1)));
+ + string (dwarf_errmsg (-1)),
+ e->tok);
break;
case 0:
@@ -2066,7 +2073,7 @@ struct dwflpp
while (dwarf_tag (die) != DW_TAG_member
|| ({ const char *member = dwarf_diename_integrate (die);
- member == NULL || string(member) != components[i].second; }))
+ member == NULL || string(member) != e->components[i].second; }))
{
if ( dwarf_diename (die) == NULL ) // handling Anonymous structs/unions
{
@@ -2079,19 +2086,19 @@ struct dwflpp
{
dwarf_error_flag ++ ;
dwarf_error_count ++;
- throw semantic_error(" Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:"<anonymous>"));
+ throw semantic_error(" Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:"<anonymous>"), e->tok);
}
if ( !dwarf_formref_die (&temp_attr, &temp_die))
{
dwarf_error_flag ++ ;
dwarf_error_count ++;
- throw semantic_error(" Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:"<anonymous>"));
+ throw semantic_error(" Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:"<anonymous>"), e->tok);
}
func_call_level ++ ;
- Dwarf_Die *result_die = translate_components(pool, tail, pc, components, &temp_die, &temp_die_2, &temp_attr );
+ Dwarf_Die *result_die = translate_components(pool, tail, pc, e, &temp_die, &temp_die_2, &temp_attr);
func_call_level -- ;
@@ -2129,34 +2136,38 @@ struct dwflpp
but just use the containing union's location. */
if (typetag != DW_TAG_union_type)
throw semantic_error ("no location for field '"
- + components[i].second
- + "' :" + string(dwarf_errmsg (-1)));
+ + e->components[i].second
+ + "' :" + string(dwarf_errmsg (-1)),
+ e->tok);
}
else
- translate_location (pool, attr_mem, pc, NULL, tail);
+ translate_location (pool, attr_mem, pc, NULL, tail, e);
++i;
break;
case DW_TAG_base_type:
throw semantic_error ("field '"
- + components[i].second
+ + e->components[i].second
+ "' vs. base type "
- + string(dwarf_diename_integrate (die) ?: "<anonymous type>"));
+ + string(dwarf_diename_integrate (die) ?: "<anonymous type>"),
+ e->tok);
break;
case -1:
- throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)));
+ throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)),
+ e->tok);
break;
default:
throw semantic_error (string(dwarf_diename_integrate (die) ?: "<anonymous type>")
+ ": unexpected type tag "
- + lex_cast<string>(dwarf_tag (die)));
+ + lex_cast<string>(dwarf_tag (die)),
+ e->tok);
break;
}
/* 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)));
+ throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), e->tok);
die = dwarf_formref_die (attr_mem, die_mem);
}
return die;
@@ -2165,23 +2176,23 @@ struct dwflpp
Dwarf_Die *
resolve_unqualified_inner_typedie (Dwarf_Die *typedie_mem,
- Dwarf_Attribute *attr_mem)
+ Dwarf_Attribute *attr_mem,
+ const target_symbol *e)
{
- ;
Dwarf_Die *typedie;
int typetag = 0;
while (1)
{
typedie = dwarf_formref_die (attr_mem, typedie_mem);
if (typedie == NULL)
- throw semantic_error ("cannot get type: " + string(dwarf_errmsg (-1)));
+ throw semantic_error ("cannot get type: " + string(dwarf_errmsg (-1)), e->tok);
typetag = dwarf_tag (typedie);
if (typetag != DW_TAG_typedef &&
typetag != DW_TAG_const_type &&
typetag != DW_TAG_volatile_type)
break;
if (dwarf_attr_integrate (typedie, DW_AT_type, attr_mem) == NULL)
- throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)));
+ throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)), e->tok);
}
return typedie;
}
@@ -2194,6 +2205,7 @@ struct dwflpp
Dwarf_Die *die,
Dwarf_Attribute *attr_mem,
bool lvalue,
+ const target_symbol *e,
string &,
string &,
exp_type & ty)
@@ -2207,7 +2219,7 @@ struct dwflpp
char const *dname;
string diestr;
- typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem);
+ typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem, e);
typetag = dwarf_tag (typedie);
/* Then switch behavior depending on the type of fetch/store we
@@ -2220,7 +2232,7 @@ struct dwflpp
diestr = (dname != NULL) ? dname : "<unknown>";
throw semantic_error ("unsupported type tag "
+ lex_cast<string>(typetag)
- + " for " + diestr);
+ + " for " + diestr, e->tok);
break;
case DW_TAG_structure_type:
@@ -2228,7 +2240,7 @@ struct dwflpp
dname = dwarf_diename(die);
diestr = (dname != NULL) ? dname : "<unknown>";
throw semantic_error ("struct/union '" + diestr
- + "' is being accessed instead of a member of the struct/union");
+ + "' is being accessed instead of a member of the struct/union", e->tok);
break;
case DW_TAG_enumeration_type:
@@ -2247,7 +2259,7 @@ struct dwflpp
{
// clog << "bad type1 " << encoding << " diestr" << endl;
throw semantic_error ("unsupported type (mystery encoding " + lex_cast<string>(encoding) + ")" +
- " for " + diestr);
+ " for " + diestr, e->tok);
}
if (encoding == DW_ATE_float
@@ -2256,7 +2268,7 @@ struct dwflpp
{
// clog << "bad type " << encoding << " diestr" << endl;
throw semantic_error ("unsupported type (encoding " + lex_cast<string>(encoding) + ")" +
- " for " + diestr);
+ " for " + diestr, e->tok);
}
}
@@ -2278,7 +2290,7 @@ struct dwflpp
Dwarf_Word pointee_encoding;
Dwarf_Word pointee_byte_size = 0;
- pointee_typedie = resolve_unqualified_inner_typedie (&pointee_typedie_mem, attr_mem);
+ pointee_typedie = resolve_unqualified_inner_typedie (&pointee_typedie_mem, attr_mem, e);
if (dwarf_attr_integrate (pointee_typedie, DW_AT_byte_size, attr_mem))
dwarf_formudata (attr_mem, &pointee_byte_size);
@@ -2290,7 +2302,7 @@ struct dwflpp
{
ty = pe_long;
if (typetag == DW_TAG_array_type)
- throw semantic_error ("cannot write to array address");
+ throw semantic_error ("cannot write to array address", e->tok);
assert (typetag == DW_TAG_pointer_type);
c_translate_pointer_store (pool, 1, 0 /* PR9768 */, typedie, tail,
"THIS->value");
@@ -2355,15 +2367,14 @@ struct dwflpp
literal_stmt_for_local (Dwarf_Die *scope_die,
Dwarf_Addr pc,
string const & local,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
bool lvalue,
exp_type & ty)
{
Dwarf_Die vardie;
Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
- fb_attr = find_variable_and_frame_base (scope_die, pc, local,
+ fb_attr = find_variable_and_frame_base (scope_die, pc, local, e,
&vardie, &fb_attr_mem);
if (sess.verbose>2)
@@ -2379,7 +2390,8 @@ struct dwflpp
"attribute for local '" + local
+ "' (dieoffset: "
+ lex_cast_hex<string>(dwarf_dieoffset (&vardie))
- + ")");
+ + ")",
+ e->tok);
}
#define obstack_chunk_alloc malloc
@@ -2392,17 +2404,19 @@ struct dwflpp
/* Given $foo->bar->baz[NN], translate the location of foo. */
struct location *head = translate_location (&pool,
- &attr_mem, pc, fb_attr, &tail);
+ &attr_mem, pc, fb_attr, &tail,
+ e);
if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL)
throw semantic_error("failed to retrieve type "
- "attribute for local '" + local + "'");
+ "attribute for local '" + local + "'",
+ e->tok);
/* Translate the ->bar->baz[NN] parts. */
Dwarf_Die die_mem, *die = NULL;
die = dwarf_formref_die (&attr_mem, &die_mem);
- die = translate_components (&pool, &tail, pc, components,
+ die = translate_components (&pool, &tail, pc, e,
die, &die_mem, &attr_mem);
if(!die)
{
@@ -2412,7 +2426,8 @@ struct dwflpp
print_members(die,alternatives);
throw semantic_error("unable to find local '" + local + "'"
+ " near pc " + lex_cast_hex<string>(pc)
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
/* Translate the assignment part, either
@@ -2423,7 +2438,7 @@ struct dwflpp
string prelude, postlude;
translate_final_fetch_or_store (&pool, &tail, module_bias,
- die, &attr_mem, lvalue,
+ die, &attr_mem, lvalue, e,
prelude, postlude, ty);
/* Write the translation to a string. */
@@ -2434,8 +2449,7 @@ struct dwflpp
string
literal_stmt_for_return (Dwarf_Die *scope_die,
Dwarf_Addr pc,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
bool lvalue,
exp_type & ty)
{
@@ -2460,7 +2474,8 @@ struct dwflpp
" for "
+ string(dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + string(dwarf_diename(cu) ?: "<unknown>")
- + ")");
+ + ")",
+ e->tok);
}
// the function has no return value (e.g. "void" in C)
else if (nlocops == 0)
@@ -2468,7 +2483,8 @@ struct dwflpp
throw semantic_error("function "
+ string(dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + string(dwarf_diename(cu) ?: "<unknown>")
- + ") has no return value");
+ + ") has no return value",
+ e->tok);
}
struct location *head = c_translate_location (&pool, &loc2c_error, this,
@@ -2486,7 +2502,7 @@ struct dwflpp
Dwarf_Die *vardie = dwarf_formref_die (attr, &vardie_mem);
Dwarf_Die die_mem, *die = NULL;
- die = translate_components (&pool, &tail, pc, components,
+ die = translate_components (&pool, &tail, pc, e,
vardie, &die_mem, &attr_mem);
if(!die)
{
@@ -2500,7 +2516,8 @@ struct dwflpp
+ string(dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + string(dwarf_diename(cu) ?: "<unknown>")
+ ")"
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
@@ -2512,7 +2529,7 @@ struct dwflpp
string prelude, postlude;
translate_final_fetch_or_store (&pool, &tail, module_bias,
- die, &attr_mem, lvalue,
+ die, &attr_mem, lvalue, e,
prelude, postlude, ty);
/* Write the translation to a string. */
@@ -2522,8 +2539,7 @@ struct dwflpp
string
literal_stmt_for_pointer (Dwarf_Die *type_die,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
bool lvalue,
exp_type & ty)
{
@@ -2545,7 +2561,7 @@ struct dwflpp
Dwarf_Attribute attr_mem;
Dwarf_Die die_mem, *die = NULL;
- die = translate_components (&pool, &tail, 0, components,
+ die = translate_components (&pool, &tail, 0, e,
type_die, &die_mem, &attr_mem);
if(!die)
{
@@ -2554,7 +2570,8 @@ struct dwflpp
print_members(die ?: type_die, alternatives);
throw semantic_error("unable to find member for struct "
+ string(dwarf_diename(die ?: type_die) ?: "<unknown>")
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
@@ -2566,7 +2583,7 @@ struct dwflpp
string prelude, postlude;
translate_final_fetch_or_store (&pool, &tail, module_bias,
- die, &attr_mem, lvalue,
+ die, &attr_mem, lvalue, e,
prelude, postlude, ty);
/* Write the translation to a string. */
@@ -4865,7 +4882,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
{
ec->code = q.dw.literal_stmt_for_return (scope_die,
addr,
- e->components,
+ e,
lvalue,
fdecl->type);
}
@@ -4874,7 +4891,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
ec->code = q.dw.literal_stmt_for_local (scope_die,
addr,
e->base_name.substr(1),
- e->components,
+ e,
lvalue,
fdecl->type);
}
@@ -5008,7 +5025,7 @@ dwarf_cast_query::handle_query_cu(Dwarf_Die * cudie)
{
try
{
- code = dw.literal_stmt_for_pointer (type_die, e.components,
+ code = dw.literal_stmt_for_pointer (type_die, &e,
lvalue, pe_type);
}
catch (const semantic_error& e)
@@ -6231,7 +6248,7 @@ module_info::~module_info()
delete sym_table;
}
-// Helper function to emit vma tracker callback _stp_tf_vm_cb.
+// Helper function to emit vma tracker callbacks.
static void
emit_vma_callback_probe_decl (systemtap_session& s,
string path,
@@ -6249,7 +6266,9 @@ emit_vma_callback_probe_decl (systemtap_session& s,
s.op->line() << " .pid=" << pid << ",";
}
s.op->line() << " .callback=NULL,";
- s.op->line() << " .vm_callback=&_stp_tf_vm_cb,";
+ s.op->line() << " .mmap_callback=&_stp_tf_mmap_cb,";
+ s.op->line() << " .munmap_callback=&_stp_tf_munmap_cb,";
+ s.op->line() << " .mprotect_callback=NULL,";
s.op->line() << " },";
}
@@ -6557,6 +6576,7 @@ itrace_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline();
s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "_stp_sym_init();";
s.op->newline() << "/* ---- itrace vma callbacks ---- */";
s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_itrace_vmcbs); i++) {";
s.op->indent(1);
@@ -6971,7 +6991,9 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
}
s.op->line() << " .callback=&_stp_utrace_probe_cb,";
- s.op->line() << " .vm_callback=NULL,";
+ s.op->line() << " .mmap_callback=NULL,";
+ s.op->line() << " .munmap_callback=NULL,";
+ s.op->line() << " .mprotect_callback=NULL,";
s.op->line() << " },";
s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
s.op->line() << " .ph=&" << p->name << ",";
@@ -7303,6 +7325,7 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline();
s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "_stp_sym_init();";
s.op->newline() << "/* ---- utrace vma callbacks ---- */";
s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_vmcbs); i++) {";
s.op->indent(1);
@@ -7745,23 +7768,25 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(0) << "return stap_uprobe_change (tsk, register_p, 0, sups);";
s.op->newline(-1) << "}";
- // The task_finder_vm_callback we use for ET_DYN targets.
+ // The task_finder_mmap_callback we use for ET_DYN targets.
s.op->newline();
- s.op->newline() << "static int stap_uprobe_vmchange_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, unsigned long vm_start, unsigned long vm_end, unsigned long vm_pgoff) {";
+ s.op->newline() << "static int stap_uprobe_mmap_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, char *path, unsigned long addr, unsigned long length, unsigned long offset, unsigned long vm_flags) {";
s.op->newline(1) << "struct stap_uprobe_spec *sups = container_of(tgt, struct stap_uprobe_spec, finder);";
// 1 - shared libraries' executable segments load from offset 0 - ld.so convention
- s.op->newline() << "if (vm_pgoff != 0) return 0;";
+ s.op->newline() << "if (offset != 0) return 0;";
// 2 - the shared library we're interested in
- s.op->newline() << "if (vm_path == NULL || strcmp (vm_path, sups->pathname)) return 0;";
+ s.op->newline() << "if (path == NULL || strcmp (path, sups->pathname)) return 0;";
// 3 - probe address within the mapping limits; test should not fail
- s.op->newline() << "if (vm_end <= vm_start + sups->address) return 0;";
+ s.op->newline() << "if (sups->address >= addr && sups->address < (addr + length)) return 0;";
+ // 4 - mapping should be executable
+ s.op->newline() << "if (!(vm_flags & VM_EXEC)) return 0;";
s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA";
- s.op->newline() << "printk (KERN_INFO \"vmchange pid %d map_p %d path %s vms %p vme %p vmp %p\\n\", tsk->tgid, map_p, vm_path, (void*) vm_start, (void*) vm_end, (void*) vm_pgoff);";
+ s.op->newline() << "printk (KERN_INFO \"vmchange pid %d path %s addr %p length %lu offset %p\\n\", tsk->tgid, path, (void *) addr, length, (void*) offset);";
s.op->newline() << "printk (KERN_INFO \"sups %p pp %s path %s address %p\\n\", sups, sups->pp, sups->pathname ?: \"\", (void*) sups->address);";
s.op->newline() << "#endif";
- s.op->newline(0) << "return stap_uprobe_change (tsk, map_p, vm_start, sups);";
+ s.op->newline(0) << "return stap_uprobe_change (tsk, 1, addr, sups);";
s.op->newline(-1) << "}";
s.op->assert_0_indent();
@@ -7775,6 +7800,7 @@ uprobe_derived_probe_group::emit_module_init (systemtap_session& s)
{
if (probes.empty()) return;
s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "_stp_sym_init();";
s.op->newline() << "/* ---- uprobe vma callbacks ---- */";
s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_uprobe_vmcbs); i++) {";
s.op->indent(1);
@@ -7798,7 +7824,7 @@ uprobe_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline(1) << "struct stap_uprobe_spec *sups = & stap_uprobe_specs[i];";
s.op->newline() << "probe_point = sups->pp;"; // for error messages
s.op->newline() << "if (sups->finder.pathname) sups->finder.callback = & stap_uprobe_process_found;";
- s.op->newline() << "else if (sups->pathname) sups->finder.vm_callback = & stap_uprobe_vmchange_found;";
+ s.op->newline() << "else if (sups->pathname) sups->finder.mmap_callback = & stap_uprobe_mmap_found;";
s.op->newline() << "rc = stap_register_task_finder_target (& sups->finder);";
// NB: if (rc), there is no need (XXX: nor any way) to clean up any
@@ -8654,6 +8680,7 @@ struct mark_derived_probe: public derived_probe
bool target_symbol_seen;
void join_group (systemtap_session& s);
+ void print_dupe_stamp (ostream& o);
void emit_probe_context_vars (translator_output* o);
void initialize_probe_context_vars (translator_output* o);
void printargs (std::ostream &o) const;
@@ -8757,36 +8784,9 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
// Remember that we've seen a target variable.
target_symbol_seen = true;
- // Synthesize a function.
- functiondecl *fdecl = new functiondecl;
- fdecl->tok = e->tok;
- embeddedcode *ec = new embeddedcode;
- ec->tok = e->tok;
-
- string fname = string("_mark_tvar_get")
- + "_" + e->base_name.substr(1)
- + "_" + lex_cast<string>(tick++);
-
- if (mark_args[argnum-1]->stp_type == pe_long)
- ec->code = string("THIS->__retvalue = CONTEXT->locals[0].")
- + probe_name + string(".__mark_arg")
- + lex_cast<string>(argnum) + string (";");
- else
- ec->code = string("strlcpy (THIS->__retvalue, CONTEXT->locals[0].")
- + probe_name + string(".__mark_arg")
- + lex_cast<string>(argnum) + string (", MAXSTRINGLEN);");
- ec->code += "/* pure */";
- fdecl->name = fname;
- fdecl->body = ec;
- fdecl->type = mark_args[argnum-1]->stp_type;
- sess.functions[fdecl->name]=fdecl;
-
- // Synthesize a functioncall.
- functioncall* n = new functioncall;
- n->tok = e->tok;
- n->function = fname;
- n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
- provide (n);
+ e->probe_context_var = "__mark_arg" + lex_cast<string>(argnum);
+ e->type = mark_args[argnum-1]->stp_type;
+ provide (e);
}
@@ -9037,6 +9037,15 @@ mark_derived_probe::join_group (systemtap_session& s)
void
+mark_derived_probe::print_dupe_stamp (ostream& o)
+{
+ if (target_symbol_seen)
+ for (unsigned i = 0; i < mark_args.size(); i++)
+ o << mark_args[i]->c_type << " __mark_arg" << (i+1) << endl;
+}
+
+
+void
mark_derived_probe::emit_probe_context_vars (translator_output* o)
{
// If we haven't seen a target symbol for this probe, quit.
@@ -9374,6 +9383,7 @@ struct tracepoint_derived_probe: public derived_probe
void build_args(dwflpp& dw, Dwarf_Die& func_die);
void printargs (std::ostream &o) const;
void join_group (systemtap_session& s);
+ void print_dupe_stamp(ostream& o);
void emit_probe_context_vars (translator_output* o);
};
@@ -9463,33 +9473,10 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
if (e->components.empty())
{
- // Synthesize a simple function to grab the parameter
- functiondecl *fdecl = new functiondecl;
- fdecl->tok = e->tok;
- embeddedcode *ec = new embeddedcode;
- ec->tok = e->tok;
-
- string fname = (string("_tracepoint_tvar_get")
- + "_" + e->base_name.substr(1)
- + "_" + lex_cast<string>(tick++));
-
- fdecl->name = fname;
- fdecl->body = ec;
- fdecl->type = pe_long;
-
- ec->code = (string("THIS->__retvalue = CONTEXT->locals[0].")
- + probe_name + string(".__tracepoint_arg_")
- + arg->name + string (";/* pure */"));
-
- dw.sess.functions[fdecl->name] = fdecl;
-
- // Synthesize a functioncall.
- functioncall* n = new functioncall;
- n->tok = e->tok;
- n->function = fname;
- n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
-
- provide (n);
+ // Just grab the value from the probe locals
+ e->probe_context_var = "__tracepoint_arg_" + arg->name;
+ e->type = pe_long;
+ provide (e);
}
else
{
@@ -9509,7 +9496,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
try
{
- ec->code = dw.literal_stmt_for_pointer (&arg->type_die, e->components,
+ ec->code = dw.literal_stmt_for_pointer (&arg->type_die, e,
lvalue, fdecl->type);
}
catch (const semantic_error& er)
@@ -9612,7 +9599,6 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
}
else if (e->base_name == "$$vars" || e->base_name == "$$parms")
{
- target_symbol *tsym = new target_symbol;
print_format* pf = new print_format;
// Convert $$vars to sprintf of a list of vars which we recursively evaluate
@@ -9636,6 +9622,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
if (i > 0)
pf->raw_components += " ";
pf->raw_components += args[i].name;
+ target_symbol *tsym = new target_symbol;
tsym->tok = e->tok;
tsym->base_name = "$" + args[i].name;
@@ -9866,6 +9853,15 @@ tracepoint_derived_probe::join_group (systemtap_session& s)
void
+tracepoint_derived_probe::print_dupe_stamp(ostream& o)
+{
+ for (unsigned i = 0; i < args.size(); i++)
+ if (args[i].used)
+ o << "__tracepoint_arg_" << args[i].name << endl;
+}
+
+
+void
tracepoint_derived_probe::emit_probe_context_vars (translator_output* o)
{
for (unsigned i = 0; i < args.size(); i++)
@@ -10205,11 +10201,16 @@ struct hrtimer_derived_probe: public derived_probe
int64_t interval, randomize;
- hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r):
+ hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r,
+ int64_t scale):
derived_probe (p, l), interval (i), randomize (r)
{
if ((i < min_ns_interval) || (i > max_ns_interval))
- throw semantic_error("interval value out of range");
+ throw semantic_error(string("interval value out of range (")
+ + lex_cast<string>(scale < min_ns_interval
+ ? min_ns_interval/scale : 1)
+ + ","
+ + lex_cast<string>(max_ns_interval/scale) + ")");
// randomize = 0 means no randomization
if ((r < 0) || (r > i))
@@ -10387,7 +10388,7 @@ timer_builder::build(systemtap_session & sess,
literal_map_t const & parameters,
vector<derived_probe *> & finished_results)
{
- int64_t period, rand=0;
+ int64_t scale=1, period, rand=0;
if (!get_param(parameters, "randomize", rand))
rand = 0;
@@ -10408,20 +10409,23 @@ timer_builder::build(systemtap_session & sess,
else if (get_param(parameters, "s", period)
|| get_param(parameters, "sec", period))
{
- period *= 1000000000;
- rand *= 1000000000;
+ scale = 1000000000;
+ period *= scale;
+ rand *= scale;
}
else if (get_param(parameters, "ms", period)
|| get_param(parameters, "msec", period))
{
- period *= 1000000;
- rand *= 1000000;
+ scale = 1000000;
+ period *= scale;
+ rand *= scale;
}
else if (get_param(parameters, "us", period)
|| get_param(parameters, "usec", period))
{
- period *= 1000;
- rand *= 1000;
+ scale = 1000;
+ period *= scale;
+ rand *= scale;
}
else if (get_param(parameters, "ns", period)
|| get_param(parameters, "nsec", period))
@@ -10444,7 +10448,7 @@ timer_builder::build(systemtap_session & sess,
}
else
finished_results.push_back(
- new hrtimer_derived_probe(base, location, period, rand));
+ new hrtimer_derived_probe(base, location, period, rand, scale));
}
void
diff --git a/testsuite/buildok/uaddr.stp b/testsuite/buildok/uaddr.stp
new file mode 100755
index 00000000..8acfc495
--- /dev/null
+++ b/testsuite/buildok/uaddr.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for uaddr()
+#
+probe begin
+{
+ printf("uaddr: 0x%x\n", uaddr())
+}
diff --git a/testsuite/buildok/usymdata.stp b/testsuite/buildok/usymdata.stp
new file mode 100755
index 00000000..48c1f36f
--- /dev/null
+++ b/testsuite/buildok/usymdata.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for usymdata()
+#
+probe begin
+{
+ log(usymdata(0))
+}
diff --git a/testsuite/buildok/usymname.stp b/testsuite/buildok/usymname.stp
new file mode 100755
index 00000000..57e3f9c2
--- /dev/null
+++ b/testsuite/buildok/usymname.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for usymname()
+#
+probe begin
+{
+ log(usymname(0))
+}
diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp
index 8af20126..39b3b442 100644
--- a/testsuite/systemtap.context/usymbols.exp
+++ b/testsuite/systemtap.context/usymbols.exp
@@ -35,7 +35,7 @@ set testscript {
probe syscall.rt_sigaction {
if (pid() == target() && execname() == "%s") {
handler = $act->sa_handler;
- printf("handler: %%s\n", symname(handler));
+ printf("handler: %%s\n", usymname(handler));
}
}
/* track through uprobes, so as to make sure we have the symbols */
@@ -56,8 +56,7 @@ if {[string equal "link" [file type $libpath]]} {
}
send_log "libpath: $libpath\n"
-# XXX Cheat, explicitly add STP_NEED_VMA_TRACKER
-set cmd [concat stap -DSTP_NEED_VMA_TRACKER -d $libpath -d $testexe -c $testexe -e {$script}]
+set cmd [concat stap -d $libpath -d $testexe -c $testexe -e {$script}]
send_log "cmd: $cmd\n"
catch {eval exec $cmd} res
send_log "cmd output: $res\n"
diff --git a/testsuite/systemtap.examples/network/nettop.stp b/testsuite/systemtap.examples/network/nettop.stp
index 15b4d62a..b84e4882 100755
--- a/testsuite/systemtap.examples/network/nettop.stp
+++ b/testsuite/systemtap.examples/network/nettop.stp
@@ -1,6 +1,7 @@
#! /usr/bin/env stap
global ifxmit, ifrecv
+global ifmerged
probe netdev.transmit
{
@@ -19,6 +20,12 @@ function print_activity()
"XMIT_KB", "RECV_KB", "COMMAND")
foreach ([pid, dev, exec, uid] in ifrecv-) {
+ ifmerged[pid, dev, exec, uid] = 1;
+ }
+ foreach ([pid, dev, exec, uid] in ifxmit-) {
+ ifmerged[pid, dev, exec, uid] = 1;
+ }
+ foreach ([pid, dev, exec, uid] in ifmerged-) {
n_xmit = @count(ifxmit[pid, dev, exec, uid])
n_recv = @count(ifrecv[pid, dev, exec, uid])
printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n",
@@ -32,6 +39,7 @@ function print_activity()
delete ifxmit
delete ifrecv
+ delete ifmerged
}
probe timer.ms(5000), end, error
diff --git a/translate.cxx b/translate.cxx
index 9e1c2519..1a86dcd2 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -919,6 +919,7 @@ c_unparser::emit_common_header ()
ostringstream oss;
oss << "c->statp = & time_" << dp->basest()->name << ";" << endl; // -t anti-dupe
oss << "# needs_global_locks: " << dp->needs_global_locks () << endl;
+ dp->print_dupe_stamp (oss);
dp->body->print(oss);
// NB: dependent probe conditions *could* be listed here, but don't need to be.
// That's because they're only dependent on the probe body, which is already
@@ -1546,6 +1547,7 @@ c_unparser::emit_probe (derived_probe* v)
// be very different with or without -t.
oss << "c->statp = & time_" << v->basest()->name << ";" << endl;
+ v->print_dupe_stamp (oss);
v->body->print(oss);
// Since the generated C changes based on whether or not the probe
@@ -3527,7 +3529,10 @@ c_unparser_assignment::visit_symbol (symbol *e)
void
c_unparser::visit_target_symbol (target_symbol* e)
{
- throw semantic_error("cannot translate general target-symbol expression", e->tok);
+ if (!e->probe_context_var.empty())
+ o->line() << "l->" << e->probe_context_var;
+ else
+ throw semantic_error("cannot translate general cast expression", e->tok);
}
@@ -4610,10 +4615,13 @@ dump_unwindsyms (Dwfl_Module *m,
// 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.
+ // functions in the kernel. We also omit symbols that have
+ // suspicious addresses (before base).
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_shndx == SHN_UNDEF
+ || sym.st_shndx == SHN_ABS
+ || sym.st_value < base))
{
Dwarf_Addr sym_addr = sym.st_value;
const char *secname = NULL;