]> sourceware.org Git - systemtap.git/commitdiff
2005-03-15 Frank Ch. Eigler <fche@redhat.com>
authorfche <fche>
Tue, 15 Mar 2005 22:38:27 +0000 (22:38 +0000)
committerfche <fche>
Tue, 15 Mar 2005 22:38:27 +0000 (22:38 +0000)
* TODO: New file.  Include some probe-point-provider syntax examples.
* parse.cxx (lexer::scan, parser::parse_literal): Support hex, octal
numbers via strtol.
(parse_probe, parse_probe_point): Modify for dotted syntax.
* staptree.cxx: Ditto.
* parsetest.cxx, semtest.cxx: Print parse/sem results even if
.stp files were given on command line.
* parse.h, staptree.h: Rename probe_point_spec -> probe_point.
* runtest.sh: New test-runner front-end script.
* Makefile.am: Use it for TESTS_ENVIRONMENT.
* testsuite/*: Update probe point syntax.  Add a bunch of new tests.

21 files changed:
ChangeLog
Makefile.am
Makefile.in
TODO [new file with mode: 0644]
parse.cxx
parse.h
parsetest.cxx
runtest.sh [new file with mode: 0755]
semtest.cxx
staptree.cxx
staptree.h
testsuite/parseko/five.stp [new file with mode: 0755]
testsuite/parseko/six.stp [new file with mode: 0755]
testsuite/parseok/five.stp [new file with mode: 0755]
testsuite/parseok/four.stp [new file with mode: 0755]
testsuite/parseok/six.stp [new file with mode: 0755]
testsuite/parseok/three.stp
testsuite/parseok/two.stp
testsuite/semko/one.stp
testsuite/semok/four.stp
testsuite/semok/one.stp

index d87b69ddd3e259530510f82d4b41c891c6065f50..6a5c3dc447d18f551933b71931f03a4537cdb42e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2005-03-15  Frank Ch. Eigler  <fche@redhat.com>
+
+       * TODO: New file.  Include some probe-point-provider syntax examples.
+       * parse.cxx (lexer::scan, parser::parse_literal): Support hex, octal
+       numbers via strtol.
+       (parse_probe, parse_probe_point): Modify for dotted syntax.
+       * staptree.cxx: Ditto.
+       * parsetest.cxx, semtest.cxx: Print parse/sem results even if
+       .stp files were given on command line.
+       * parse.h, staptree.h: Rename probe_point_spec -> probe_point.
+       * runtest.sh: New test-runner front-end script.
+       * Makefile.am: Use it for TESTS_ENVIRONMENT.
+       * testsuite/*: Update probe point syntax.  Add a bunch of new tests.
+
 2005-03-04  Frank Ch. Eigler  <fche@redhat.com>
 
        * parse.cxx (scan): Support '$' characters in identifiers.
index 1ba8071a1a2c37bea7dcfee341b46f3f46627088..ff1651c45a257855e74d90d900c9974bedc8a3da 100644 (file)
@@ -25,3 +25,5 @@ s=$(srcdir)/testsuite/sem
 TESTS = $(wildcard $(p)ok/*.stp) $(wildcard $(p)ko/*.stp) \
        $(wildcard $(s)ok/*.stp) $(wildcard $(s)ko/*.stp)
 XFAIL_TESTS = $(wildcard $(p)ko/*.stp) $(wildcard $(s)ko/*.stp)
+
+TESTS_ENVIRONMENT = $(srcdir)/runtest.sh
index c93c775711437ff93932b062a9254cd8b6398b2b..2b995761fa0f8fd50b6e0f395a9e71c69928055f 100644 (file)
@@ -44,7 +44,7 @@ subdir = .
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(srcdir)/config.in \
        $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
-       depcomp install-sh missing
+       TODO depcomp install-sh missing
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -193,6 +193,7 @@ TESTS = $(wildcard $(p)ok/*.stp) $(wildcard $(p)ko/*.stp) \
        $(wildcard $(s)ok/*.stp) $(wildcard $(s)ko/*.stp)
 
 XFAIL_TESTS = $(wildcard $(p)ko/*.stp) $(wildcard $(s)ko/*.stp)
+TESTS_ENVIRONMENT = $(srcdir)/runtest.sh
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-am
 
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..3172908
--- /dev/null
+++ b/TODO
@@ -0,0 +1,27 @@
+LANGUAGE
+ - lock (var) { block }
+ - /* */ and // comments
+
+PROVIDERS
+  lkst("process_contextswitch")
+  syscall("name").return
+  syscall("*")
+  kernel.function("wait_for_godot")
+  kernel.function("name").line(10)
+  kernel.source("mempool.c").line(5004)
+  kernel.address(0xdeadbeef)
+  kernel.module("driver.ko").function("name").return
+  kernel.module("cpqarray.ko").jumptable("ida_fops")
+  kernel.watch("datasymbol").write
+  user("fche").inode("/bin/vi").function("refresh")
+  user.inode("/lib/libc.so.6").function("malloc").return
+  time.real.hz(500)
+  time.virtual.jiffies(100)
+  perfcounter("tlbmiss").count(4000)
+  resource.freemembelow(50) # pages?
+  begin
+  end
+
+KPROBES
+ - smp friendliness: no kprobes-wide lock held during probe execution
+
index 640c37152330e391156df7ca280a25d6731bf78c..91600e2551b97390c1c4c9b49ea9a20ae936db1a 100644 (file)
--- a/parse.cxx
+++ b/parse.cxx
@@ -6,7 +6,10 @@
 #include "staptree.h"
 #include "parse.h"
 #include <cctype>
+#include <cstdlib>
 #include <fstream>
+#include <cerrno>
+#include <climits>
 
 using namespace std;
 
@@ -179,17 +182,22 @@ lexer::scan ()
 
   else if (isdigit (c))
     {
-      // XXX: support 0xHEX etc.
       n->type = tok_number;
-      n->content = c;
+      n->content = (char) c;
+
       while (1)
        {
          int c2 = input.peek ();
          if (! input)
            break;
-         if (isdigit(c2))
+
+          // NB: isalnum is very permissive.  We rely on strtol, called in
+          // parser::parse_literal below, to confirm that the number string
+          // is correctly formatted and in range.
+
+         if (isalnum (c2))
            {
-             n->content.push_back(c2);
+             n->content.push_back (c2);
              input_get ();
            }
          else
@@ -344,10 +352,10 @@ parser::parse_probe ()
       if (t && t->type == tok_identifier)
        {
           p->tok = t;
-         p->location.push_back (parse_probe_point_spec ());
+         p->locations.push_back (parse_probe_point ());
 
          t = peek ();
-         if (t && t->type == tok_operator && t->content == ":")
+         if (t && t->type == tok_operator && t->content == ",")
            {
              next ();
              continue;
@@ -355,11 +363,11 @@ parser::parse_probe ()
          else if (t && t->type == tok_operator && t->content == "{")
            break;
          else
-            throw parse_error ("expected ':' or '{'");
+            throw parse_error ("expected ',' or '{'");
           // XXX: unify logic with that in parse_symbol()
        }
       else
-       throw parse_error ("expected probe location specifier");
+       throw parse_error ("expected probe point specifier");
     }
   
   p->body = parse_stmt_block ();
@@ -524,25 +532,49 @@ parser::parse_functiondecl ()
 }
 
 
-probe_point_spec*
-parser::parse_probe_point_spec ()
+probe_point*
+parser::parse_probe_point ()
 {
-  probe_point_spec* pl = new probe_point_spec;
+  probe_point* pl = new probe_point;
 
-  const token* t = next ();
-  if (t->type != tok_identifier)
-    throw parse_error ("expected identifier");
-  pl->functor = t->content;
-  pl->tok = t;
-
-  t = peek ();
-  if (t && t->type == tok_operator && t->content == "(")
+  while (1)
     {
-      next (); // consume "("
-      pl->arg = parse_literal ();
-      const token* tt = next ();
-      if (! (tt->type == tok_operator && tt->content == ")"))
-       throw parse_error ("expected ')'");
+      const token* t = next ();
+      if (t->type != tok_identifier)
+        throw parse_error ("expected identifier");
+
+      if (pl->tok == 0) pl->tok = t;
+
+      probe_point::component* c = new probe_point::component;
+      c->functor = t->content;
+      pl->components.push_back (c);
+      // NB though we still may add c->arg soon
+
+      t = peek ();
+      if (t && t->type == tok_operator 
+          && (t->content == "{" || t->content == ","))
+        break;
+      
+      if (t && t->type == tok_operator && t->content == "(")
+        {
+          next (); // consume "("
+          c->arg = parse_literal ();
+
+          t = next ();
+          if (! (t->type == tok_operator && t->content == ")"))
+            throw parse_error ("expected ')'");
+
+          t = peek ();
+          if (t && t->type == tok_operator 
+              && (t->content == "{" || t->content == ","))
+            break;
+        }
+      // fall through
+
+      if (t && t->type == tok_operator && t->content == ".")
+        next ();
+      else
+        throw parse_error ("expected '.'");
     }
 
   return pl;
@@ -557,7 +589,20 @@ parser::parse_literal ()
   if (t->type == tok_string)
     l = new literal_string (t->content);
   else if (t->type == tok_number)
-    l = new literal_number (atol (t->content.c_str ()));
+    {
+      const char* startp = t->content.c_str ();
+      char* endp = (char*) startp;
+
+      // NB: we allow controlled overflow from LONG_MIN .. ULONG_MAX
+      errno = 0;
+      long long value = strtoll (startp, & endp, 0);
+      if (errno == ERANGE || errno == EINVAL || *endp != '\0'
+          || value > ULONG_MAX || value < LONG_MIN)
+        throw parse_error ("number invalid or out of range"); 
+
+      long value2 = (long) value;
+      l = new literal_number (value2);
+    }
   else
     throw parse_error ("expected literal string or number");
 
diff --git a/parse.h b/parse.h
index c8008bc7738e0a91f83b7265c48fadef99594fdc..f2510d7e6abcbf7f5444f2cd88a22d8c7271a616 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -82,7 +82,7 @@ private:
 
 private: // nonterminals
   probe* parse_probe ();
-  probe_point_spec* parse_probe_point_spec ();
+  probe_point* parse_probe_point ();
   literal* parse_literal ();
   void parse_global (vector<vardecl*>&);
   functiondecl* parse_functiondecl ();
index ab1d53c8211c8ade250bdace2068cde2b903343e..6293a2f5d155f56dff618209093ed1d6081975df 100644 (file)
@@ -14,20 +14,18 @@ int main (int argc, char *argv [])
 
   if (argc > 1)
     {
-      // quietly parse all listed input files
       for (int i = 1; i < argc; i ++)
         {
           parser p (argv[i]);
           stapfile* f = p.parse ();
           if (f)
-            cout << "file '" << argv[i] << "' parsed ok." << endl;
+            f->print (cout);
           else
             rc = 1;
         }
     }
   else
     {
-      // parse then print just stdin
       parser p (cin);
       stapfile* f = p.parse ();
       if (f)
diff --git a/runtest.sh b/runtest.sh
new file mode 100755 (executable)
index 0000000..c67b66a
--- /dev/null
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+# Redirect stdout/stderr to /dev/null before invoking the given test
+
+exec $@ >/dev/null 2>&1
index f86d17cac1e9330f39ce2931b670325007a4df39..b154209faa05893ffdb01566a120384f05679077 100644 (file)
@@ -133,52 +133,49 @@ main (int argc, char *argv [])
   rc += semantic_pass_1 (files);
   rc += semantic_pass_2 (files);
 
-  if (argc == 1) // processed stdin only
+  for (unsigned i=0; i<files.size(); i++)
     {
-      for (unsigned i=0; i<files.size(); i++)
+      stapfile* f = files[i];
+      for (unsigned j=0; j<f->functions.size(); j++)
         {
-          stapfile* f = files[i];
-          for (unsigned j=0; j<f->functions.size(); j++)
-            {
-              functiondecl* fn = f->functions[j];
-              cerr << "Function ";
-              fn->printsig (cerr);
-              cerr << endl << "locals:" << endl;
-              for (unsigned k=0; k<fn->locals.size(); k++)
-                {
-                  vardecl* fa = fn->locals[k];
-                  cerr << "\t";
-                  fa->printsig (cerr);
-                  cerr << endl;
-                }
-              cerr << endl;
-            }
-
-          for (unsigned j=0; j<f->probes.size(); j++)
+          functiondecl* fn = f->functions[j];
+          cerr << "Function ";
+          fn->printsig (cerr);
+          cerr << endl << "locals:" << endl;
+          for (unsigned k=0; k<fn->locals.size(); k++)
             {
-              probe* pn = f->probes[j];
-              cerr << "Probe " << *pn->tok << endl; // XXX: print probespec
-              cerr << "locals:" << endl;
-              for (unsigned k=0; k<pn->locals.size(); k++)
-                {
-                  vardecl* fa = pn->locals[k];
-                  cerr << "\t";
-                  fa->printsig (cerr);
-                  cerr << endl;
-                }
+              vardecl* fa = fn->locals[k];
+              cerr << "\t";
+              fa->printsig (cerr);
               cerr << endl;
             }
-
-          cerr << "globals:" << endl;
-          for (unsigned k=0; k<f->globals.size(); k++)
+          cerr << endl;
+        }
+      
+      for (unsigned j=0; j<f->probes.size(); j++)
+        {
+          probe* pn = f->probes[j];
+          cerr << "Probe " << *pn->tok << endl; // XXX: print probespec
+          cerr << "locals:" << endl;
+          for (unsigned k=0; k<pn->locals.size(); k++)
             {
-              vardecl* fa = f->globals[k];
+              vardecl* fa = pn->locals[k];
               cerr << "\t";
               fa->printsig (cerr);
               cerr << endl;
             }
           cerr << endl;
         }
+      
+      cerr << "globals:" << endl;
+      for (unsigned k=0; k<f->globals.size(); k++)
+        {
+          vardecl* fa = f->globals[k];
+          cerr << "\t";
+          fa->printsig (cerr);
+          cerr << endl;
+        }
+      cerr << endl;
     }
 
   return rc;
index 2bbdea9fc78664f6c6ee4864307cd49669fef05a..51ac81135ef044029b823e7e095df1b6b321d370 100644 (file)
@@ -61,6 +61,18 @@ symboldecl::~symboldecl ()
 }
 
 
+probe_point::probe_point ():
+  tok (0), prov (0)
+{
+}
+
+
+probe_point::component::component ():
+  arg (0)
+{
+}
+
+
 vardecl::vardecl ()
 {
 }
@@ -301,21 +313,26 @@ void stapfile::print (ostream& o)
 void probe::print (ostream& o)
 {
   o << "probe ";
-  for (unsigned i=0; i<location.size(); i++)
+  for (unsigned i=0; i<locations.size(); i++)
     {
-      o << (i>0 ? ":" : "");
-      location[i]->print (o);
+      o << (i>0 ? "" : "");
+      locations[i]->print (o);
     }
   o << endl;
   o << *body;
 }
 
 
-void probe_point_spec::print (ostream& o)
+void probe_point::print (ostream& o)
 {
-  o << functor;
-  if (arg)
-    o << "(" << *arg << ")";
+  for (unsigned i=0; i<components.size(); i++)
+    {
+      if (i>0) o << ".";
+      probe_point::component* c = components[i];
+      o << c->functor;
+      if (c->arg)
+        o << "(" << *c->arg << ")";
+    }
 }
 
 
index b38221bc13ae67c537a53b1ee8bb128c05ddafb6..cb22969be044c9cd6e50734ec78bed1b83244f9b 100644 (file)
@@ -364,18 +364,26 @@ struct stapfile
 };
 
 
-struct probe_point_spec // inherit from something or other?
-{
-  string functor;
-  const token* tok;
-  literal* arg;
+class provider;
+struct probe_point
+{
+  struct component // XXX: sort of a restricted functioncall
+  { 
+    string functor;
+    literal* arg;
+    component ();
+  };
+  vector<component*> components;
+  const token* tok; // points to first component's functor
+  provider* prov;
   void print (ostream& o);
+  probe_point ();
 };
 
 
 struct probe
 {
-  vector<probe_point_spec*> location;
+  vector<probe_point*> locations;
   const token* tok;
   block* body;
   vector<vardecl*> locals;
diff --git a/testsuite/parseko/five.stp b/testsuite/parseko/five.stp
new file mode 100755 (executable)
index 0000000..1673a1e
--- /dev/null
@@ -0,0 +1,16 @@
+#! semtest
+
+probe foo( {
+}
+
+probe bar() {
+}
+
+probe baz.(1) {
+}
+
+probe faz(2), {
+}
+
+probe kaz,goo. {
+}
diff --git a/testsuite/parseko/six.stp b/testsuite/parseko/six.stp
new file mode 100755 (executable)
index 0000000..2e8c8db
--- /dev/null
@@ -0,0 +1,8 @@
+#! semtest
+
+probe foo {
+  a = -9999999999999999999999999;
+  b = 0xzoopoo;
+  c = 00011122233344455566677788;
+  d = 07777777777777777777777777;
+}
diff --git a/testsuite/parseok/five.stp b/testsuite/parseok/five.stp
new file mode 100755 (executable)
index 0000000..a475807
--- /dev/null
@@ -0,0 +1,19 @@
+#! parsetest
+
+probe lkst("process_contextswitch") {}
+probe syscall("name").return {}
+probe syscall("*") {}
+probe kernel.function("wait_for_godot") {}
+probe kernel.function("name").line(10) {}
+probe kernel.source("mempool.c").line(5004) {}
+probe kernel.address(0xdeadbeef) {}
+probe kernel.module("driver.ko").function("name").return {}
+probe kernel.module("cpqarray.ko").jumptable("ida_fops") {}
+probe kernel.watch("datasymbol").write {}
+probe user("fche").inode("/bin/vi").function("refresh") {}
+probe user.inode("/lib/libc.so.6").function("malloc").return {}
+probe time.real.hz(500) {}
+probe time.virtual.jiffies(100) {}
+probe perfcounter("tlbmiss").count(4000) {}
+probe resource.freemembelow(50) {} # pages?
+probe begin {}
diff --git a/testsuite/parseok/four.stp b/testsuite/parseok/four.stp
new file mode 100755 (executable)
index 0000000..d381b24
--- /dev/null
@@ -0,0 +1,7 @@
+#! parsetest
+
+probe syscall ("foo").foo.bar , syscall ("bar"), syscall ("*").return
+{
+  $a = a$a = a$a$ = 0;
+}
+
diff --git a/testsuite/parseok/six.stp b/testsuite/parseok/six.stp
new file mode 100755 (executable)
index 0000000..6fb9b76
--- /dev/null
@@ -0,0 +1,8 @@
+#! parsetest
+
+probe one
+{
+  a = 1+01+0x1-1-01-0x1;
+  b = 2147483647;
+  c = -2147483647-1;
+}
index b2628d4d032ea44bd7d5f6b4975d95c2b4abffe0..d2401877d7e137766069a88e7237952bc2e0a665 100755 (executable)
@@ -1,6 +1,6 @@
 #! parsetest
 
-probe kernel:systemcall("foo") 
+probe syscall ("foo")
 {
   $a = a$a = a$a$ = 0;
 }
index 6ab3823e4a66060a11206faf5cf11327204e8585..b6b843de57a35ad989baf5d3a88ce4805cde8853 100755 (executable)
@@ -1,6 +1,6 @@
 #! parsetest
 
-probe kernel:systemcall("foo") 
+probe syscall (231)
 {
   array[idx] << value;
   if (global > 5) { global -- } else ;
@@ -11,7 +11,7 @@ function foo () {
   return 0;
 }
 
-probe systemtap:end
+probe end
 {
   foo ("value", 4+8);
 }
index 994bb451920c38fe34fe05f1649ce4f6fc49b2a5..7519dfc6a9764a920b15fccd2f9f2a3b97f72b3f 100755 (executable)
@@ -5,4 +5,4 @@ function stamp (syscall)
   # no return expression => unknown function type
 }
 
-probe kernel:syscall:read { stamp ("read"); }
+probe syscall (read) { stamp ("read"); }
index e11b644ae102abbc8ecbffce5043da0677e19448..c3b2a7d0ddb8f87cfe993b6c7c96e65ddb226d6f 100755 (executable)
@@ -17,7 +17,7 @@ function stamp (syscall)
 # probe kernel:syscall:read = kernel:function("sys_read");
 
 
-probe kernel:syscall:read
+probe syscall ("read")
 { 
   stamp ("read");
 }
index fb7483e2053f02daf4c2b27bbea9195c3b0aee22..336e57d28247c592e3d4167304fd6b1cb580275e 100755 (executable)
@@ -19,7 +19,7 @@ function stamp (syscall)
 # probe kernel:syscall:read = kernel:function("sys_read");
 
 
-probe kernel:syscall:read
+probe syscall ("read")
 { 
   stamp ("read");
 }
This page took 0.05826 seconds and 5 git commands to generate.