summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-07-04 17:11:29 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-07-04 17:11:29 -0400
commit53f7dd30e87fa480c5d43ce2a1312ce27a4372c9 (patch)
tree4f1c64048d43c50c11877a66d3f7f918e43a0f7b
parent1b94bf6d310cf41041d0a6c24be85a892d443708 (diff)
parent422b0781177e0755df5542e1c70e809e6f3cfe89 (diff)
downloadsystemtap-steved-53f7dd30e87fa480c5d43ce2a1312ce27a4372c9.tar.gz
systemtap-steved-53f7dd30e87fa480c5d43ce2a1312ce27a4372c9.tar.xz
systemtap-steved-53f7dd30e87fa480c5d43ce2a1312ce27a4372c9.zip
Merge commit 'origin/master' into pr6429-comp-unwindsyms
* commit 'origin/master': ubuntu (2.6.24-16-server) kernel compatibility fix client/server take 2. See bz6565. Add functioncallcount.meta and functioncallcount.stp. Add para-callgraph.stp and para-callgraph.meta. Fixed __stp_get_mm_path() error return code. diagnostics improvement: print arch/mach at top if -vv Make _vfs.generic_commit_write only for kernel<=2.6.25 Handles "mortally wounded" threads correctly when detaching. further clarify that elfutils need not be absolutely freshest, nor rebuilt every time point out releases/ directory; clarify optionality of elfutils bundling Add auto_free_ref to auto_free stuff; bug 6694
-rw-r--r--ChangeLog48
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in2
-rw-r--r--README15
-rw-r--r--auto_free.h28
-rw-r--r--main.cxx7
-rw-r--r--runtime/ChangeLog15
-rw-r--r--runtime/task_finder.c76
-rwxr-xr-xstap-client146
-rwxr-xr-xstap-server113
-rwxr-xr-xstap-serverd93
-rw-r--r--tapset/ChangeLog4
-rw-r--r--tapset/vfs.stp2
-rw-r--r--tapsets.cxx4
-rw-r--r--testsuite/ChangeLog6
-rw-r--r--testsuite/buildok/vfs_testcase.stp2
-rw-r--r--testsuite/systemtap.examples/ChangeLog8
-rw-r--r--testsuite/systemtap.examples/functioncallcount.meta13
-rw-r--r--testsuite/systemtap.examples/functioncallcount.stp17
-rw-r--r--testsuite/systemtap.examples/para-callgraph.meta13
-rw-r--r--testsuite/systemtap.examples/para-callgraph.stp20
-rw-r--r--translate.cxx2
22 files changed, 465 insertions, 171 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b1b25b0..4c0b90a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,51 @@
+2008-07-03 Frank Ch. Eigler <fche@elastic.org>
+
+ * translate.cxx (translate_pass): Don't #include <linux/compile.h>.
+
+2008-07-03 <brolley@redhat.com>
+
+ * stap-serverd: New script.
+ * stap-client (client_sysinfo): Client sysinfo is stripped down to
+ the output of `uname -r` for now.
+ (package_request): Don't create temporary server tar file here.
+ (send_request): Communication protocol simplified. Use nc to send
+ the tar file.
+ (receive_response): Communication protocol eliminated. Simply wait
+ for the file from the server using nc.
+ (unpack_response): Create temporary server tar file here. Verify the
+ contents of the server's response.
+ (find_and_connect_to_server): Obtain server address and port from
+ avahi-browse.
+ (server_fatal): New function.
+ (check_server_error): Call server_fatal.
+ * stap-server (configuration): port is now provided as an argument.
+ Default to port 65001.
+ (initialization): Don't create temp work directory here.
+ (receive_request): Communication protocol simplified. Receive the
+ request file using nc.
+ (unpack_request): Make temp work directory here. Verify the contents
+ of the request.
+ (server_sysinfo): New function.
+ (check_compatibility): Exact match required.
+ (package_response): Don't use -p on tar command.
+ (send_response): Communication protocol eliminated. Simply send the
+ file using nc.
+ (main line): Pass "$@" to configuration.
+
+2008-07-01 Frank Ch. Eigler <fche@elastic.org>
+
+ * main.cxx (main): In -vv mode, also dump out session arch/release
+ values right at the top.
+
+2008-06-29 Tim Moore <timoore@redhat.com>
+
+ * Makefile.am (EXTRA_DIST): Add auto_free.h.
+ * Makefile.in: Regenerated.
+ * auto_free.h (auto_free_ref): New class to free references to
+ pointers allocated with malloc / realloc.
+ * tapsets.cxx (iterate_over_srcfile_lines): Use auto_free_ref at
+ top level of function to free srcsp.
+
2008-06-27 David Smith <dsmith@redhat.com>
* tapsets.cxx (utrace_derived_probe_group::emit_module_decls): Fix
diff --git a/Makefile.am b/Makefile.am
index 3e5bd6c9..8333281e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -148,7 +148,7 @@ endif
# Get extra libs as needed
LDADD =
-EXTRA_DIST = buildrun.h elaborate.h loc2c.h session.h \
+EXTRA_DIST = auto_free.h buildrun.h elaborate.h loc2c.h session.h \
parse.h staptree.h tapsets.h translate.h \
cache.h hash.h mdfour.h util.h staplog.c coveragedb.h \
testsuite systemtap.spec runtime tapset \
diff --git a/Makefile.in b/Makefile.in
index 675edde2..dc039c3f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -324,7 +324,7 @@ loc2c_test_LDADD = $(stap_LDADD)
# Get extra libs as needed
LDADD =
-EXTRA_DIST = buildrun.h elaborate.h loc2c.h session.h \
+EXTRA_DIST = auto_free.h buildrun.h elaborate.h loc2c.h session.h \
parse.h staptree.h tapsets.h translate.h \
cache.h hash.h mdfour.h util.h staplog.c coveragedb.h \
testsuite systemtap.spec runtime tapset \
diff --git a/README b/README
index b36d7241..5fb8d408 100644
--- a/README
+++ b/README
@@ -27,18 +27,23 @@ Build steps:
- Install the kernel-debuginfo, kernel-[smp-]devel, gcc and libcap-devel
packages (or see below if you are building your own kernels from source).
-- Download the latest elfutils snapshot (if desired):
+
+- If desired, download a recent elfutils snapshot to build in "bundled mode".
+ If desired, build it separately one time, and install it to /usr/local.
+
ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-NNNN.tar.gz
ftp://sources.redhat.com/pub/systemtap/elfutils/elfutils-portability.patch
- Untar the snapshot in some new directory; apply patch (don't ask, long story)
-- Download systemtap sources snapshot or from GIT:
- ftp://sources.redhat.com/pub/systemtap/snapshots/
+
+- Download systemtap sources:
+ http://sources.redhat.com/systemtap/ftp/releases/
+ http://sources.redhat.com/systemtap/ftp/snapshots/
(or)
git clone git://sources.redhat.com/git/systemtap.git
(or) http://sources.redhat.com/git/systemtap.git
+
- Build it:
- cd src
- ./configure --with-elfutils=PATCHED-ELFUTILS-DIR [other autoconf options]
+ .../configure [--with-elfutils=PATCHED-ELFUTILS-DIR] [other autoconf options]
make all check
sudo make install
sudo make installcheck
diff --git a/auto_free.h b/auto_free.h
index b13e7371..58290821 100644
--- a/auto_free.h
+++ b/auto_free.h
@@ -27,14 +27,32 @@ public:
}
private:
// No copying allowed.
- auto_free(const auto_free& af)
+ auto_free(const auto_free& af);
+ // No assignment either
+ auto_free& operator=(const auto_free& rhs);
+ void* _ptr;
+};
+
+// Use this to free a pointer whose value may change after the initial
+// allocation e.g., be realloced.
+template <typename T>
+class auto_free_ref
+{
+public:
+ typedef T pointer_type;
+ auto_free_ref(pointer_type& ptr) : _ptr(ptr)
{
}
- // No assignment either
- auto_free& operator=(const auto_free& rhs)
+ ~auto_free_ref()
{
- return *this;
+ if (_ptr)
+ std::free(_ptr);
}
- void* _ptr;
+private:
+ // No copying allowed.
+ auto_free_ref(const auto_free_ref& af);
+ // No assignment either
+ auto_free_ref& operator=(const auto_free_ref& rhs);
+ pointer_type& _ptr;
};
#endif
diff --git a/main.cxx b/main.cxx
index 23ab3b2f..edb72768 100644
--- a/main.cxx
+++ b/main.cxx
@@ -713,7 +713,12 @@ main (int argc, char * const argv [])
// arguments parsed; get down to business
if (s.verbose > 1)
- version ();
+ {
+ version ();
+ clog << "Session arch: " << s.architecture
+ << " release: " << s.kernel_release
+ << endl;
+ }
// Create a temporary directory to build within.
// Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end.
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 6da5814c..f7f1a5a8 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,18 @@
+2008-07-01 David Smith <dsmith@redhat.com>
+
+ * task_finder.c (__stp_get_mm_path): Corrected error return code.
+ (__stp_utrace_attach_match_tsk): Ignores ENOENT error from
+ __stp_get_mm_path().
+ (stap_start_task_finder): Ditto.
+
+2008-06-30 David Smith <dsmith@redhat.com>
+
+ * task_finder.c (stap_utrace_detach_ops): Removed check to see if
+ thread has a mm (in the case where a thread isn't quite dead
+ yet).
+ (stap_utrace_attach): Minor error handling improvement.
+ (__stp_utrace_attach_match_tsk): Ditto.
+
2008-06-24 David Smith <dsmith@redhat.com>
From: Srinivasa DS <srinivasa@in.ibm.com>
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 07610864..316a9bc0 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -149,30 +149,37 @@ stap_utrace_detach_ops(struct utrace_engine_ops *ops)
long error = 0;
pid_t pid = 0;
+ // Notice we're not calling get_task_mm() in this loop. In
+ // every other instance when calling do_each_thread, we avoid
+ // tasks with no mm, because those are kernel threads. So,
+ // why is this function different? When a thread is in the
+ // process of dying, its mm gets freed. Then, later the
+ // thread gets in the dying state and the thread's
+ // UTRACE_EVENT(DEATH) event handler gets called (if any).
+ //
+ // If a thread is in this "mortally wounded" state - no mm
+ // but not dead - and at that moment this function is called,
+ // we'd miss detaching from it if we were checking to see if
+ // it had an mm.
+
rcu_read_lock();
do_each_thread(grp, tsk) {
- struct mm_struct *mm;
-
- if (tsk->pid <= 1)
+ if (tsk == NULL || tsk->pid <= 1)
continue;
- mm = get_task_mm(tsk);
- if (mm) {
- mmput(mm);
- engine = utrace_attach(tsk, UTRACE_ATTACH_MATCH_OPS,
- ops, 0);
- if (IS_ERR(engine)) {
- error = -PTR_ERR(engine);
- if (error != ENOENT) {
- pid = tsk->pid;
- goto udo_err;
- }
- error = 0;
- }
- else if (engine != NULL) {
- utrace_detach(tsk, engine);
- debug_task_finder_detach();
+ engine = utrace_attach(tsk, UTRACE_ATTACH_MATCH_OPS,
+ ops, 0);
+ if (IS_ERR(engine)) {
+ error = -PTR_ERR(engine);
+ if (error != ENOENT) {
+ pid = tsk->pid;
+ goto udo_err;
}
+ error = 0;
+ }
+ else if (engine != NULL) {
+ utrace_detach(tsk, engine);
+ debug_task_finder_detach();
}
} while_each_thread(grp, tsk);
udo_err:
@@ -242,7 +249,7 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
}
else {
*buf = '\0';
- rc = ERR_PTR(ENOENT);
+ rc = ERR_PTR(-ENOENT);
}
up_read(&mm->mmap_sem);
return rc;
@@ -276,7 +283,7 @@ stap_utrace_attach(struct task_struct *tsk,
int rc = 0;
// Ignore init
- if (tsk->pid <= 1)
+ if (tsk == NULL || tsk->pid <= 1)
return EPERM;
// Ignore threads with no mm (which are kernel threads).
@@ -300,8 +307,12 @@ stap_utrace_attach(struct task_struct *tsk,
rc = EFAULT;
}
else {
- utrace_set_flags(tsk, engine, event_flags);
- debug_task_finder_attach();
+ rc = utrace_set_flags(tsk, engine, event_flags);
+ if (rc == 0)
+ debug_task_finder_attach();
+ else
+ _stp_error("utrace_set_flags returned error %d on pid %d",
+ rc, (int)tsk->pid);
}
return rc;
}
@@ -392,7 +403,8 @@ __stp_utrace_attach_match_tsk(struct task_struct *path_tsk,
char *mmpath_buf;
char *mmpath;
- if (path_tsk->pid <= 1 || match_tsk->pid <= 1)
+ if (path_tsk == NULL || path_tsk->pid <= 1
+ || match_tsk == NULL || match_tsk->pid <= 1)
return;
/* Grab the path associated with the path_tsk. */
@@ -416,8 +428,9 @@ __stp_utrace_attach_match_tsk(struct task_struct *path_tsk,
mmput(mm); /* We're done with mm */
if (mmpath == NULL || IS_ERR(mmpath)) {
int rc = -PTR_ERR(mmpath);
- _stp_error("Unable to get path (error %d) for pid %d",
- rc, (int)path_tsk->pid);
+ if (rc != ENOENT)
+ _stp_error("Unable to get path (error %d) for pid %d",
+ rc, (int)path_tsk->pid);
}
else {
__stp_utrace_attach_match_filename(match_tsk, mmpath,
@@ -940,9 +953,14 @@ stap_start_task_finder(void)
mmput(mm); /* We're done with mm */
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);
- goto stf_err;
+ if (rc == ENOENT) {
+ continue;
+ }
+ else {
+ _stp_error("Unable to get path (error %d) for pid %d",
+ rc, (int)tsk->pid);
+ goto stf_err;
+ }
}
/* Check the thread's exe's path/pid against our list. */
diff --git a/stap-client b/stap-client
index 42402a27..515cab92 100755
--- a/stap-client
+++ b/stap-client
@@ -314,12 +314,8 @@ function create_request {
# Generate the client's sysinfo and echo it to stdout
function client_sysinfo {
if test "X$sysinfo_client" = "X"; then
- # Get the stap version
- stap_version=`stap -V 2>&1 | grep version`
- # Remove the number before the first slash
- stap_version=`expr "$stap_version" : '.*version [^/]*/\([0-9./]*\).*'`
# Add some info from uname
- sysinfo_client="stap $stap_version `uname -sr`"
+ sysinfo_client="`uname -r`"
fi
echo $sysinfo_client
}
@@ -338,67 +334,50 @@ function package_request {
tar -czhf $tar_client $tmpdir_client_base || \
fatal "ERROR: tar of request tree, $tmpdir_client, failed"
-
- tar_server=$tmpdir_env/`mktemp $tmpdir_prefix_server.tgz.XXXXXX` || \
- fatal "ERROR: cannot create temporary file " $tar_server
}
# function: send_request
#
-# Notify the server and then send $tar_client to the server as $tar_server
+# Notify the server and then send $tar_client to the server
# The protocol is:
-# client -> "request: $tmpdir_client"
-# server -> "send: $tar_server"
-# client: rsync local:$tar_client server:$tar_server
-# client -> "waiting:"
+# client -> "request:"
+# server -> "ready:"
+# client -> $tar_client
#
# $tmpdir_client is provided on the request so that the server knows what
# the tar file will expand to.
function send_request {
- echo "request: `basename $tmpdir_client`" >&3
+ echo "request:" >&3
+ # Get the server's response.
read <&3
local line=$REPLY
check_server_error $line
- local tar_dest=`expr "$line" : 'send: \([^ ]*\)$'`
- test "X$tar_dest" == "X" && \
- fatal "ERROR: destination tar file not provided"
-
- rsync -essh -a --delete $tar_client root@$server:$tar_dest || \
- fatal "ERROR: rsync of client request, $tar_client to $server:$tar_dest, failed"
+ # Check for the proper response.
+ test "$line" = "ready:" || \
+ fatal "ERROR: server response, '$line', is incorrect"
- echo "waiting:" >&3
+ # Send the request file.
+ until nc $server $(($port + 1)) < $tar_client
+ do
+ sleep 1
+ done
}
# function: receive_response
#
# Wait for a response from the server indicating the results of our request.
-# The protocol is:
-# server -> "sending: remote-tar-name server-tempdir-name stap-tempdir-name"
-# client -> "OK"
function receive_response {
- read <&3
- local line=$REPLY
- check_server_error $line
-
- tar_dest=`expr "$line" : 'sending: \([^ ]*\) [^ ]* [^ ]*$'`
- test "X$tar_dest" == "X" && \
- fatal "ERROR: server response remote file is missing"
-
- tmpdir_server=`expr "$line" : 'sending: [^ ]* \([^ ]*\) [^ ]*$'`
- test "X$tmpdir_server" == "X" && \
- fatal "ERROR: server response temp dir is missing"
-
- tmpdir_stap=`expr "$line" : 'sending: [^ ]* [^ ]* \([^ ]*\)$'`
- test "X$tmpdir_stap" == "X" && \
- fatal "ERROR: server response stap temp dir is missing"
-
+ # Make a place to receive the response file.
+ tar_server=`mktemp -t $tmpdir_prefix_client.server.tgz.XXXXXX` || \
+ fatal "ERROR: cannot create temporary file " $tar_server
# Retrieve the file
- rsync -essh -a --delete root@$server:$tar_dest $tar_server || \
- fatal "ERROR: rsync of server response, $server:$tar_dest to $tar_server, failed"
- echo "OK" >&3
+ until nc $server $(($port + 1)) > $tar_server
+ do
+ sleep 1
+ done
}
# function: unpack_response
@@ -406,17 +385,45 @@ function receive_response {
# Unpack the tar file received from the server and make the contents available
# for printing the results and/or running 'staprun'.
function unpack_response {
+ tmpdir_server=`mktemp -dt $tmpdir_prefix_client.server.XXXXXX` || \
+ fatal "ERROR: cannot create temporary file " $tmpdir_server
+
# Unpack the server output directory
- cd $tmpdir_client
+ cd $tmpdir_server
tar -xzf $tar_server || \
fatal "ERROR: Unpacking of server response, $tar_server, failed"
- # Create a local location for the server response.
- local local_tmpdir_server_base=`basename $tar_server | sed 's,\.tgz,,'`
- local local_tmpdir_server=`mktemp -dt $local_tmpdir_server_base.XXXXXX` || \
- fatal "ERROR: cannot create temporary directory " $local_tmpdir_server
-
- # Move the systemtap temp directory to our a local temp location, if -k
+ # Identify the server's request tree. The tar file should have expanded
+ # into a single directory named to match $tmpdir_prefix_server.??????
+ # which should now be the only item in the current directory.
+ test "`ls | wc -l`" = 1 || \
+ fatal "ERROR: Wrong number of files after expansion of server's tar file"
+
+ tmpdir_server=`ls`
+ tmpdir_server=`expr "$tmpdir_server" : "\\\($tmpdir_prefix_server\\\\.......\\\)"`
+
+ test "X$tmpdir_server" != "X" || \
+ fatal "ERROR: server tar file did not expand as expected"
+
+ # Check the contents of the expanded directory. It should contain:
+ # 1) a file called stdout
+ # 2) a file called stderr
+ # 3) a directory named to match stap??????
+ test "`ls $tmpdir_server | wc -l`" = 3 || \
+ fatal "ERROR: Wrong number of files after expansion of server's tar file"
+ test -f $tmpdir_server/stdout || \
+ fatal "ERROR: `pwd`/$tmpdir_server/stdout does not exist or is not a regular file"
+ test -f $tmpdir_server/stderr || \
+ fatal "ERROR: `pwd`/$tmpdir_server/stderr does not exist or is not a regular file"
+
+ tmpdir_stap=`ls $tmpdir_server | grep stap`
+ tmpdir_stap=`expr "$tmpdir_stap" : "\\\(stap......\\\)"`
+ test "X$tmpdir_stap" = "X" && \
+ fatal "ERROR: `pwd`/$tmpdir_server/stap?????? does not exist"
+ test -d $tmpdir_server/$tmpdir_stap || \
+ fatal "ERROR: `pwd`/$tmpdir_server/$tmpdir_stap is not a directory"
+
+ # Move the systemtap temp directory to a local temp location, if -k
# was specified.
if test $keep_temps = 1; then
local local_tmpdir_stap=`mktemp -dt stapXXXXXX` || \
@@ -428,13 +435,17 @@ function unpack_response {
sed -i "s,^Keeping temporary directory.*,Keeping temporary directory \"$local_tmpdir_stap\"," $tmpdir_server/stderr
tmpdir_stap=$local_tmpdir_stap
else
- tmpdir_stap=$local_tmpdir_server/$tmpdir_stap
+ tmpdir_stap=`pwd`/$tmpdir_stap
fi
- # Move the extracted tree to our local location
- mv $tmpdir_server/* $local_tmpdir_server
+ # Move the contents of the server's tmpdir down one level to the
+ # current directory (our local server tmpdir)
+ mv $tmpdir_server/* . 2>/dev/null
rm -fr $tmpdir_server
- tmpdir_server=$local_tmpdir_server
+ tmpdir_server=`pwd`
+
+ # Make sure we own the systemtap temp directory if we are root.
+ test $EUID = 0 && chown $EUID:$EUID $tmpdir_stap
}
# function: find_and_connect_to_server
@@ -443,11 +454,14 @@ function unpack_response {
function find_and_connect_to_server {
# Find a server
server=`avahi-browse $avahi_service_tag --terminate -r 2>/dev/null | match_server`
+ port=`expr "$server" : '[^/]*/\(.*\)'`
+ server=`expr "$server" : '\([^/]*\)/.*'`
+
test "X$server" != "X" || \
fatal "ERROR: cannot find a server"
- port=`expr "$server" : '[^/]*/\(.*\)'`
- server=`expr "$server" : '\([^/]*\)/.*'`
+ test "X$port" != "X" || \
+ fatal "ERROR: server port not provided"
# Open a connection to the server
if ! exec 3<> /dev/tcp/$server/$port; then
@@ -500,7 +514,6 @@ function match_server {
;;
txt )
sysinfo_server=`expr "$service_data" : '\[\"\([^]]*\)\"\]'`
- sysinfo_server=`expr "$sysinfo_server" : '[^/]*/\(.*\)'`
;;
* )
break ;;
@@ -508,7 +521,6 @@ function match_server {
done
# It is a stap server, but is it compatible?
- sysinfo_server="stap $sysinfo_server"
if test "$sysinfo_server" != "`client_sysinfo`"; then
continue
fi
@@ -534,9 +546,9 @@ function disconnect_from_server {
# Write the stdout and stderr from the server to stdout and stderr respectively.
function stream_output {
# Output stdout and stderr as directed
- cd $local_tmpdir_server
- cat ${tmpdir_server}/stderr >&2
- eval cat ${tmpdir_server}/stdout $stdout_redirection
+ cd $tmpdir_server
+ cat stderr >&2
+ eval cat stdout $stdout_redirection
}
# function: maybe_call_staprun
@@ -558,7 +570,7 @@ function maybe_call_staprun {
# Check the given server response for an error message.
function check_server_error {
echo $1 | grep -q "^ERROR:" && \
- fatal "Server:" "$@"
+ server_fatal "Server:" "$@"
}
# function: fatal [ MESSAGE ]
@@ -567,6 +579,16 @@ function check_server_error {
# Prints its arguments to stderr and exits
function fatal {
echo $0: "$@" >&2
+ cleanup
+ exit 1
+}
+
+# function: server_fatal [ MESSAGE ]
+#
+# Fatal error
+# Prints its arguments to stderr and exits
+function server_fatal {
+ echo $0: "$@" >&2
cat <&3 >&2
cleanup
exit 1
diff --git a/stap-server b/stap-server
index 1a2e7918..11d6d81d 100755
--- a/stap-server
+++ b/stap-server
@@ -21,6 +21,8 @@ function configuration {
# Configuration
tmpdir_prefix_client=stap.client
tmpdir_prefix_server=stap.server
+ port=$1
+ test "X$port" = "X" && port=65001
}
# function: initialization
@@ -31,54 +33,33 @@ function initialization {
# Default options settings
p_phase=5
keep_temps=0
-
- # Make a temp directory to work in.
- tmpdir_server=`mktemp -dt $tmpdir_prefix_server.XXXXXX` || \
- fatal "ERROR: cannot create temporary directory " $tmpdir_server
- tmpdir_env=`dirname $tmpdir_server`
}
# function: receive_request
#
# Receive a tar file representing the request from the client:
# The protocol is:
-# client -> "request: $tmpdir_client"
-# server -> "send: $tar_client"
-# client: copies file to server:$tar_client
-# client -> "waiting:"
-#
-# $tmpdir_client is provided on the request so that we know what
-# the tar file will expand to.
+# client -> "request:"
+# server -> "ready:"
+# client -> $tar_client
function receive_request {
- cd $tmpdir_server
-
# Request from the client is on stdin
read
line=$REPLY
- # Extract the name of the client's temp directory.
- tmpdir_client=`expr "$line" : 'request: \([^ ]*\)$'`
- test "X$tmpdir_client" == "X" && \
- fatal "ERROR: client request temp dir name is missing" $tmpdir_server
- tmpdir_client=$tmpdir_server/$tmpdir_client
-
- # Create the client's temp dir now to guarantee that it won't clash with
- # any files we need to create later.
- mkdir $tmpdir_client || \
- fatal "ERROR: cannot create client temp dir" $tmpdir_client
+ # Check to see that it is a client request
+ test "$line" = "request:" || \
+ fatal "ERROR: client request, '$line' is incorrect"
# Create a place to receive the client's tar file
- tar_client=`mktemp -t $tmpdir_prefix_client.tgz.XXXXXX` || \
+ tar_client=`mktemp -t $tmpdir_prefix_server.client.tgz.XXXXXX` || \
fatal "ERROR: cannot create temporary tar file " $tar_client
# Request that the file be sent.
- echo "send: $tar_client"
+ echo "ready:"
- # Wait for confirmation that the tar file has arrived via rysnc
- read
- line=$REPLY
- test "X$line" = "Xwaiting:" || \
- fatal "ERROR: client send confirmation, '$line', is incorrect"
+ # Receive the file.
+ nc -l $port < /dev/null > $tar_client
}
# function: unpack_request
@@ -86,15 +67,31 @@ function receive_request {
# Unpack the tar file received from the client and make the contents
# available for use when running 'stap'
function unpack_request {
+ # Make a temp directory to work in.
+ tmpdir_server=`mktemp -dt $tmpdir_prefix_server.XXXXXX` || \
+ fatal "ERROR: cannot create temporary directory " $tmpdir_server
+ tmpdir_env=`dirname $tmpdir_server`
+
cd $tmpdir_server
# Unpack the tar file.
tar -xzf $tar_client || \
fatal "ERROR: cannot unpack tar archive $tar_client"
+ # Identify the client's request tree. The tar file should have expanded
+ # into a single directory named to match $tmpdir_prefix_client.??????
+ # which should now be the only item in the current directory.
+ test "`ls | wc -l`" = 1 || \
+ fatal "ERROR: Wrong number of files after expansion of client's tar file"
+
+ tmpdir_client=`ls`
+ tmpdir_client=`expr "$tmpdir_client" : "\\\($tmpdir_prefix_client\\\\.......\\\)"`
+
+ test "X$tmpdir_client" != "X" || \
+ fatal "ERROR: client tar file did not expand as expected"
+
# Move the client's temp directory to a local temp location
- local tmpdir_client_base=`basename $tar_client | sed 's,\.tgz,,'`
- local local_tmpdir_client=`mktemp -dt $tmpdir_client_base.XXXXXX` || \
+ local local_tmpdir_client=`mktemp -dt $tmpdir_prefix_server.client.XXXXXX` || \
fatal "ERROR: cannot create temporary tar file " $local_tmpdir_client
mv $tmpdir_client/* $local_tmpdir_client
rm -fr $tmpdir_client
@@ -114,19 +111,18 @@ function check_request {
client_sysinfo=`read_data_file sysinfo`
test "X$client_sysinfo" != "X" || exit 1
- # Extract the client's config info.
- client_name=`expr "$client_sysinfo" : 'stap [^ ]* [^ ]* \([^ ]*\).*'`
- client_sysinfo=`echo $client_sysinfo | sed s,$client_name,,`
-
- # Extract the server's config info.
- server_sysinfo=`uname -sr`
- server_name=`expr "$server_sysinfo" : '[^ ]* \([^ ]*\).*'`
- server_sysinfo=`echo $server_sysinfo | sed s,$server_name,,`
- local stap_version=`stap -V 2>&1 | grep version`
- stap_version=`expr "$stap_version" : '.*version \([0-9./]*\).*'`
- server_sysinfo="stap $stap_version $server_sysinfo"
+ check_compatibility "$client_sysinfo" `server_sysinfo`
+}
- check_compatibility "$client_sysinfo" "$server_sysinfo"
+# function server_sysinfo
+#
+# Generate the server's sysinfo and echo it to stdout
+function server_sysinfo {
+ if test "X$sysinfo_server" = "X"; then
+ # Add some info from uname
+ sysinfo_server="`uname -r`"
+ fi
+ echo $sysinfo_server
}
# function check_compaibility SYSINFO1 SYSINFO2
@@ -134,10 +130,9 @@ function check_request {
# Make sure that systemtap as described by SYSINFO1 and SYSINFO2 are compaible
function check_compatibility {
# TODO: This needs work
- # - In stap version x/y, require that the y matches
# - Make sure the linux kernel matches exactly
- local sysinfo1=`echo $1 | sed 's,stap [^/]*/,stap ,'`
- local sysinfo2=`echo $2 | sed 's,stap [^/]*/,stap ,'`
+ local sysinfo1=$1
+ local sysinfo2=$2
if test "$sysinfo1" != "$sysinfo2"; then
error "ERROR: system configuration mismatch"
@@ -361,7 +356,7 @@ function package_response {
chmod +r $tar_server
# Generate the tar file
- tar -czphf $tar_server `basename $tmpdir_server` || \
+ tar -czhf $tar_server `basename $tmpdir_server` || \
fatal "ERROR: tar of $tmpdir_server failed"
}
@@ -370,21 +365,11 @@ function package_response {
# Notify the client that $tar_server is ready and wait for the client to take
# it.
# The protocol is:
-# server -> "sending: $tar_server $tmpdir_server $tmpdir_stap"
-# client: copies file from server:$tar_server
-# client -> "OK"
+# server -> "sending: $tmpdir_server $tmpdir_stap"
+# server -> $tar_server
function send_response {
- # TODO needed for rsync from client to work
- chmod +r $tmpdir_server
-
- # Tell the client where to get it.
- echo "sending: $tar_server `basename $tmpdir_server` `basename $tmpdir_stap`"
-
- # Wait for the confirmation
- read
- line=$REPLY
- test $line = "OK" || \
- fatal "ERROR: client final confirmation, '$line' is incorrect"
+ # Now send it
+ nc -l $port < $tar_server > /dev/null
}
# function: fatal [ MESSAGE ]
@@ -421,7 +406,7 @@ function cleanup {
#-----------------------------------------------------------------------------
# Beginning of main line execution.
#-----------------------------------------------------------------------------
-configuration
+configuration "$@"
initialization
receive_request
unpack_request
diff --git a/stap-serverd b/stap-serverd
new file mode 100755
index 00000000..2c0743c0
--- /dev/null
+++ b/stap-serverd
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+# Compile server manager for systemtap
+#
+# Copyright (C) 2008 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.
+
+# This script publishes its presence on the network and then listens for
+# incoming connections. When a connection is detected, the stap-server script
+# is run to handle the request.
+
+# Catch ctrl-c
+trap 'handle_sigint' SIGINT
+
+#-----------------------------------------------------------------------------
+# Helper functions.
+#-----------------------------------------------------------------------------
+# function: initialization PORT
+function initialization {
+ # Default settings.
+ tmpdir_prefix_serverd=stap.serverd
+ avahi_type=_stap._tcp
+ port=$1
+ test "X$port" = "X" && port=65000
+}
+
+# function: advertise_presence
+#
+# Advertise the availability of the server on the network.
+function advertise_presence {
+ # Build up a string representing our server's properties.
+ # TODO: this needs fleshing out.
+
+ local sysinfo=`uname -r`
+ local txt="$sysinfo"
+
+ # Call avahi-publish-service to advertise our presence.
+ avahi-publish-service "Systemtap Compile Server on `uname -n`" \
+ $avahi_type $port $txt > /dev/null 2>&1 &
+
+ echo "Systemtap Compile Server on `uname -n` listening on port $port"
+}
+
+# function: listen
+#
+# Listen for and handle requests to the server.
+function listen {
+ # Work in a temporary directory
+ tmpdir=`mktemp -dt $tmpdir_prefix_serverd.XXXXXX` || \
+ fatal "ERROR: cannot create temporary directory " $tmpdir
+ cd $tmpdir
+
+ # Create a fifo for communicating with the server
+ local fifo_name=$tmpdir_prefix_serverd.fifo
+ mknod $fifo_name p || \
+ fatal "ERROR: cannot create temporary fifo " $tmpdir/$fifo_name
+
+ # Loop forever accepting requests
+ while true
+ do
+ nc -l $port < $fifo_name | stap-server $((port + 1)) > $fifo_name 2>&1
+ done
+}
+
+# function: fatal [ MESSAGE ]
+#
+# Fatal error
+# Prints its arguments to stderr and exits
+function fatal {
+ echo "$@" >&2
+ exit 1
+}
+
+# function: handle_sigint
+#
+# Terminate gracefully when SIGINT is received.
+function handle_sigint {
+ echo "$0: received SIGINT. Exiting."
+ cd `dirname $tmpdir`
+ rm -fr $tmpdir
+ exit
+}
+
+#-----------------------------------------------------------------------------
+# Beginning of main line execution.
+#-----------------------------------------------------------------------------
+initialization "$@"
+advertise_presence
+listen
diff --git a/tapset/ChangeLog b/tapset/ChangeLog
index 0332a384..b1862324 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,3 +1,7 @@
+2008-07-01 Wenji Huang <wenji.huang@oracle.com>
+
+ * vfs.stp : Make _vfs.generic_commit_write only for kernel<=2.6.25
+
2008-06-26 Zhaolei <zhaolei@cn.fujitsu.com>
* syscalls2.stp: Add sys_renameat.
diff --git a/tapset/vfs.stp b/tapset/vfs.stp
index 78c79051..3c38786a 100644
--- a/tapset/vfs.stp
+++ b/tapset/vfs.stp
@@ -898,6 +898,7 @@ probe _vfs.generic_block_bmap = kernel.function ("generic_block_bmap")
get_block = $get_block
}
+%( kernel_v <= "2.6.25" %?
probe _vfs.generic_commit_write = kernel.function ("generic_commit_write")
{
file = $file
@@ -905,6 +906,7 @@ probe _vfs.generic_commit_write = kernel.function ("generic_commit_write")
from = $from
to = $to
}
+%)
probe _vfs.block_prepare_write = kernel.function ("__block_prepare_write")
{
diff --git a/tapsets.cxx b/tapsets.cxx
index 35428fcd..56838140 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1184,7 +1184,8 @@ struct dwflpp
size_t nsrcs = 0;
dwarf_query * q = static_cast<dwarf_query *>(data);
int lineno = lines[0];
-
+ auto_free_ref<Dwarf_Line**> free_srcsp(srcsp);
+
get_module_dwarf();
if (line_type == RELATIVE)
@@ -1210,7 +1211,6 @@ struct dwflpp
dwarf_getsrc_file (module_dwarf,
srcfile, l, 0,
&srcsp, &nsrcs));
- auto_free srcsp_af(srcsp);
if (line_type == WILDCARD || line_type == RANGE)
{
Dwarf_Addr line_addr;
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index eda51529..9353cc32 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+
+2008-07-01 Wenji Huang <wenji.huang@oracle.com>
+
+ * buildok/vfs_testcase.stp: Test _vfs.generic_commit_write only when
+ kernel<=2.6.25.
+
2008-06-27 David Smith <dsmith@redhat.com>
* systemtap.base/utrace_p4.exp: Added tests for 'process(PID)'
diff --git a/testsuite/buildok/vfs_testcase.stp b/testsuite/buildok/vfs_testcase.stp
index dc78399c..5d8dff25 100644
--- a/testsuite/buildok/vfs_testcase.stp
+++ b/testsuite/buildok/vfs_testcase.stp
@@ -410,6 +410,7 @@ probe _vfs.generic_block_bmap
print("get_block = %p\n", get_block);
}
+%( kernel_v <= "2.6.25" %?
probe _vfs.generic_commit_write
{
print("Probe hit the function: %s\n", probefunc());
@@ -417,6 +418,7 @@ probe _vfs.generic_commit_write
print("page = %p\n", page);
print("from = %u to=%u\n", from, to);
}
+%)
probe _vfs.block_prepare_write
{
diff --git a/testsuite/systemtap.examples/ChangeLog b/testsuite/systemtap.examples/ChangeLog
index b1c34347..dcaafe59 100644
--- a/testsuite/systemtap.examples/ChangeLog
+++ b/testsuite/systemtap.examples/ChangeLog
@@ -1,3 +1,11 @@
+2008-07-02 William Cohen <wcohen@redhat.com>
+
+ * functioncallcount.meta, functioncallcount.stp: New.
+
+2008-07-02 William Cohen <wcohen@redhat.com>
+
+ * para-callgraph.stp, para-callgraph.meta: New.
+
2008-06-20 William Cohen <wcohen@redhat.com>
* traceio2.meta: Correct test_check and test_installcheck commands.
diff --git a/testsuite/systemtap.examples/functioncallcount.meta b/testsuite/systemtap.examples/functioncallcount.meta
new file mode 100644
index 00000000..4d419528
--- /dev/null
+++ b/testsuite/systemtap.examples/functioncallcount.meta
@@ -0,0 +1,13 @@
+title: Count Times Functions Called
+name: functioncallcount.stp
+version: 1.0
+author: anonymous
+keywords: profiling functions
+subsystem: kernel
+status: production
+exit: user-controlled
+output: sorted-list on-exit
+scope: system-wide
+description: The functioncallcount.stp script takes one argument, a list of functions to probe. The script will run and count the number of times that each of the functions on the list is called. On exit the script will print a sorted list from most frequently to least frequently called function.
+test_check: stap -p4 functioncallcount.stp "*@mm/*.c"
+test_installcheck: stap functioncallcount.stp "*@mm/*.c" -c "sleep 1"
diff --git a/testsuite/systemtap.examples/functioncallcount.stp b/testsuite/systemtap.examples/functioncallcount.stp
new file mode 100644
index 00000000..e393b612
--- /dev/null
+++ b/testsuite/systemtap.examples/functioncallcount.stp
@@ -0,0 +1,17 @@
+# The following line command will probe all the functions
+# in kernel's memory management code:
+#
+# stap functioncallcount.stp "*@mm/*.c"
+
+probe kernel.function(@1) { # probe functions listed on commandline
+ called[probefunc()] <<< 1 # add a count efficiently
+}
+
+global called
+
+probe end {
+ foreach (fn in called-) # Sort by call count (in decreasing order)
+ # (fn+ in called) # Sort by function name
+ printf("%s %d\n", fn, @count(called[fn]))
+ exit()
+}
diff --git a/testsuite/systemtap.examples/para-callgraph.meta b/testsuite/systemtap.examples/para-callgraph.meta
new file mode 100644
index 00000000..3ce4b648
--- /dev/null
+++ b/testsuite/systemtap.examples/para-callgraph.meta
@@ -0,0 +1,13 @@
+title: Tracing Calls for Sections of Code
+name: para-callgraph.stp
+version: 1.0
+author: anonymous
+keywords: trace callgraph
+subsystem: kernel
+status: production
+exit: user-controlled
+output: trace
+scope: system-wide
+description: The script takes two arguments: the first argument is the function to starts/stops the per thread call graph traces and the second argument is the list of functions to generate trace information on. The script prints out a timestap for the thread, the function name and pid, followed by entry or exit symboly and function name.
+test_check: stap -p4 para-callgraph.stp sys_read "*@fs/*.c"
+test_installcheck: stap para-callgraph.stp sys_read "*@fs/*.c" -c "sleep 1"
diff --git a/testsuite/systemtap.examples/para-callgraph.stp b/testsuite/systemtap.examples/para-callgraph.stp
new file mode 100644
index 00000000..1afb8837
--- /dev/null
+++ b/testsuite/systemtap.examples/para-callgraph.stp
@@ -0,0 +1,20 @@
+function trace(entry_p) {
+ if(tid() in trace)
+ printf("%s%s%s\n",thread_indent(entry_p),
+ (entry_p>0?"->":"<-"),
+ probefunc())
+}
+
+global trace
+probe kernel.function(@1).call {
+ if (execname() == "stapio") next # skip our own helper process
+ trace[tid()] = 1
+ trace(1)
+}
+probe kernel.function(@1).return {
+ trace(-1)
+ delete trace[tid()]
+}
+
+probe kernel.function(@2).call { trace(1) }
+probe kernel.function(@2).return { trace(-1) }
diff --git a/translate.cxx b/translate.cxx
index d878cfd7..5c25b912 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4651,7 +4651,7 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#include <linux/utsrelease.h>";
s.op->newline() << "#include <linux/utsname.h>";
s.op->newline() << "#include <linux/version.h>";
- s.op->newline() << "#include <linux/compile.h>";
+ // s.op->newline() << "#include <linux/compile.h>";
s.op->newline() << "#include \"loc2c-runtime.h\" ";
// XXX: old 2.6 kernel hack