From 5c5099faf99e24038eda90d91d0efa59d482e440 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 27 Jul 2009 21:48:53 +0200 Subject: Mention where we looked and if we didn't find line info on statement probe. * tapsets.cxx (query_cu): When statement check fails and no line info available, mention the CU had no line info. --- tapsets.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tapsets.cxx b/tapsets.cxx index 752a9ddf..9186ba82 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1405,6 +1405,9 @@ query_cu (Dwarf_Die * cudie, void * arg) << " does not match the beginning of a statement"; if (address_line) msg << " (try 0x" << hex << lineaddr << ")"; + else + msg << " (no line info found for '" << q->dw.cu_name + << "', in module '" << q->dw.module_name << "')"; if (! q->sess.guru_mode) throw semantic_error(msg.str()); else if (! q->sess.suppress_warnings) -- cgit From 1123a74ab28d4ae9f2db0d704ce3981064ed9591 Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Mon, 27 Jul 2009 15:52:28 -0400 Subject: PR6905: tweak WILDCARD and RANGE line type for process.statement * dwflpp.cxx (iterate_over_srcfile_lines): Check the line range and tolerate invalid line number for WILDCARD line type. * testsuite/systemtap.base/bz6905.c: Test case. * testsuite/systemtap.base/bz6905.exp: Ditto. * testsuite/systemtap.base/bz6905.stp: Ditto. --- dwflpp.cxx | 32 ++++++++++++++++++++++++++++---- testsuite/systemtap.base/bz6905.c | 7 +++++++ testsuite/systemtap.base/bz6905.exp | 25 +++++++++++++++++++++++++ testsuite/systemtap.base/bz6905.stp | 4 ++++ 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 testsuite/systemtap.base/bz6905.c create mode 100644 testsuite/systemtap.base/bz6905.exp create mode 100644 testsuite/systemtap.base/bz6905.stp diff --git a/dwflpp.cxx b/dwflpp.cxx index ce9993c8..01cfddaa 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -808,19 +808,43 @@ dwflpp::iterate_over_srcfile_lines (char const * srcfile, } else if (line_type == WILDCARD) function_line (&lineno); + else if (line_type == RANGE) { /* correct lineno */ + int start_lineno; + + function_line (&start_lineno); + lineno = lineno < start_lineno ? start_lineno : lineno; + if (lineno > lines[1]) { /* invalid line range */ + stringstream advice; + advice << "Invalid line range (" << lines[0] << "-" << lines[1] << ")"; + if (start_lineno > lines[1]) + advice << ", the end line number " << lines[1] << " < " << start_lineno; + throw semantic_error (advice.str()); + } + } + for (int l = lineno; ; l = l + 1) { set lines_probed; pair::iterator,bool> line_probed; - dwarf_assert ("dwarf_getsrc_file", - dwarf_getsrc_file (module_dwarf, - srcfile, l, 0, - &srcsp, &nsrcs)); + int ret = 0; + + ret = dwarf_getsrc_file (module_dwarf, srcfile, l, 0, + &srcsp, &nsrcs); + if (line_type != WILDCARD && line_type != RANGE) + dwarf_assert ("dwarf_getsrc_file", ret); + if (line_type == WILDCARD || line_type == RANGE) { Dwarf_Addr line_addr; + + if (ret != 0) /* tolerate invalid line number */ + break; + dwarf_lineno (srcsp [0], &lineno); + /* Maybe lineno will exceed the input end */ + if (line_type == RANGE && lineno > lines[1]) + break; line_probed = lines_probed.insert(lineno); if (lineno != l || line_probed.second == false || nsrcs > 1) continue; diff --git a/testsuite/systemtap.base/bz6905.c b/testsuite/systemtap.base/bz6905.c new file mode 100644 index 00000000..bb3f524e --- /dev/null +++ b/testsuite/systemtap.base/bz6905.c @@ -0,0 +1,7 @@ +int main() +{ + int a; + + a = a + 1; + return 0; +} diff --git a/testsuite/systemtap.base/bz6905.exp b/testsuite/systemtap.base/bz6905.exp new file mode 100644 index 00000000..8119159e --- /dev/null +++ b/testsuite/systemtap.base/bz6905.exp @@ -0,0 +1,25 @@ +set test bz6905 + +catch {exec gcc -g -o $test $srcdir/$subdir/$test.c} err +if {$err == "" && [file exists $test]} then { pass "$test compile" } else { fail "$test compile" } + +if {![utrace_p]} { + catch {exec rm -f $test} + untested "$test -p2" + return +} + +set stapexe [exec /usr/bin/which stap] +spawn sudo $stapexe -p2 $srcdir/$subdir/$test.stp +set hint 0 +set probes 0 +expect { + -timeout 60 + -re "# probes" { incr hint; exp_continue } + -re {process.*statement.*} { incr probes; exp_continue } + timeout { fail "$test (timeout)" } + eof { } +} +wait +if { $hint == 1 && $probes > 0 } then { pass "$test -p2" } else { fail "$test -p2 ($probes)" } +exec rm -f $test diff --git a/testsuite/systemtap.base/bz6905.stp b/testsuite/systemtap.base/bz6905.stp new file mode 100644 index 00000000..73c7d50c --- /dev/null +++ b/testsuite/systemtap.base/bz6905.stp @@ -0,0 +1,4 @@ +#! stap -p2 +probe process("./bz6905").statement("main@bz6905.c:*") { + printf("ok") +} -- cgit From 89fc05fd9c7c04de6568b9ef31e1feb9c092da95 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 22 Apr 2009 09:12:27 +0200 Subject: restore newlines to grapher script header * testsuite/systemtap.examples/general/grapher.stp: Restore newlines. --- testsuite/systemtap.examples/general/grapher.stp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) mode change 100755 => 100644 testsuite/systemtap.examples/general/grapher.stp diff --git a/testsuite/systemtap.examples/general/grapher.stp b/testsuite/systemtap.examples/general/grapher.stp old mode 100755 new mode 100644 index 4f326ec1..5d9b4bb5 --- a/testsuite/systemtap.examples/general/grapher.stp +++ b/testsuite/systemtap.examples/general/grapher.stp @@ -3,10 +3,10 @@ probe begin { printf ("%%Title:CPU utilization\n"); -printf ("%%XAxisTitle:Time"); -printf ("%%YAxisTitle:Percent"); -printf ("%%DataSet:cpu 100 00ff00 bar"); -printf ("%%DataSet:kbd 100 ff0000 dot"); +printf ("%%XAxisTitle:Time\n"); +printf ("%%YAxisTitle:Percent\n"); +printf ("%%DataSet:cpu 100 00ff00 bar\n"); +printf ("%%DataSet:kbd 100 ff0000 dot\n"); } # CPU utilization -- cgit From d982d13c99f7c4119a9ceea1749a54cca7e53d38 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 22 Apr 2009 10:20:20 +0200 Subject: Tweaks to grapher axis drawing * grapher/GraphWidget.cxx (on_expose_event): Don't draw axis labels that would overlap others. --- grapher/GraphWidget.cxx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx index 38f8078d..34b4daf4 100644 --- a/grapher/GraphWidget.cxx +++ b/grapher/GraphWidget.cxx @@ -210,7 +210,7 @@ namespace systemtap // Draw axes double diff = _right - _left; double majorUnit = pow(10.0, floor(log(diff) / log(10.0))); - double startTime = floor(_left / majorUnit) * majorUnit; + double startTime = ceil(_left / majorUnit) * majorUnit; cr->save(); cr->set_source_rgba(1.0, 1.0, 1.0, .9); cr->set_line_cap(Cairo::LINE_CAP_BUTT); @@ -226,15 +226,23 @@ namespace systemtap std::valarray dash(1); dash[0] = height / 10; cr->set_dash(dash, 0.0); - for (double tickVal = startTime; tickVal < _right; tickVal += majorUnit) + double prevTextAdvance = 0; + for (double tickVal = startTime; tickVal <= _right; tickVal += majorUnit) { - cr->move_to((tickVal - _left) * horizScale + 20.0, graphHeight - 5); + double x = (tickVal - _left) * horizScale + 20.0; + cr->move_to(x, 0.0); + cr->line_to(x, height); + cr->move_to(x, graphHeight - 5); std::ostringstream stream; stream << std::fixed << std::setprecision(0) << tickVal; - cr->show_text(stream.str()); - cr->move_to((tickVal - _left) * horizScale + 20.0, 0.0); - cr->line_to((tickVal - _left) * horizScale + 20.0, height); - cr->stroke(); + Cairo::TextExtents extents; + cr->get_text_extents(stream.str(), extents); + // Room for this label? + if (x + extents.x_bearing > prevTextAdvance) + { + cr->show_text(stream.str()); + prevTextAdvance = x + extents.x_advance; + } } cr->stroke(); cr->restore(); -- cgit From 3c434960a680c459d526bee483a2bc79ce767473 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 29 Apr 2009 19:52:50 +0200 Subject: Refactor StapParser into its own files * grapher/StapParser.cxx: new file * grapher/StapParser.hxx: new file * grapher/grapher.cxx: Use external StapParser class. --- grapher/Makefile.am | 2 +- grapher/Makefile.in | 21 ++++++++++-- grapher/StapParser.cxx | 81 ++++++++++++++++++++++++++++++++++++++++++++++ grapher/StapParser.hxx | 21 ++++++++++++ grapher/grapher.cxx | 88 +------------------------------------------------- 5 files changed, 123 insertions(+), 90 deletions(-) create mode 100644 grapher/StapParser.cxx create mode 100644 grapher/StapParser.hxx diff --git a/grapher/Makefile.am b/grapher/Makefile.am index fdb52ef7..bd651352 100644 --- a/grapher/Makefile.am +++ b/grapher/Makefile.am @@ -2,6 +2,6 @@ if BUILD_GRAPHER bin_PROGRAMS = grapher grapher_CXXFLAGS = $(GRAPHER_CFLAGS) -grapher_SOURCES = grapher.cxx GraphWidget.cxx CairoWidget.cxx +grapher_SOURCES = grapher.cxx StapParser.cxx GraphWidget.cxx CairoWidget.cxx grapher_LDADD = $(GRAPHER_LIBS) endif \ No newline at end of file diff --git a/grapher/Makefile.in b/grapher/Makefile.in index 88caeda1..3e65401e 100644 --- a/grapher/Makefile.in +++ b/grapher/Makefile.in @@ -43,8 +43,10 @@ CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) -am__grapher_SOURCES_DIST = grapher.cxx GraphWidget.cxx CairoWidget.cxx +am__grapher_SOURCES_DIST = grapher.cxx StapParser.cxx GraphWidget.cxx \ + CairoWidget.cxx @BUILD_GRAPHER_TRUE@am_grapher_OBJECTS = grapher-grapher.$(OBJEXT) \ +@BUILD_GRAPHER_TRUE@ grapher-StapParser.$(OBJEXT) \ @BUILD_GRAPHER_TRUE@ grapher-GraphWidget.$(OBJEXT) \ @BUILD_GRAPHER_TRUE@ grapher-CairoWidget.$(OBJEXT) grapher_OBJECTS = $(am_grapher_OBJECTS) @@ -184,7 +186,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @BUILD_GRAPHER_TRUE@grapher_CXXFLAGS = $(GRAPHER_CFLAGS) -@BUILD_GRAPHER_TRUE@grapher_SOURCES = grapher.cxx GraphWidget.cxx CairoWidget.cxx +@BUILD_GRAPHER_TRUE@grapher_SOURCES = grapher.cxx StapParser.cxx GraphWidget.cxx CairoWidget.cxx @BUILD_GRAPHER_TRUE@grapher_LDADD = $(GRAPHER_LIBS) all: all-am @@ -254,6 +256,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-CairoWidget.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-GraphWidget.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-StapParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-grapher.Po@am__quote@ .cxx.o: @@ -284,6 +287,20 @@ grapher-grapher.obj: grapher.cxx @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-grapher.obj `if test -f 'grapher.cxx'; then $(CYGPATH_W) 'grapher.cxx'; else $(CYGPATH_W) '$(srcdir)/grapher.cxx'; fi` +grapher-StapParser.o: StapParser.cxx +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-StapParser.o -MD -MP -MF $(DEPDIR)/grapher-StapParser.Tpo -c -o grapher-StapParser.o `test -f 'StapParser.cxx' || echo '$(srcdir)/'`StapParser.cxx +@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='StapParser.cxx' object='grapher-StapParser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-StapParser.o `test -f 'StapParser.cxx' || echo '$(srcdir)/'`StapParser.cxx + +grapher-StapParser.obj: StapParser.cxx +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-StapParser.obj -MD -MP -MF $(DEPDIR)/grapher-StapParser.Tpo -c -o grapher-StapParser.obj `if test -f 'StapParser.cxx'; then $(CYGPATH_W) 'StapParser.cxx'; else $(CYGPATH_W) '$(srcdir)/StapParser.cxx'; fi` +@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='StapParser.cxx' object='grapher-StapParser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-StapParser.obj `if test -f 'StapParser.cxx'; then $(CYGPATH_W) 'StapParser.cxx'; else $(CYGPATH_W) '$(srcdir)/StapParser.cxx'; fi` + grapher-GraphWidget.o: GraphWidget.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-GraphWidget.o -MD -MP -MF $(DEPDIR)/grapher-GraphWidget.Tpo -c -o grapher-GraphWidget.o `test -f 'GraphWidget.cxx' || echo '$(srcdir)/'`GraphWidget.cxx @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx new file mode 100644 index 00000000..2bf26324 --- /dev/null +++ b/grapher/StapParser.cxx @@ -0,0 +1,81 @@ +#include "StapParser.hxx" + +#include + +namespace systemtap +{ +bool StapParser::ioCallback(Glib::IOCondition ioCondition) +{ + if ((ioCondition & Glib::IO_IN) == 0) + return true; + char buf[256]; + ssize_t bytes_read = 0; + bytes_read = read(0, buf, sizeof(buf) - 1); + if (bytes_read <= 0) + { + _win.hide(); + return true; + } + buf[bytes_read] = '\0'; + _buffer += buf; + std::string::size_type ret = std::string::npos; + while ((ret = _buffer.find('\n')) != std::string::npos) + { + Glib::ustring dataString(_buffer, 0, ret); + if (dataString[0] == '%') + { + size_t found; + if ((found = dataString.find("%Title:") == 0)) + { + std::string title = dataString.substr(7); + _widget.setTitle(title); + } + else if ((found = dataString.find("%XAxisTitle:") == 0)) + { + _widget.setXAxisText(dataString.substr(12)); + } + else if ((found = dataString.find("%YAxisTitle:") == 0)) + { + _widget.setYAxisText(dataString.substr(12)); + } + else if ((found = dataString.find("%YMax:") == 0)) + { + double ymax; + std::istringstream stream(dataString.substr(6)); + stream >> ymax; + // _gdata->scale = ymax; + } + else if ((found = dataString.find("%DataSet:") == 0)) + { + std::tr1::shared_ptr dataSet(new GraphData); + std::string setName; + int hexColor; + std::string style; + std::istringstream stream(dataString.substr(9)); + stream >> setName >> dataSet->scale >> std::hex >> hexColor + >> style; + dataSet->color[0] = (hexColor >> 16) / 255.0; + dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; + dataSet->color[2] = (hexColor & 0xff) / 255.0; + if (style == "dot") + dataSet->style = GraphData::DOT; + _dataSets.insert(std::make_pair(setName, dataSet)); + _widget.addGraphData(dataSet); + } + } + else + { + std::string dataSet; + double time; + double data; + std::istringstream stream(dataString); + stream >> dataSet >> time >> data; + DataMap::iterator itr = _dataSets.find(dataSet); + if (itr != _dataSets.end()) + itr->second->data.push_back(std::make_pair(time, data)); + } + _buffer.erase(0, ret + 1); + } + return true; +} +} diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx new file mode 100644 index 00000000..a94b0a9b --- /dev/null +++ b/grapher/StapParser.hxx @@ -0,0 +1,21 @@ +#include "GraphData.hxx" +#include "GraphWidget.hxx" + +#include +namespace systemtap +{ +class StapParser +{ + std::string _buffer; + typedef std::map > DataMap; + DataMap _dataSets; + Gtk::Window& _win; + GraphWidget& _widget; +public: + StapParser(Gtk::Window& win, + GraphWidget& widget) : _win(win), _widget(widget) {} + + bool ioCallback(Glib::IOCondition ioCondition); + +}; +} diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx index 46182178..4f9ccae8 100644 --- a/grapher/grapher.cxx +++ b/grapher/grapher.cxx @@ -1,4 +1,5 @@ #include "GraphWidget.hxx" +#include "StapParser.hxx" #include #include @@ -12,93 +13,6 @@ using namespace systemtap; -class StapParser -{ - Glib::ustring _buffer; - typedef std::map > DataMap; - DataMap _dataSets; - Gtk::Window& _win; - GraphWidget& _widget; -public: - StapParser(Gtk::Window& win, - GraphWidget& widget) : _win(win), _widget(widget) {} - - bool ioCallback(Glib::IOCondition ioCondition) - { - if ((ioCondition & Glib::IO_IN) == 0) - return true; - char buf[256]; - ssize_t bytes_read = 0; - bytes_read = read(0, buf, sizeof(buf) - 1); - if (bytes_read <= 0) - { - _win.hide(); - return true; - } - buf[bytes_read] = '\0'; - _buffer += buf; - Glib::ustring::size_type ret = Glib::ustring::npos; - while ((ret = _buffer.find('\n')) != Glib::ustring::npos) - { - Glib::ustring dataString(_buffer, 0, ret); - if (dataString[0] == '%') - { - size_t found; - if ((found = dataString.find("%Title:") == 0)) - { - std::string title = dataString.substr(7); - _widget.setTitle(title); - } - else if ((found = dataString.find("%XAxisTitle:") == 0)) - { - _widget.setXAxisText(dataString.substr(12)); - } - else if ((found = dataString.find("%YAxisTitle:") == 0)) - { - _widget.setYAxisText(dataString.substr(12)); - } - else if ((found = dataString.find("%YMax:") == 0)) - { - double ymax; - std::istringstream stream(dataString.substr(6)); - stream >> ymax; - // _gdata->scale = ymax; - } - else if ((found = dataString.find("%DataSet:") == 0)) - { - std::tr1::shared_ptr dataSet(new GraphData); - std::string setName; - int hexColor; - std::string style; - std::istringstream stream(dataString.substr(9)); - stream >> setName >> dataSet->scale >> std::hex >> hexColor - >> style; - dataSet->color[0] = (hexColor >> 16) / 255.0; - dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; - dataSet->color[2] = (hexColor & 0xff) / 255.0; - if (style == "dot") - dataSet->style = GraphData::DOT; - _dataSets.insert(std::make_pair(setName, dataSet)); - _widget.addGraphData(dataSet); - } - } - else - { - std::string dataSet; - double time; - double data; - std::istringstream stream(dataString); - stream >> dataSet >> time >> data; - DataMap::iterator itr = _dataSets.find(dataSet); - if (itr != _dataSets.end()) - itr->second->data.push_back(std::make_pair(time, data)); - } - _buffer.erase(0, ret + 1); - } - return true; - } -}; - int main(int argc, char** argv) { Gtk::Main app(argc, argv); -- cgit From 0f262fd10d337db0ec435d840b541d629879ce9f Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 20 May 2009 13:29:54 +0200 Subject: Add CSV syntax support to the grapher * grapher/GraphData.hxx (CSVData): new class * grapher/GraphData.cxx (commaSplit): new function (ioCallback): handle CSV definition and data --- grapher/GraphData.hxx | 7 +++++ grapher/StapParser.cxx | 80 +++++++++++++++++++++++++++++++++++++++++++------- grapher/StapParser.hxx | 1 + 3 files changed, 78 insertions(+), 10 deletions(-) diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx index 0f3b0b31..2c0783c6 100644 --- a/grapher/GraphData.hxx +++ b/grapher/GraphData.hxx @@ -3,6 +3,7 @@ #include #include +#include namespace systemtap { @@ -40,5 +41,11 @@ namespace systemtap } }; }; + + struct CSVData + { + typedef std::pair > Element; + std::vector elements; + }; } #endif diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx index 2bf26324..c973b0aa 100644 --- a/grapher/StapParser.cxx +++ b/grapher/StapParser.cxx @@ -4,8 +4,32 @@ namespace systemtap { +using namespace std; + +vector commaSplit(const string& inStr, size_t pos = 0) +{ + size_t found = pos; + vector result; + while (1) + { + + size_t commaPos = inStr.find(',', found); + string token + = inStr.substr(found, (commaPos == string::npos + ? string::npos + : commaPos - 1 - found)); + result.push_back(token); + if (commaPos != string::npos) + found = commaPos + 1; + else + break; + } + return result; +} + bool StapParser::ioCallback(Glib::IOCondition ioCondition) { + using namespace std; if ((ioCondition & Glib::IO_IN) == 0) return true; char buf[256]; @@ -18,8 +42,8 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition) } buf[bytes_read] = '\0'; _buffer += buf; - std::string::size_type ret = std::string::npos; - while ((ret = _buffer.find('\n')) != std::string::npos) + string::size_type ret = string::npos; + while ((ret = _buffer.find('\n')) != string::npos) { Glib::ustring dataString(_buffer, 0, ret); if (dataString[0] == '%') @@ -62,17 +86,53 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition) _dataSets.insert(std::make_pair(setName, dataSet)); _widget.addGraphData(dataSet); } + else if ((found = dataString.find("%CSV:") == 0)) + { + vector tokens = commaSplit(dataString, found + 5); + for (vector::iterator tokIter = tokens.begin(), + e = tokens.end(); + tokIter != e; + ++tokIter) + { + DataMap::iterator setIter = _dataSets.find(*tokIter); + if (setIter != _dataSets.end()) + _csv.elements.push_back(CSVData::Element(*tokIter, + setIter->second)); + } + } } else { - std::string dataSet; - double time; - double data; - std::istringstream stream(dataString); - stream >> dataSet >> time >> data; - DataMap::iterator itr = _dataSets.find(dataSet); - if (itr != _dataSets.end()) - itr->second->data.push_back(std::make_pair(time, data)); + if (!_csv.elements.empty()) + { + vector tokens = commaSplit(dataString); + int i = 0; + double time; + vector::iterator tokIter = tokens.begin(); + std::istringstream timeStream(*tokIter++); + timeStream >> time; + for (vector::iterator e = tokens.end(); + tokIter != e; + ++tokIter, ++i) + { + std::istringstream stream(*tokIter); + double data; + stream >> data; + _csv.elements[i].second + ->data.push_back(std::make_pair(time, data)); + } + } + else + { + std::string dataSet; + double time; + double data; + std::istringstream stream(dataString); + stream >> dataSet >> time >> data; + DataMap::iterator itr = _dataSets.find(dataSet); + if (itr != _dataSets.end()) + itr->second->data.push_back(std::make_pair(time, data)); + } } _buffer.erase(0, ret + 1); } diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx index a94b0a9b..624accc7 100644 --- a/grapher/StapParser.hxx +++ b/grapher/StapParser.hxx @@ -9,6 +9,7 @@ class StapParser std::string _buffer; typedef std::map > DataMap; DataMap _dataSets; + CSVData _csv; Gtk::Window& _win; GraphWidget& _widget; public: -- cgit From f7cfc39c07d0cf872559f9716643491b8d79de75 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Mon, 25 May 2009 18:12:41 +0200 Subject: Incorporate grapher widget in real application * grapher/grapher.cxx (GrapherWindow): New class. (main): Instantiate GrapherWindow. --- grapher/grapher.cxx | 89 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx index 4f9ccae8..b7292cfd 100644 --- a/grapher/grapher.cxx +++ b/grapher/grapher.cxx @@ -1,40 +1,107 @@ #include "GraphWidget.hxx" #include "StapParser.hxx" +#include #include +#include +#include #include #include #include +#include +#include #include #include #include #include +#include +#include +#include using namespace systemtap; +class GrapherWindow : public Gtk::Window +{ +public: + GrapherWindow(); + virtual ~GrapherWindow() {} + Gtk::VBox m_Box; + GraphWidget w; +protected: + virtual void on_menu_file_quit(); + // menu support + Glib::RefPtr m_refUIManager; + Glib::RefPtr m_refActionGroup; + +}; + +GrapherWindow::GrapherWindow() +{ + set_title("systemtap grapher"); + add(m_Box); + w.setExtents(0.0, 1.0, 5.0, 0.0); + w.setLineWidth(2); + + + + //Create actions for menus and toolbars: + m_refActionGroup = Gtk::ActionGroup::create(); + //File menu: + m_refActionGroup->add(Gtk::Action::create("FileMenu", "File")); + m_refActionGroup->add(Gtk::Action::create("FileQuit", Gtk::Stock::QUIT), + sigc::mem_fun(*this, &GrapherWindow::on_menu_file_quit)); + m_refUIManager = Gtk::UIManager::create(); + m_refUIManager->insert_action_group(m_refActionGroup); + + add_accel_group(m_refUIManager->get_accel_group()); + //Layout the actions in a menubar and toolbar: + Glib::ustring ui_info = + "" + " " + " " + " " + " " + " " + ""; + try + { + m_refUIManager->add_ui_from_string(ui_info); + } + catch(const Glib::Error& ex) + { + std::cerr << "building menus failed: " << ex.what(); + } + Gtk::Widget* pMenubar = m_refUIManager->get_widget("/MenuBar"); + if(pMenubar) + m_Box.pack_start(*pMenubar, Gtk::PACK_SHRINK); + m_Box.pack_start(w, Gtk::PACK_EXPAND_WIDGET); + w.show(); + + show_all_children(); + +} +void GrapherWindow::on_menu_file_quit() +{ + hide(); +} + int main(int argc, char** argv) { - Gtk::Main app(argc, argv); + Gtk::Main app(argc, argv); - Gtk::Window win; + GrapherWindow win; - win.set_title("Grapher"); - win.set_default_size(600, 200); + win.set_title("Grapher"); + win.set_default_size(600, 200); - GraphWidget w; - - w.setExtents(0.0, 1.0, 5.0, 0.0); - w.setLineWidth(2); + StapParser stapParser(win, win.w); StapParser stapParser(win, w); Glib::signal_io().connect(sigc::mem_fun(stapParser, &StapParser::ioCallback), 0, Glib::IO_IN); - win.add(w); - w.show(); - Gtk::Main::run(win); return 0; -- cgit From 95ddfc079a1d9affdb285f7690f8d5623cd7124a Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Mon, 25 May 2009 18:25:47 +0200 Subject: run stap from grapher * grapher/grapher.cxx (main): Start stap + script from program if supplied as an argument. --- grapher/grapher.cxx | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx index b7292cfd..0013d8b0 100644 --- a/grapher/grapher.cxx +++ b/grapher/grapher.cxx @@ -97,12 +97,42 @@ int main(int argc, char** argv) StapParser stapParser(win, win.w); - StapParser stapParser(win, w); + int childPid = -1; + if (argc > 1) + { + int pipefd[2]; + if (pipe(pipefd) < 0) + { + std::perror("pipe"); + exit(1); + } + if ((childPid = fork()) == -1) + { + exit(1); + } + else if (childPid) + { + dup2(pipefd[0], 0); + close(pipefd[0]); + } + else + { + dup2(pipefd[1], 1); + close(pipefd[1]); + execlp("stap", argv[1]); + exit(1); + return 1; + } + } Glib::signal_io().connect(sigc::mem_fun(stapParser, &StapParser::ioCallback), 0, Glib::IO_IN); Gtk::Main::run(win); - + if (childPid > 0) + kill(childPid, SIGTERM); + int status; + while (wait(&status) != -1) + ; return 0; } -- cgit From 5f4f8b1129659adb2015ce42821faccf8fe6d8d5 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 27 May 2009 10:32:51 +0200 Subject: Templatize GraphData * grapher/GraphData.hxx (GraphDataBase): new superclass for GraphData. Split time data out as a separate vector. (GraphData): Rewrite as template. * grapher/GraphWidget.cxx (on_expose_event): Reflect GraphData templatization. Handle events with string values. * grapher/GraphWidget.hxx (GraphWidget): Keep pointers to GraphDataBase objects instead of GraphData. * grapher/StapParser.cxx (parseData): new member function (ioCallback): Handle new discreet event * grapher/StapParser.hxx (StapParser): keep pointers to GraphDataBase objects instead of GraphData * testsuite/systemtap.examples/general/grapher.stp: Display actual key pressed for keyboard event --- grapher/GraphData.hxx | 40 +++++------ grapher/GraphWidget.cxx | 85 +++++++++++++++++------- grapher/GraphWidget.hxx | 4 +- grapher/StapParser.cxx | 77 ++++++++++++++++----- grapher/StapParser.hxx | 5 +- testsuite/systemtap.examples/general/grapher.stp | 5 +- 6 files changed, 146 insertions(+), 70 deletions(-) diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx index 2c0783c6..9bf3b624 100644 --- a/grapher/GraphData.hxx +++ b/grapher/GraphData.hxx @@ -7,44 +7,38 @@ namespace systemtap { - struct GraphData + struct GraphDataBase { - public: + virtual ~GraphDataBase() {} enum Style { BAR, - DOT + DOT, + EVENT }; - GraphData() : scale(1.0), style(BAR) + GraphDataBase() : scale(1.0), style(BAR) { color[0] = 0.0; color[1] = 1.0; color[2] = 0.0; } - typedef std::pair Datum; - typedef std::vector List; + typedef std::vector TimeList; // size of grid square at "normal" viewing double scale; double color[3]; Style style; - List data; - struct Compare - { - bool operator() (const Datum& lhs, const Datum& rhs) const - { - return lhs.first < rhs.first; - } - bool operator() (double lhs, const Datum& rhs) const - { - return lhs < rhs.first; - } - bool operator() (const Datum& lhs, double rhs) const - { - return lhs.first < rhs; - } - }; + TimeList times; }; + template + class GraphData : public GraphDataBase + { + public: + typedef T data_type; + typedef std::vector DataList; + DataList data; + }; struct CSVData { - typedef std::pair > Element; + typedef std::pair > + Element; std::vector elements; }; } diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx index 34b4daf4..d62ec4f3 100644 --- a/grapher/GraphWidget.cxx +++ b/grapher/GraphWidget.cxx @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include "GraphWidget.hxx" @@ -9,6 +10,8 @@ namespace systemtap { + using std::string; + GraphWidget::GraphWidget() : _left(0.0), _right(1.0), _top(1.0), _bottom(0.0), _lineWidth(10), _autoScaling(true), _autoScrolling(true), _zoomFactor(1.0), @@ -55,7 +58,7 @@ namespace systemtap { } - void GraphWidget::addGraphData(std::tr1::shared_ptr data) + void GraphWidget::addGraphData(std::tr1::shared_ptr data) { _datasets.push_back(data); } @@ -94,9 +97,9 @@ namespace systemtap ditr != de; ++ditr) { - if (!(*ditr)->data.empty()) + if (!(*ditr)->times.empty()) { - double lastDataTime = (*ditr)->data.back().first; + double lastDataTime = (*ditr)->times.back(); if (lastDataTime > latestTime) latestTime = lastDataTime; } @@ -108,16 +111,16 @@ namespace systemtap ditr != de; ++ditr) { - GraphData::List& gdata = (*ditr)->data; - if (gdata.size() <= 1) + GraphDataBase::TimeList& gtimes = (*ditr)->times; + if (gtimes.size() <= 1) continue; double totalDiff = 0.0; - for (GraphData::List::reverse_iterator ritr = gdata.rbegin(), - re = gdata.rend(); - ritr + 1 != gdata.rend(); + for (GraphDataBase::TimeList::reverse_iterator ritr = gtimes.rbegin(), + re = gtimes.rend(); + ritr + 1 != gtimes.rend(); ritr++) { - double timeDiff = ritr->first - (ritr + 1)->first; + double timeDiff = *ritr - *(ritr + 1); if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0)) minDiff = timeDiff; if (minDiff != 0 @@ -148,35 +151,71 @@ namespace systemtap itr != e; ++itr) { + std::tr1::shared_ptr > realData + = std::tr1::dynamic_pointer_cast >(*itr); + std::tr1::shared_ptr > stringData + = std::tr1::dynamic_pointer_cast >(*itr); cr->save(); cr->translate(0.0, height); cr->scale(1.0, -1.0); - GraphData::List::iterator lower - = std::lower_bound((*itr)->data.begin(), (*itr)->data.end(), _left, - GraphData::Compare()); - GraphData::List::iterator upper - = std::upper_bound((*itr)->data.begin(), (*itr)->data.end(), _right, - GraphData::Compare()); - for (GraphData::List::iterator ditr = lower, de = upper; + GraphDataBase::TimeList::iterator lower + = std::lower_bound((*itr)->times.begin(), (*itr)->times.end(), _left); + GraphDataBase::TimeList::iterator upper + = std::upper_bound((*itr)->times.begin(), (*itr)->times.end(), + _right); + // event bar + if ((*itr)->style == GraphDataBase::EVENT) + { + double eventHeight = height * ((*itr)->scale / 100.0); + cr->save(); + cr->set_line_width(3 * _lineWidth); + cr->set_source_rgba((*itr)->color[0], (*itr)->color[1], + (*itr)->color[2], .33); + cr->move_to(0, eventHeight); + cr->line_to(width, eventHeight); + cr->stroke(); + cr->restore(); + } + for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; ditr != de; ++ditr) { + size_t dataIndex = ditr - (*itr)->times.begin(); cr->set_source_rgba((*itr)->color[0], (*itr)->color[1], (*itr)->color[2], 1.0); - if ((*itr)->style == GraphData::BAR) + if ((*itr)->style == GraphDataBase::BAR && realData) { - cr->move_to((ditr->first - _left) * horizScale, 0); - cr->line_to((ditr->first - _left) * horizScale, - ditr->second * height / (*itr)->scale); + cr->move_to((*ditr - _left) * horizScale, 0); + cr->line_to((*ditr - _left) * horizScale, + realData->data[dataIndex] * height / (*itr)->scale); cr->stroke(); } - else + else if ((*itr)->style == GraphDataBase::DOT && realData) { - cr->arc((ditr->first - _left) * horizScale, - ditr->second * height / (*itr)->scale, + cr->arc((*ditr - _left) * horizScale, + realData->data[dataIndex] * height / (*itr)->scale, _lineWidth / 2.0, 0.0, M_PI * 2.0); cr->fill(); } + else if ((*itr)->style == GraphDataBase::EVENT && stringData) + { + double eventHeight = height * ((*itr)->scale / 100.0); + cr->save(); + cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_NORMAL); + cr->set_font_size(12.0); + cr->save(); + cr->scale(1.0, -1.0); + cr->move_to((*ditr - _left) * horizScale, + -eventHeight -3.0 * _lineWidth - 2.0); + cr->show_text(stringData->data[dataIndex]); + cr->restore(); + cr->rectangle((*ditr - _left) * horizScale - 1.5 * _lineWidth, + eventHeight - 1.5 * _lineWidth, + 3.0 * _lineWidth, 3.0 * _lineWidth); + cr->fill(); + cr->restore(); + } } cr->restore(); } diff --git a/grapher/GraphWidget.hxx b/grapher/GraphWidget.hxx index 46075b78..86ba771d 100644 --- a/grapher/GraphWidget.hxx +++ b/grapher/GraphWidget.hxx @@ -17,7 +17,7 @@ namespace systemtap public: GraphWidget(); virtual ~GraphWidget(); - void addGraphData(std::tr1::shared_ptr data); + void addGraphData(std::tr1::shared_ptr data); void getExtents(double& left, double& right, double& top, double& bottom) const; void setExtents(double left, double right, double top, double bottom); double getLineWidth() { return _lineWidth; } @@ -38,7 +38,7 @@ namespace systemtap virtual bool on_button_release_event(GdkEventButton* event); virtual bool on_scroll_event(GdkEventScroll* event); bool on_timeout(); - typedef std::vector > DatasetList; + typedef std::vector > DatasetList; DatasetList _datasets; double _left; double _right; diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx index c973b0aa..8b72f93b 100644 --- a/grapher/StapParser.cxx +++ b/grapher/StapParser.cxx @@ -1,6 +1,7 @@ #include "StapParser.hxx" #include +#include namespace systemtap { @@ -27,6 +28,29 @@ vector commaSplit(const string& inStr, size_t pos = 0) return result; } + void StapParser::parseData(std::tr1::shared_ptr gdata, + double time, const string& dataString) + { + std::istringstream stream(dataString); + std::tr1::shared_ptr > dblptr; + std::tr1::shared_ptr > strptr; + dblptr = std::tr1::dynamic_pointer_cast >(gdata); + if (dblptr) + { + double data; + stream >> data; + dblptr->times.push_back(time); + dblptr->data.push_back(data); + } + else if ((strptr = std::tr1 + ::dynamic_pointer_cast >(gdata)) + != 0) + { + strptr->times.push_back(time); + strptr->data.push_back(dataString); + } + } + bool StapParser::ioCallback(Glib::IOCondition ioCondition) { using namespace std; @@ -71,20 +95,38 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition) } else if ((found = dataString.find("%DataSet:") == 0)) { - std::tr1::shared_ptr dataSet(new GraphData); std::string setName; int hexColor; + double scale; std::string style; std::istringstream stream(dataString.substr(9)); - stream >> setName >> dataSet->scale >> std::hex >> hexColor + stream >> setName >> scale >> std::hex >> hexColor >> style; - dataSet->color[0] = (hexColor >> 16) / 255.0; - dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; - dataSet->color[2] = (hexColor & 0xff) / 255.0; - if (style == "dot") - dataSet->style = GraphData::DOT; - _dataSets.insert(std::make_pair(setName, dataSet)); - _widget.addGraphData(dataSet); + if (style == "bar" || style == "dot") + { + std::tr1::shared_ptr > + dataSet(new GraphData); + if (style == "dot") + dataSet->style = GraphDataBase::DOT; + dataSet->color[0] = (hexColor >> 16) / 255.0; + dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; + dataSet->color[2] = (hexColor & 0xff) / 255.0; + dataSet->scale = scale; + _dataSets.insert(std::make_pair(setName, dataSet)); + _widget.addGraphData(dataSet); + } + else if (style == "discreet") + { + std::tr1::shared_ptr > + dataSet(new GraphData); + dataSet->style = GraphDataBase::EVENT; + dataSet->color[0] = (hexColor >> 16) / 255.0; + dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; + dataSet->color[2] = (hexColor & 0xff) / 255.0; + dataSet->scale = scale; + _dataSets.insert(std::make_pair(setName, dataSet)); + _widget.addGraphData(dataSet); + } } else if ((found = dataString.find("%CSV:") == 0)) { @@ -96,8 +138,9 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition) { DataMap::iterator setIter = _dataSets.find(*tokIter); if (setIter != _dataSets.end()) - _csv.elements.push_back(CSVData::Element(*tokIter, - setIter->second)); + _csv.elements + .push_back(CSVData::Element(*tokIter, + setIter->second)); } } } @@ -115,23 +158,21 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition) tokIter != e; ++tokIter, ++i) { - std::istringstream stream(*tokIter); - double data; - stream >> data; - _csv.elements[i].second - ->data.push_back(std::make_pair(time, data)); + parseData(_csv.elements[i].second, time, *tokIter); } } else { std::string dataSet; double time; - double data; + string data; std::istringstream stream(dataString); stream >> dataSet >> time >> data; DataMap::iterator itr = _dataSets.find(dataSet); if (itr != _dataSets.end()) - itr->second->data.push_back(std::make_pair(time, data)); + { + parseData(itr->second, time, data); + } } } _buffer.erase(0, ret + 1); diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx index 624accc7..e11e7302 100644 --- a/grapher/StapParser.hxx +++ b/grapher/StapParser.hxx @@ -7,7 +7,7 @@ namespace systemtap class StapParser { std::string _buffer; - typedef std::map > DataMap; + typedef std::map > DataMap; DataMap _dataSets; CSVData _csv; Gtk::Window& _win; @@ -15,7 +15,8 @@ class StapParser public: StapParser(Gtk::Window& win, GraphWidget& widget) : _win(win), _widget(widget) {} - + void parseData(std::tr1::shared_ptr gdata, + double time, const std::string& dataString); bool ioCallback(Glib::IOCondition ioCondition); }; diff --git a/testsuite/systemtap.examples/general/grapher.stp b/testsuite/systemtap.examples/general/grapher.stp index 5d9b4bb5..26d35aca 100644 --- a/testsuite/systemtap.examples/general/grapher.stp +++ b/testsuite/systemtap.examples/general/grapher.stp @@ -6,7 +6,7 @@ printf ("%%Title:CPU utilization\n"); printf ("%%XAxisTitle:Time\n"); printf ("%%YAxisTitle:Percent\n"); printf ("%%DataSet:cpu 100 00ff00 bar\n"); -printf ("%%DataSet:kbd 100 ff0000 dot\n"); +printf ("%%DataSet:kbd 75 ff0000 discreet\n"); } # CPU utilization @@ -28,5 +28,6 @@ probe timer.ms(100) { # collect utilization percentages frequently } probe kernel.function("kbd_event") { - printf("kbd %d %d\n", gettimeofday_ms(), 75) + if ($event_type == 1 && $value) + printf("kbd %d %d\n", gettimeofday_ms(), $event_code) } -- cgit From a030ced8c0b8109ba7b23bbbc65deddf88154a2f Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Thu, 4 Jun 2009 15:49:16 +0200 Subject: grapher fixups * grapher/grapher.cxx (main): Fix problems with call to execlp. --- grapher/grapher.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx index 0013d8b0..26e5b9b2 100644 --- a/grapher/grapher.cxx +++ b/grapher/grapher.cxx @@ -119,7 +119,7 @@ int main(int argc, char** argv) { dup2(pipefd[1], 1); close(pipefd[1]); - execlp("stap", argv[1]); + execlp("stap", "stap", argv[1], static_cast(0)); exit(1); return 1; } -- cgit From 364ad890e341bb60ae169af69933a382d4bf9f81 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Mon, 27 Jul 2009 12:46:30 +0200 Subject: Support for presenting multiple graphs * grapher/Graph.hxx: New file; class for single graph display. * grapher/Graph.cxx: New file. * grapher/GraphData.hxx: Associate title and axis labels with graph data and not a graph display. * grapher/GraphWidget.hxx: Move graph-related members to Graph class. * grapher/GraphWidget.cxx (getExtents, setExtents): Move to Graph class (on_expose_event): Move graph rendering to Graph. (on_button_press_event): Delegate to Graph. (on_motion_notify_event, on_scroll_event): Modify "active" graph. * grapher/StapParser.cxx (findTaggedValue): New parsing helper function. (io_callback): Support new syntax where properties are attached to graph data and not the entire graph. * grapher/grapher.cxx (GrapherWindow): Don't set graph values. * grapher/Makefile.am: Add Graph.cxx. * testsuite/systemtap.examples/general/grapher.stp: New property syntax. --- configure | 480 ++++++++++++++--------- doc/Makefile.in | 131 +++++-- doc/SystemTap_Tapset_Reference/Makefile.in | 71 ++-- grapher/Graph.cxx | 262 +++++++++++++ grapher/Graph.hxx | 48 +++ grapher/GraphData.hxx | 4 + grapher/GraphWidget.cxx | 294 +++----------- grapher/GraphWidget.hxx | 36 +- grapher/Makefile.am | 2 +- grapher/Makefile.in | 151 ++++--- grapher/StapParser.cxx | 248 ++++++------ grapher/grapher.cxx | 3 - testsuite/Makefile.in | 40 +- testsuite/aclocal.m4 | 145 +++++-- testsuite/configure | 245 +++++++----- testsuite/systemtap.examples/general/grapher.stp | 16 +- 16 files changed, 1337 insertions(+), 839 deletions(-) create mode 100644 grapher/Graph.cxx create mode 100644 grapher/Graph.hxx diff --git a/configure b/configure index 5eb5eb05..e646b3c6 100755 --- a/configure +++ b/configure @@ -637,7 +637,9 @@ ac_includes_default="\ #endif" enable_option_checking=no -ac_subst_vars='LTLIBOBJS +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS LIBOBJS subdirs CXXCPP @@ -1943,7 +1945,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -am__api_version='1.10' +am__api_version='1.11' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2074,16 +2076,33 @@ $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + { { $as_echo "$as_me:$LINENO: error: unsafe absolute working directory name" >&5 +$as_echo "$as_me: error: unsafe absolute working directory name" >&2;} + { (exit 1); exit 1; }; };; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + { { $as_echo "$as_me:$LINENO: error: unsafe srcdir value: \`$srcdir'" >&5 +$as_echo "$as_me: error: unsafe srcdir value: \`$srcdir'" >&2;} + { (exit 1); exit 1; }; };; +esac + # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` + set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ @@ -2127,7 +2146,14 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " @@ -2137,6 +2163,115 @@ else $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + { $as_echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then @@ -2319,108 +2454,6 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} - -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:$LINENO: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:$LINENO: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. @@ -2433,6 +2466,7 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + { $as_echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. @@ -3414,7 +3448,7 @@ ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: - @echo done + @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. @@ -3425,24 +3459,24 @@ am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac fi @@ -3499,6 +3533,11 @@ else if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and @@ -3516,7 +3555,17 @@ else done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested @@ -3526,19 +3575,23 @@ else break fi ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; none) break ;; esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message @@ -3979,6 +4032,11 @@ else if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and @@ -3996,7 +4054,17 @@ else done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested @@ -4006,19 +4074,23 @@ else break fi ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; none) break ;; esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message @@ -5006,6 +5078,11 @@ else if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and @@ -5023,7 +5100,17 @@ else done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested @@ -5033,19 +5120,23 @@ else break fi ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; none) break ;; esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message @@ -8854,7 +8945,7 @@ _ACEOF ac_config_headers="$ac_config_headers config.h:config.in" -ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile grapher/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap" +ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile grapher/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap man/stapprobes.snmp.3stap initscript/systemtap" @@ -8965,6 +9056,14 @@ LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -9596,6 +9695,7 @@ do "man/stapprobes.socket.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.socket.3stap" ;; "man/stapprobes.tcp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.tcp.3stap" ;; "man/stapprobes.udp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.udp.3stap" ;; + "man/stapprobes.snmp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.snmp.3stap" ;; "initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;; "run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;; "run-staprun") CONFIG_FILES="$CONFIG_FILES run-staprun" ;; @@ -10254,27 +10354,28 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || # Autoconf 2.62 quotes --file arguments for eval, but not when files -# are listed without --file. Let's play safe and only enable the eval -# if we detect the quoting. -case $CONFIG_FILES in -*\'*) eval set x "$CONFIG_FILES" ;; -*) set x $CONFIG_FILES ;; -esac -shift -for mf -do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ @@ -10297,28 +10398,28 @@ $as_echo X"$mf" | q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ @@ -10341,7 +10442,7 @@ $as_echo X"$file" | q } s/.*/./; q'` - { as_dir=$dirpart/$fdir + { as_dir=$dirpart/$fdir case $as_dir in #( -*) as_dir=./$as_dir;; esac @@ -10382,10 +10483,11 @@ $as_echo X"$as_dir" | } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 $as_echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done done -done +} ;; "run-stap":F) chmod +x run-stap ;; "run-staprun":F) chmod +x run-staprun ;; diff --git a/doc/Makefile.in b/doc/Makefile.in index f7d902a7..996700ec 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.10.2 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -17,8 +18,9 @@ # Makefile.am --- automake input file for systemtap docs VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c @@ -40,6 +42,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ @@ -51,10 +54,38 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ ps-recursive uninstall-recursive RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ @@ -190,9 +221,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu doc/Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -210,6 +241,7 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -235,7 +267,7 @@ $(RECURSIVE_TARGETS): else \ local_target="$$target"; \ fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ @@ -269,16 +301,16 @@ $(RECURSIVE_CLEAN_TARGETS): else \ local_target="$$target"; \ fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -293,7 +325,7 @@ tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ + set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ @@ -305,7 +337,7 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ - tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -314,29 +346,34 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ + test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique + $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -357,29 +394,44 @@ distdir: $(DISTFILES) if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done - list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ - distdir=`$(am__cd) $(distdir) && pwd`; \ - top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ - (cd $$subdir && \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$top_distdir" \ - distdir="$$distdir/$$subdir" \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ + am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ @@ -410,6 +462,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -431,6 +484,8 @@ dvi-am: html: html-recursive +html-am: + info: info-recursive info-am: @@ -438,21 +493,30 @@ info-am: install-data-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook - install-dvi: install-dvi-recursive +install-dvi-am: + install-exec-am: install-html: install-html-recursive +install-html-am: + install-info: install-info-recursive +install-info-am: + install-man: install-pdf: install-pdf-recursive +install-pdf-am: + install-ps: install-ps-recursive +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-recursive @@ -473,8 +537,8 @@ ps-am: uninstall-am: uninstall-local -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ - install-data-am install-strip +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-data-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am all-local check check-am clean clean-generic \ @@ -520,6 +584,7 @@ uninstall-am: uninstall-local latex -output-directory=$$pwd $<; \ latex -output-directory=$$pwd $<; \ latex -output-directory=$$pwd $< + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in index 82217f3a..2368ccad 100644 --- a/doc/SystemTap_Tapset_Reference/Makefile.in +++ b/doc/SystemTap_Tapset_Reference/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.10.2 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -18,8 +19,9 @@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c @@ -42,6 +44,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) docproc_SOURCES = docproc.c docproc_OBJECTS = docproc.$(OBJEXT) @@ -49,6 +52,7 @@ docproc_LDADD = $(LDADD) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles +am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -195,9 +199,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -215,6 +219,7 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) @@ -232,14 +237,14 @@ distclean-compile: .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` @@ -256,7 +261,7 @@ tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ + set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -264,29 +269,34 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ + test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique + $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -307,13 +317,17 @@ distdir: $(DISTFILES) if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @@ -341,6 +355,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -362,6 +377,8 @@ dvi-am: html: html-am +html-am: + info: info-am info-am: @@ -369,21 +386,30 @@ info-am: install-data-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook - install-dvi: install-dvi-am +install-dvi-am: + install-exec-am: install-html: install-html-am +install-html-am: + install-info: install-info-am +install-info-am: + install-man: install-pdf: install-pdf-am +install-pdf-am: + install-ps: install-ps-am +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-am @@ -452,6 +478,7 @@ uninstall-am: @BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man3/* $(MAN_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(HTML_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR) + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/grapher/Graph.cxx b/grapher/Graph.cxx new file mode 100644 index 00000000..1fa598c2 --- /dev/null +++ b/grapher/Graph.cxx @@ -0,0 +1,262 @@ +#include "Graph.hxx" + +#include +#include +#include + +namespace systemtap +{ + using namespace std; + using namespace std::tr1; + + Graph::Graph() + : _left(0.0), _right(1.0), _top(5.0), _bottom(0.0), _lineWidth(2), + _autoScaling(true), _autoScrolling(true), _zoomFactor(1.0), + _playButton(new CairoPlayButton) + { + } + + + void Graph::draw(Cairo::RefPtr cr) + { + + if (_autoScaling) + { + // line separation + int linesPossible = _graphWidth / (_lineWidth + 2); + // Find latest time. + double latestTime = 0; + for (DatasetList::iterator ditr = _datasets.begin(), + de = _datasets.end(); + ditr != de; + ++ditr) + { + if (!(*ditr)->times.empty()) + { + double lastDataTime = (*ditr)->times.back(); + if (lastDataTime > latestTime) + latestTime = lastDataTime; + } + } + double minDiff = 0.0; + double maxTotal = 0.0; + for (DatasetList::iterator ditr = _datasets.begin(), + de = _datasets.end(); + ditr != de; + ++ditr) + { + GraphDataBase::TimeList& gtimes = (*ditr)->times; + if (gtimes.size() <= 1) + continue; + double totalDiff = 0.0; + for (GraphDataBase::TimeList::reverse_iterator ritr = gtimes.rbegin(), + re = gtimes.rend(); + ritr + 1 != gtimes.rend(); + ritr++) + { + double timeDiff = *ritr - *(ritr + 1); + if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0)) + minDiff = timeDiff; + if (minDiff != 0 + && (totalDiff + timeDiff) / minDiff > linesPossible) + break; + totalDiff += timeDiff; + } + if (totalDiff > maxTotal) + maxTotal = totalDiff; + } + // Now we have a global scale. + _right = latestTime; + if (maxTotal != 0) + _left = latestTime - maxTotal; + else + _left = _right - 1.0; + } + cr->save(); + double horizScale = _zoomFactor * _graphWidth / ( _right - _left); + cr->translate(20.0, 0.0); + cr->set_line_width(_lineWidth); + cr->save(); + cr->set_source_rgba(0.0, 0.0, 0.0, 1.0); + cr->paint(); + cr->restore(); + + for (DatasetList::iterator itr = _datasets.begin(), e = _datasets.end(); + itr != e; + ++itr) + { + shared_ptr graphData = *itr; + shared_ptr > realData + = dynamic_pointer_cast >(*itr); + shared_ptr > stringData + = dynamic_pointer_cast >(*itr); + cr->save(); + cr->translate(0.0, _graphHeight); + cr->scale(1.0, -1.0); + GraphDataBase::TimeList::iterator lower + = std::lower_bound(graphData->times.begin(), graphData->times.end(), + _left); + GraphDataBase::TimeList::iterator upper + = std::upper_bound(graphData->times.begin(), graphData->times.end(), + _right); + // event bar + if (graphData->style == GraphDataBase::EVENT) + { + double eventHeight = _graphHeight * (graphData->scale / 100.0); + cr->save(); + cr->set_line_width(3 * _lineWidth); + cr->set_source_rgba(graphData->color[0], graphData->color[1], + graphData->color[2], .33); + cr->move_to(0, eventHeight); + cr->line_to(_graphWidth, eventHeight); + cr->stroke(); + cr->restore(); + } + for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; + ditr != de; + ++ditr) + { + size_t dataIndex = ditr - graphData->times.begin(); + cr->set_source_rgba(graphData->color[0], graphData->color[1], + graphData->color[2], 1.0); + if (graphData->style == GraphDataBase::BAR && realData) + { + cr->move_to((*ditr - _left) * horizScale, 0); + cr->line_to((*ditr - _left) * horizScale, + realData->data[dataIndex] * _graphHeight + / graphData->scale); + cr->stroke(); + } + else if (graphData->style == GraphDataBase::DOT && realData) + { + cr->arc((*ditr - _left) * horizScale, + realData->data[dataIndex] * _graphHeight / graphData->scale, + _lineWidth / 2.0, 0.0, M_PI * 2.0); + cr->fill(); + } + else if (graphData->style == GraphDataBase::EVENT && stringData) + { + double eventHeight = _graphHeight * (graphData->scale / 100.0); + cr->save(); + cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_NORMAL); + cr->set_font_size(12.0); + cr->save(); + cr->scale(1.0, -1.0); + cr->move_to((*ditr - _left) * horizScale, + -eventHeight -3.0 * _lineWidth - 2.0); + cr->show_text(stringData->data[dataIndex]); + cr->restore(); + cr->rectangle((*ditr - _left) * horizScale - 1.5 * _lineWidth, + eventHeight - 1.5 * _lineWidth, + 3.0 * _lineWidth, 3.0 * _lineWidth); + cr->fill(); + cr->restore(); + } + } + cr->restore(); + cr->save(); + cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_BOLD); + cr->set_font_size(14.0); + cr->set_source_rgba(1.0, 1.0, 1.0, .8); + + if (!graphData->title.empty()) + { + cr->move_to(20.0, 20.0); + cr->show_text(graphData->title); + } + if (!graphData->xAxisText.empty()) + { + cr->move_to(10.0, _graphHeight - 5); + cr->show_text(graphData->xAxisText); + } + if (!graphData->yAxisText.empty()) + { + cr->save(); + cr->translate(10.0, _height - 10.0); + cr->rotate(-M_PI / 2.0); + cr->move_to(10.0, 0.0); + cr->show_text(graphData->yAxisText); + cr->restore(); + } + cr->restore(); + + } + cr->restore(); + // Draw axes + double diff = _right - _left; + double majorUnit = pow(10.0, floor(log(diff) / log(10.0))); + double startTime = ceil(_left / majorUnit) * majorUnit; + cr->save(); + cr->set_source_rgba(1.0, 1.0, 1.0, .9); + cr->set_line_cap(Cairo::LINE_CAP_BUTT); + cr->set_line_width(_lineWidth); + cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_NORMAL); + cr->set_font_size(10.0); + cr->move_to(20.0, 0.0); + cr->line_to(20.0, _height); + cr->move_to(20.0, _graphHeight); + cr->line_to(_graphWidth, _graphHeight); + cr->stroke(); + std::valarray dash(1); + dash[0] = _graphHeight / 10; + cr->set_dash(dash, 0); + double prevTextAdvance = 0; + for (double tickVal = startTime; tickVal <= _right; tickVal += majorUnit) + { + double x = (tickVal - _left) * horizScale + 20.0; + cr->move_to(x, 0.0); + cr->line_to(x, _graphHeight); + cr->move_to(x, _graphHeight - 5); + std::ostringstream stream; + stream << std::fixed << std::setprecision(0) << tickVal; + Cairo::TextExtents extents; + cr->get_text_extents(stream.str(), extents); + // Room for this label? + if (x + extents.x_bearing > prevTextAdvance) + { + cr->show_text(stream.str()); + prevTextAdvance = x + extents.x_advance; + } + } + cr->stroke(); + cr->restore(); + + if (!_autoScrolling) + { + _playButton->setVisible(true); + _playButton->setOrigin(_graphWidth / 2 - 25, .875 * _graphHeight - 50); + _playButton->draw(cr); + } + + } + + void Graph::addGraphData(std::tr1::shared_ptr data) + { + _datasets.push_back(data); + } + + void Graph::getExtents(double& left, double& right, double& top, + double& bottom) const + { + left = _left; + right = _right; + top = _top; + bottom = _bottom; + } + + void Graph::setExtents(double left, double right, double top, double bottom) + { + _left = left; + _right = right; + _top = top; + _bottom = bottom; + } + + bool Graph::containsPoint(double x, double y) + { + return x >= _x0 && x < _x0 + _width && y >= _y0 && y < _y0 + _height; + } +} diff --git a/grapher/Graph.hxx b/grapher/Graph.hxx new file mode 100644 index 00000000..1cc1892d --- /dev/null +++ b/grapher/Graph.hxx @@ -0,0 +1,48 @@ +#ifndef SYSTEMTAP_GRAPH_HXX +#define SYSTEMTAP_GRAPH_HXX 1 + +#include + +#include "GraphData.hxx" +#include "CairoWidget.hxx" + +namespace systemtap +{ + class Graph : public CairoWidget + { + public: + friend class GraphWidget; + Graph(); + virtual void draw(Cairo::RefPtr cr); + virtual bool containsPoint(double x, double y); + double getLineWidth() { return _lineWidth; } + void setLineWidth(double lineWidth) { _lineWidth = lineWidth; } + bool getAutoScaling() const { return _autoScaling; } + void setAutoScaling(bool val) { _autoScaling = val; } + void addGraphData(std::tr1::shared_ptr data); + void getExtents(double& left, double& right, double& top, double& bottom) + const; + void setExtents(double left, double right, double top, double bottom); + // extents of the whole graph area + double _width; + double _height; + // Position, extents of the graph + double _graphX; + double _graphY; + double _graphWidth; + double _graphHeight; + double _lineWidth; + bool _autoScaling; + bool _autoScrolling; + double _zoomFactor; + std::tr1::shared_ptr _playButton; + protected: + typedef std::vector > DatasetList; + DatasetList _datasets; + double _left; + double _right; + double _top; + double _bottom; + }; +} +#endif diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx index 9bf3b624..e4c08cfd 100644 --- a/grapher/GraphData.hxx +++ b/grapher/GraphData.hxx @@ -1,6 +1,7 @@ #ifndef SYSTEMTAP_GRAPHDATA_HXX #define SYSTEMTAP_GRAPHDATA_HXX 1 +#include #include #include #include @@ -24,6 +25,9 @@ namespace systemtap double scale; double color[3]; Style style; + std::string title; + std::string xAxisText; + std::string yAxisText; TimeList times; }; diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx index d62ec4f3..5b0d1b1c 100644 --- a/grapher/GraphWidget.cxx +++ b/grapher/GraphWidget.cxx @@ -1,21 +1,18 @@ #include #include #include -#include -#include -#include + #include #include "GraphWidget.hxx" #include "CairoWidget.hxx" namespace systemtap { - using std::string; + using namespace std; + using namespace std::tr1; GraphWidget::GraphWidget() - : _left(0.0), _right(1.0), _top(1.0), _bottom(0.0), _lineWidth(10), - _autoScaling(true), _autoScrolling(true), _zoomFactor(1.0), - _trackingDrag(false), _playButton(new CairoPlayButton) + : _trackingDrag(false) { add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); @@ -34,33 +31,20 @@ namespace systemtap false); signal_scroll_event() .connect(sigc::mem_fun(*this, &GraphWidget::on_scroll_event), false); + // Temporary testing of multiple graphs + shared_ptr graph(new Graph); + graph->_graphHeight = 180; + graph->_graphWidth = 580; + _graphs.push_back(graph); } - void GraphWidget::getExtents(double& left, double& right, double& top, - double& bottom) const - { - left = _left; - right = _right; - top = _top; - bottom = _bottom; - } - - void GraphWidget::setExtents(double left, double right, double top, - double bottom) - { - _left = left; - _right = right; - _top = top; - _bottom = bottom; - - } GraphWidget::~GraphWidget() { } void GraphWidget::addGraphData(std::tr1::shared_ptr data) { - _datasets.push_back(data); + _graphs[0]->addGraphData(data); } bool GraphWidget::on_expose_event(GdkEventExpose* event) @@ -78,6 +62,7 @@ namespace systemtap const int height = graphHeight - 20; Cairo::RefPtr cr = window->create_cairo_context(); +#if 0 if(event && !_autoScaling) { // clip to the area indicated by the expose event so that we only @@ -86,233 +71,51 @@ namespace systemtap event->area.width, event->area.height); cr->clip(); } - if (_autoScaling) - { - // line separation - int linesPossible = width / ((int)_lineWidth + 2); - // Find latest time. - double latestTime = 0; - for (DatasetList::iterator ditr = _datasets.begin(), - de = _datasets.end(); - ditr != de; - ++ditr) - { - if (!(*ditr)->times.empty()) - { - double lastDataTime = (*ditr)->times.back(); - if (lastDataTime > latestTime) - latestTime = lastDataTime; - } - } - double minDiff = 0.0; - double maxTotal = 0.0; - for (DatasetList::iterator ditr = _datasets.begin(), - de = _datasets.end(); - ditr != de; - ++ditr) - { - GraphDataBase::TimeList& gtimes = (*ditr)->times; - if (gtimes.size() <= 1) - continue; - double totalDiff = 0.0; - for (GraphDataBase::TimeList::reverse_iterator ritr = gtimes.rbegin(), - re = gtimes.rend(); - ritr + 1 != gtimes.rend(); - ritr++) - { - double timeDiff = *ritr - *(ritr + 1); - if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0)) - minDiff = timeDiff; - if (minDiff != 0 - && (totalDiff + timeDiff) / minDiff > linesPossible) - break; - totalDiff += timeDiff; - } - if (totalDiff > maxTotal) - maxTotal = totalDiff; - } - // Now we have a global scale. - _right = latestTime; - if (maxTotal != 0) - _left = latestTime - maxTotal; - else - _left = _right - 1.0; - } - cr->save(); - double horizScale = _zoomFactor * width / ( _right - _left); - cr->translate(20.0, 0.0); - cr->set_line_width(_lineWidth); +#endif cr->save(); cr->set_source_rgba(0.0, 0.0, 0.0, 1.0); cr->paint(); - cr->restore(); - - for (DatasetList::iterator itr = _datasets.begin(), e = _datasets.end(); - itr != e; - ++itr) - { - std::tr1::shared_ptr > realData - = std::tr1::dynamic_pointer_cast >(*itr); - std::tr1::shared_ptr > stringData - = std::tr1::dynamic_pointer_cast >(*itr); - cr->save(); - cr->translate(0.0, height); - cr->scale(1.0, -1.0); - GraphDataBase::TimeList::iterator lower - = std::lower_bound((*itr)->times.begin(), (*itr)->times.end(), _left); - GraphDataBase::TimeList::iterator upper - = std::upper_bound((*itr)->times.begin(), (*itr)->times.end(), - _right); - // event bar - if ((*itr)->style == GraphDataBase::EVENT) - { - double eventHeight = height * ((*itr)->scale / 100.0); - cr->save(); - cr->set_line_width(3 * _lineWidth); - cr->set_source_rgba((*itr)->color[0], (*itr)->color[1], - (*itr)->color[2], .33); - cr->move_to(0, eventHeight); - cr->line_to(width, eventHeight); - cr->stroke(); - cr->restore(); - } - for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; - ditr != de; - ++ditr) - { - size_t dataIndex = ditr - (*itr)->times.begin(); - cr->set_source_rgba((*itr)->color[0], (*itr)->color[1], - (*itr)->color[2], 1.0); - if ((*itr)->style == GraphDataBase::BAR && realData) - { - cr->move_to((*ditr - _left) * horizScale, 0); - cr->line_to((*ditr - _left) * horizScale, - realData->data[dataIndex] * height / (*itr)->scale); - cr->stroke(); - } - else if ((*itr)->style == GraphDataBase::DOT && realData) - { - cr->arc((*ditr - _left) * horizScale, - realData->data[dataIndex] * height / (*itr)->scale, - _lineWidth / 2.0, 0.0, M_PI * 2.0); - cr->fill(); - } - else if ((*itr)->style == GraphDataBase::EVENT && stringData) - { - double eventHeight = height * ((*itr)->scale / 100.0); - cr->save(); - cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, - Cairo::FONT_WEIGHT_NORMAL); - cr->set_font_size(12.0); - cr->save(); - cr->scale(1.0, -1.0); - cr->move_to((*ditr - _left) * horizScale, - -eventHeight -3.0 * _lineWidth - 2.0); - cr->show_text(stringData->data[dataIndex]); - cr->restore(); - cr->rectangle((*ditr - _left) * horizScale - 1.5 * _lineWidth, - eventHeight - 1.5 * _lineWidth, - 3.0 * _lineWidth, 3.0 * _lineWidth); - cr->fill(); - cr->restore(); - } - } - cr->restore(); - } - cr->restore(); - cr->save(); - cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, - Cairo::FONT_WEIGHT_BOLD); - cr->set_font_size(14.0); - cr->set_source_rgba(1.0, 1.0, 1.0, .8); - - if (!_title.empty()) - { - cr->move_to(20.0, 20.0); - cr->show_text(_title); - } - if (!_xAxisText.empty()) - { - cr->move_to(10.0, graphHeight - 5); - cr->show_text(_xAxisText); - } - if (!_yAxisText.empty()) + for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g) { cr->save(); - cr->translate(10.0, height - 10.0); - cr->rotate(-M_PI / 2.0); - cr->move_to(10.0, 0.0); - cr->show_text(_yAxisText); + cr->translate((*g)->_graphX, (*g)->_graphY); + (*g)->draw(cr); cr->restore(); } - cr->restore(); - // Draw axes - double diff = _right - _left; - double majorUnit = pow(10.0, floor(log(diff) / log(10.0))); - double startTime = ceil(_left / majorUnit) * majorUnit; - cr->save(); - cr->set_source_rgba(1.0, 1.0, 1.0, .9); - cr->set_line_cap(Cairo::LINE_CAP_BUTT); - cr->set_line_width(_lineWidth); - cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, - Cairo::FONT_WEIGHT_NORMAL); - cr->set_font_size(10.0); - cr->move_to(20.0, 0.0); - cr->line_to(20.0, height); - cr->move_to(20.0, height); - cr->line_to(graphWidth, height); - cr->stroke(); - std::valarray dash(1); - dash[0] = height / 10; - cr->set_dash(dash, 0.0); - double prevTextAdvance = 0; - for (double tickVal = startTime; tickVal <= _right; tickVal += majorUnit) - { - double x = (tickVal - _left) * horizScale + 20.0; - cr->move_to(x, 0.0); - cr->line_to(x, height); - cr->move_to(x, graphHeight - 5); - std::ostringstream stream; - stream << std::fixed << std::setprecision(0) << tickVal; - Cairo::TextExtents extents; - cr->get_text_extents(stream.str(), extents); - // Room for this label? - if (x + extents.x_bearing > prevTextAdvance) - { - cr->show_text(stream.str()); - prevTextAdvance = x + extents.x_advance; - } - } - cr->stroke(); - cr->restore(); - - if (!_autoScrolling) - { - _playButton->setVisible(true); - _playButton->setOrigin(width / 2 - 25, .875 * height - 50); - _playButton->draw(cr); - } - return true; } bool GraphWidget::on_button_press_event(GdkEventButton* event) { - if (!_autoScrolling && _playButton->containsPoint(event->x, event->y)) + for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g) + { + if (event->x >= (*g)->_graphX + && event->x < (*g)->_graphX + (*g)->_graphWidth + && event->y >= (*g)->_graphY + && event->y < (*g)->_graphY + (*g)->_graphHeight) + { + _activeGraph = *g; + break; + } + } + if (!_activeGraph) + return true; + if (!_activeGraph->_autoScrolling + && _activeGraph->_playButton->containsPoint(event->x, event->y)) { - _autoScaling = true; - _autoScrolling = true; + _activeGraph->_autoScaling = true; + _activeGraph->_autoScrolling = true; queue_draw(); } else { _trackingDrag = true; - _autoScaling = false; - _autoScrolling = false; + _activeGraph->_autoScaling = false; + _activeGraph->_autoScrolling = false; _dragOriginX = event->x; _dragOriginY = event->y; - _dragOrigLeft = _left; - _dragOrigRight = _right; + _dragOrigLeft = _activeGraph->_left; + _dragOrigRight = _activeGraph->_right; } return true; } @@ -339,14 +142,14 @@ namespace systemtap x = event->x; y = event->y; } - if (_trackingDrag) + if (_trackingDrag && _activeGraph) { Gtk::Allocation allocation = get_allocation(); const int width = allocation.get_width(); double motion = (x - _dragOriginX) / (double) width; double increment = motion * (_dragOrigLeft - _dragOrigRight); - _left = _dragOrigLeft + increment; - _right = _dragOrigRight + increment; + _activeGraph->_left = _dragOrigLeft + increment; + _activeGraph->_right = _dragOrigRight + increment; queue_draw(); } return true; @@ -354,11 +157,20 @@ namespace systemtap bool GraphWidget::on_scroll_event(GdkEventScroll* event) { - if (event->direction == GDK_SCROLL_UP) - _zoomFactor += .1; - else if (event->direction == GDK_SCROLL_DOWN) - _zoomFactor -= .1; - queue_draw(); + for (GraphList::iterator gitr = _graphs.begin(); + gitr != _graphs.end(); + ++gitr) + { + if ((*gitr)->containsPoint(event->x, event->y)) + { + if (event->direction == GDK_SCROLL_UP) + (*gitr)->_zoomFactor += .1; + else if (event->direction == GDK_SCROLL_DOWN) + (*gitr)->_zoomFactor -= .1; + queue_draw(); + break; + } + } return true; } diff --git a/grapher/GraphWidget.hxx b/grapher/GraphWidget.hxx index 86ba771d..c15f8fcd 100644 --- a/grapher/GraphWidget.hxx +++ b/grapher/GraphWidget.hxx @@ -6,7 +6,7 @@ #include #include -#include "GraphData.hxx" +#include namespace systemtap { @@ -18,19 +18,15 @@ namespace systemtap GraphWidget(); virtual ~GraphWidget(); void addGraphData(std::tr1::shared_ptr data); - void getExtents(double& left, double& right, double& top, double& bottom) const; - void setExtents(double left, double right, double top, double bottom); - double getLineWidth() { return _lineWidth; } - void setLineWidth(double lineWidth) { _lineWidth = lineWidth; } - bool getAutoScaling() const { return _autoScaling; } - void setAutoScaling(bool val) { _autoScaling = val; } - std::string getTitle() const { return _title; } - void setTitle(const std::string& title) { _title = title; } - std::string getXAxisText() const { return _xAxisText; } - void setXAxisText(const std::string& text) { _xAxisText = text; } - std::string getYAxisText() const { return _yAxisText; } - void setYAxisText(const std::string& text) { _yAxisText = text; } + protected: + typedef std::vector > GraphList; + GraphList _graphs; + // For click and drag + std::tr1::shared_ptr _activeGraph; + // Dragging all graphs simultaneously, or perhaps seperately + typedef std::vector > DragList; + DragList dragCoords; //Override default signal handler: virtual bool on_expose_event(GdkEventExpose* event); virtual bool on_motion_notify_event(GdkEventMotion* event); @@ -38,25 +34,11 @@ namespace systemtap virtual bool on_button_release_event(GdkEventButton* event); virtual bool on_scroll_event(GdkEventScroll* event); bool on_timeout(); - typedef std::vector > DatasetList; - DatasetList _datasets; - double _left; - double _right; - double _top; - double _bottom; - double _lineWidth; - bool _autoScaling; - bool _autoScrolling; - double _zoomFactor; bool _trackingDrag; double _dragOriginX; double _dragOriginY; double _dragOrigLeft; double _dragOrigRight; - std::string _title; - std::string _xAxisText; - std::string _yAxisText; - std::tr1::shared_ptr _playButton; }; } #endif // SYSTEMTAP_GRAPHWIDGET_H diff --git a/grapher/Makefile.am b/grapher/Makefile.am index bd651352..0f61d77b 100644 --- a/grapher/Makefile.am +++ b/grapher/Makefile.am @@ -2,6 +2,6 @@ if BUILD_GRAPHER bin_PROGRAMS = grapher grapher_CXXFLAGS = $(GRAPHER_CFLAGS) -grapher_SOURCES = grapher.cxx StapParser.cxx GraphWidget.cxx CairoWidget.cxx +grapher_SOURCES = grapher.cxx StapParser.cxx Graph.cxx GraphWidget.cxx CairoWidget.cxx grapher_LDADD = $(GRAPHER_LIBS) endif \ No newline at end of file diff --git a/grapher/Makefile.in b/grapher/Makefile.in index 3e65401e..227359be 100644 --- a/grapher/Makefile.in +++ b/grapher/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.10.2 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -16,8 +17,9 @@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c @@ -40,13 +42,14 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" -binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) -am__grapher_SOURCES_DIST = grapher.cxx StapParser.cxx GraphWidget.cxx \ - CairoWidget.cxx +am__grapher_SOURCES_DIST = grapher.cxx StapParser.cxx Graph.cxx \ + GraphWidget.cxx CairoWidget.cxx @BUILD_GRAPHER_TRUE@am_grapher_OBJECTS = grapher-grapher.$(OBJEXT) \ @BUILD_GRAPHER_TRUE@ grapher-StapParser.$(OBJEXT) \ +@BUILD_GRAPHER_TRUE@ grapher-Graph.$(OBJEXT) \ @BUILD_GRAPHER_TRUE@ grapher-GraphWidget.$(OBJEXT) \ @BUILD_GRAPHER_TRUE@ grapher-CairoWidget.$(OBJEXT) grapher_OBJECTS = $(am_grapher_OBJECTS) @@ -57,6 +60,7 @@ grapher_LINK = $(CXXLD) $(grapher_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles +am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -186,7 +190,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @BUILD_GRAPHER_TRUE@grapher_CXXFLAGS = $(GRAPHER_CFLAGS) -@BUILD_GRAPHER_TRUE@grapher_SOURCES = grapher.cxx StapParser.cxx GraphWidget.cxx CairoWidget.cxx +@BUILD_GRAPHER_TRUE@grapher_SOURCES = grapher.cxx StapParser.cxx Graph.cxx GraphWidget.cxx CairoWidget.cxx @BUILD_GRAPHER_TRUE@grapher_LDADD = $(GRAPHER_LIBS) all: all-am @@ -201,9 +205,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu grapher/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu grapher/Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu grapher/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu grapher/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -221,26 +225,41 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" - @list='$(bin_PROGRAMS)'; for p in $$list; do \ - p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ - if test -f $$p \ - ; then \ - f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ - $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ - else :; fi; \ - done + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) - @list='$(bin_PROGRAMS)'; for p in $$list; do \ - f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ - rm -f "$(DESTDIR)$(bindir)/$$f"; \ - done + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) @@ -255,76 +274,91 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-CairoWidget.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-Graph.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-GraphWidget.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-StapParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-grapher.Po@am__quote@ .cxx.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cxx.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` grapher-grapher.o: grapher.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-grapher.o -MD -MP -MF $(DEPDIR)/grapher-grapher.Tpo -c -o grapher-grapher.o `test -f 'grapher.cxx' || echo '$(srcdir)/'`grapher.cxx -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='grapher.cxx' object='grapher-grapher.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-grapher.o `test -f 'grapher.cxx' || echo '$(srcdir)/'`grapher.cxx grapher-grapher.obj: grapher.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-grapher.obj -MD -MP -MF $(DEPDIR)/grapher-grapher.Tpo -c -o grapher-grapher.obj `if test -f 'grapher.cxx'; then $(CYGPATH_W) 'grapher.cxx'; else $(CYGPATH_W) '$(srcdir)/grapher.cxx'; fi` -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='grapher.cxx' object='grapher-grapher.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-grapher.obj `if test -f 'grapher.cxx'; then $(CYGPATH_W) 'grapher.cxx'; else $(CYGPATH_W) '$(srcdir)/grapher.cxx'; fi` grapher-StapParser.o: StapParser.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-StapParser.o -MD -MP -MF $(DEPDIR)/grapher-StapParser.Tpo -c -o grapher-StapParser.o `test -f 'StapParser.cxx' || echo '$(srcdir)/'`StapParser.cxx -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='StapParser.cxx' object='grapher-StapParser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-StapParser.o `test -f 'StapParser.cxx' || echo '$(srcdir)/'`StapParser.cxx grapher-StapParser.obj: StapParser.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-StapParser.obj -MD -MP -MF $(DEPDIR)/grapher-StapParser.Tpo -c -o grapher-StapParser.obj `if test -f 'StapParser.cxx'; then $(CYGPATH_W) 'StapParser.cxx'; else $(CYGPATH_W) '$(srcdir)/StapParser.cxx'; fi` -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='StapParser.cxx' object='grapher-StapParser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-StapParser.obj `if test -f 'StapParser.cxx'; then $(CYGPATH_W) 'StapParser.cxx'; else $(CYGPATH_W) '$(srcdir)/StapParser.cxx'; fi` +grapher-Graph.o: Graph.cxx +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-Graph.o -MD -MP -MF $(DEPDIR)/grapher-Graph.Tpo -c -o grapher-Graph.o `test -f 'Graph.cxx' || echo '$(srcdir)/'`Graph.cxx +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-Graph.Tpo $(DEPDIR)/grapher-Graph.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Graph.cxx' object='grapher-Graph.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-Graph.o `test -f 'Graph.cxx' || echo '$(srcdir)/'`Graph.cxx + +grapher-Graph.obj: Graph.cxx +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-Graph.obj -MD -MP -MF $(DEPDIR)/grapher-Graph.Tpo -c -o grapher-Graph.obj `if test -f 'Graph.cxx'; then $(CYGPATH_W) 'Graph.cxx'; else $(CYGPATH_W) '$(srcdir)/Graph.cxx'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-Graph.Tpo $(DEPDIR)/grapher-Graph.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Graph.cxx' object='grapher-Graph.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-Graph.obj `if test -f 'Graph.cxx'; then $(CYGPATH_W) 'Graph.cxx'; else $(CYGPATH_W) '$(srcdir)/Graph.cxx'; fi` + grapher-GraphWidget.o: GraphWidget.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-GraphWidget.o -MD -MP -MF $(DEPDIR)/grapher-GraphWidget.Tpo -c -o grapher-GraphWidget.o `test -f 'GraphWidget.cxx' || echo '$(srcdir)/'`GraphWidget.cxx -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='GraphWidget.cxx' object='grapher-GraphWidget.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-GraphWidget.o `test -f 'GraphWidget.cxx' || echo '$(srcdir)/'`GraphWidget.cxx grapher-GraphWidget.obj: GraphWidget.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-GraphWidget.obj -MD -MP -MF $(DEPDIR)/grapher-GraphWidget.Tpo -c -o grapher-GraphWidget.obj `if test -f 'GraphWidget.cxx'; then $(CYGPATH_W) 'GraphWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/GraphWidget.cxx'; fi` -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='GraphWidget.cxx' object='grapher-GraphWidget.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-GraphWidget.obj `if test -f 'GraphWidget.cxx'; then $(CYGPATH_W) 'GraphWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/GraphWidget.cxx'; fi` grapher-CairoWidget.o: CairoWidget.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-CairoWidget.o -MD -MP -MF $(DEPDIR)/grapher-CairoWidget.Tpo -c -o grapher-CairoWidget.o `test -f 'CairoWidget.cxx' || echo '$(srcdir)/'`CairoWidget.cxx -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='CairoWidget.cxx' object='grapher-CairoWidget.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-CairoWidget.o `test -f 'CairoWidget.cxx' || echo '$(srcdir)/'`CairoWidget.cxx grapher-CairoWidget.obj: CairoWidget.cxx @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-CairoWidget.obj -MD -MP -MF $(DEPDIR)/grapher-CairoWidget.Tpo -c -o grapher-CairoWidget.obj `if test -f 'CairoWidget.cxx'; then $(CYGPATH_W) 'CairoWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/CairoWidget.cxx'; fi` -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='CairoWidget.cxx' object='grapher-CairoWidget.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-CairoWidget.obj `if test -f 'CairoWidget.cxx'; then $(CYGPATH_W) 'CairoWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/CairoWidget.cxx'; fi` @@ -341,7 +375,7 @@ tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ + set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -349,29 +383,34 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ + test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique + $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -392,13 +431,17 @@ distdir: $(DISTFILES) if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @@ -429,6 +472,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -449,6 +493,8 @@ dvi-am: html: html-am +html-am: + info: info-am info-am: @@ -457,18 +503,28 @@ install-data-am: install-dvi: install-dvi-am +install-dvi-am: + install-exec-am: install-binPROGRAMS install-html: install-html-am +install-html-am: + install-info: install-info-am +install-info-am: + install-man: install-pdf: install-pdf-am +install-pdf-am: + install-ps: install-ps-am +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-am @@ -505,6 +561,7 @@ uninstall-am: uninstall-binPROGRAMS mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-binPROGRAMS + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx index 8b72f93b..1c865614 100644 --- a/grapher/StapParser.cxx +++ b/grapher/StapParser.cxx @@ -5,7 +5,8 @@ namespace systemtap { -using namespace std; + using namespace std; + using namespace std::tr1; vector commaSplit(const string& inStr, size_t pos = 0) { @@ -28,13 +29,13 @@ vector commaSplit(const string& inStr, size_t pos = 0) return result; } - void StapParser::parseData(std::tr1::shared_ptr gdata, + void StapParser::parseData(shared_ptr gdata, double time, const string& dataString) { std::istringstream stream(dataString); - std::tr1::shared_ptr > dblptr; - std::tr1::shared_ptr > strptr; - dblptr = std::tr1::dynamic_pointer_cast >(gdata); + shared_ptr > dblptr; + shared_ptr > strptr; + dblptr = dynamic_pointer_cast >(gdata); if (dblptr) { double data; @@ -51,132 +52,153 @@ vector commaSplit(const string& inStr, size_t pos = 0) } } -bool StapParser::ioCallback(Glib::IOCondition ioCondition) -{ - using namespace std; - if ((ioCondition & Glib::IO_IN) == 0) - return true; - char buf[256]; - ssize_t bytes_read = 0; - bytes_read = read(0, buf, sizeof(buf) - 1); - if (bytes_read <= 0) - { - _win.hide(); - return true; - } - buf[bytes_read] = '\0'; - _buffer += buf; - string::size_type ret = string::npos; - while ((ret = _buffer.find('\n')) != string::npos) + size_t findTaggedValue(const string& src, const char* tag, string& result) + { + size_t found; + if ((found = src.find(tag)) != string::npos) + result = src.substr(strlen(tag)); + return found; + } + + bool StapParser::ioCallback(Glib::IOCondition ioCondition) { - Glib::ustring dataString(_buffer, 0, ret); - if (dataString[0] == '%') + using namespace std; + if ((ioCondition & Glib::IO_IN) == 0) + return true; + char buf[256]; + ssize_t bytes_read = 0; + bytes_read = read(0, buf, sizeof(buf) - 1); + if (bytes_read <= 0) + { + _win.hide(); + return true; + } + buf[bytes_read] = '\0'; + _buffer += buf; + string::size_type ret = string::npos; + while ((ret = _buffer.find('\n')) != string::npos) { + Glib::ustring dataString(_buffer, 0, ret); + // %DataSet and %CSV declare a data set; all other statements begin with + // the name of a data set. size_t found; - if ((found = dataString.find("%Title:") == 0)) - { - std::string title = dataString.substr(7); - _widget.setTitle(title); - } - else if ((found = dataString.find("%XAxisTitle:") == 0)) - { - _widget.setXAxisText(dataString.substr(12)); - } - else if ((found = dataString.find("%YAxisTitle:") == 0)) + if (dataString[0] == '%') { - _widget.setYAxisText(dataString.substr(12)); - } - else if ((found = dataString.find("%YMax:") == 0)) - { - double ymax; - std::istringstream stream(dataString.substr(6)); - stream >> ymax; - // _gdata->scale = ymax; - } - else if ((found = dataString.find("%DataSet:") == 0)) - { - std::string setName; - int hexColor; - double scale; - std::string style; - std::istringstream stream(dataString.substr(9)); - stream >> setName >> scale >> std::hex >> hexColor - >> style; - if (style == "bar" || style == "dot") + if ((found = dataString.find("%DataSet:") == 0)) { - std::tr1::shared_ptr > - dataSet(new GraphData); - if (style == "dot") - dataSet->style = GraphDataBase::DOT; - dataSet->color[0] = (hexColor >> 16) / 255.0; - dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; - dataSet->color[2] = (hexColor & 0xff) / 255.0; - dataSet->scale = scale; - _dataSets.insert(std::make_pair(setName, dataSet)); - _widget.addGraphData(dataSet); + std::string setName; + int hexColor; + double scale; + std::string style; + std::istringstream stream(dataString.substr(9)); + stream >> setName >> scale >> std::hex >> hexColor + >> style; + if (style == "bar" || style == "dot") + { + shared_ptr > + dataSet(new GraphData); + if (style == "dot") + dataSet->style = GraphDataBase::DOT; + dataSet->color[0] = (hexColor >> 16) / 255.0; + dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; + dataSet->color[2] = (hexColor & 0xff) / 255.0; + dataSet->scale = scale; + _dataSets.insert(std::make_pair(setName, dataSet)); + _widget.addGraphData(dataSet); + } + else if (style == "discreet") + { + shared_ptr > + dataSet(new GraphData); + dataSet->style = GraphDataBase::EVENT; + dataSet->color[0] = (hexColor >> 16) / 255.0; + dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; + dataSet->color[2] = (hexColor & 0xff) / 255.0; + dataSet->scale = scale; + _dataSets.insert(std::make_pair(setName, dataSet)); + _widget.addGraphData(dataSet); + } } - else if (style == "discreet") + else if ((found = dataString.find("%CSV:") == 0)) { - std::tr1::shared_ptr > - dataSet(new GraphData); - dataSet->style = GraphDataBase::EVENT; - dataSet->color[0] = (hexColor >> 16) / 255.0; - dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; - dataSet->color[2] = (hexColor & 0xff) / 255.0; - dataSet->scale = scale; - _dataSets.insert(std::make_pair(setName, dataSet)); - _widget.addGraphData(dataSet); + vector tokens = commaSplit(dataString, found + 5); + for (vector::iterator tokIter = tokens.begin(), + e = tokens.end(); + tokIter != e; + ++tokIter) + { + DataMap::iterator setIter = _dataSets.find(*tokIter); + if (setIter != _dataSets.end()) + _csv.elements + .push_back(CSVData::Element(*tokIter, + setIter->second)); + } } - } - else if ((found = dataString.find("%CSV:") == 0)) - { - vector tokens = commaSplit(dataString, found + 5); - for (vector::iterator tokIter = tokens.begin(), - e = tokens.end(); - tokIter != e; - ++tokIter) + else { - DataMap::iterator setIter = _dataSets.find(*tokIter); - if (setIter != _dataSets.end()) - _csv.elements - .push_back(CSVData::Element(*tokIter, - setIter->second)); - } - } - } - else - { - if (!_csv.elements.empty()) - { - vector tokens = commaSplit(dataString); - int i = 0; - double time; - vector::iterator tokIter = tokens.begin(); - std::istringstream timeStream(*tokIter++); - timeStream >> time; - for (vector::iterator e = tokens.end(); - tokIter != e; - ++tokIter, ++i) - { - parseData(_csv.elements[i].second, time, *tokIter); + cerr << "Unknown declaration " << dataString << endl; } } else { - std::string dataSet; - double time; - string data; std::istringstream stream(dataString); - stream >> dataSet >> time >> data; - DataMap::iterator itr = _dataSets.find(dataSet); + string setName; + stream >> setName; + DataMap::iterator itr = _dataSets.find(setName); if (itr != _dataSets.end()) { - parseData(itr->second, time, data); + shared_ptr gdata = itr->second; + string decl; + // Hack: scan from the beginning of dataString again + if (findTaggedValue(dataString, "%Title", decl) + != string::npos) + { + gdata->title = decl; + } + else if (findTaggedValue(dataString, "%XAxisTitle:", decl) + != string::npos) + { + gdata->xAxisText = decl; + } + else if (findTaggedValue(dataString, "%YAxisTitle:", decl) + != string::npos) + { + gdata->yAxisText = decl; + } + else if ((found = dataString.find("%YMax:")) != string::npos) + { + double ymax; + std::istringstream stream(dataString.substr(found)); + stream >> ymax; + gdata->scale = ymax; + } + + if (!_csv.elements.empty()) + { + vector tokens = commaSplit(dataString); + int i = 0; + double time; + vector::iterator tokIter = tokens.begin(); + std::istringstream timeStream(*tokIter++); + timeStream >> time; + for (vector::iterator e = tokens.end(); + tokIter != e; + ++tokIter, ++i) + { + parseData(_csv.elements[i].second, time, *tokIter); + } + } + else + { + double time; + string data; + stream >> time >> data; + parseData(itr->second, time, data); + } } } + _buffer.erase(0, ret + 1); } - _buffer.erase(0, ret + 1); + return true; } - return true; -} } diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx index 26e5b9b2..a0d35017 100644 --- a/grapher/grapher.cxx +++ b/grapher/grapher.cxx @@ -40,9 +40,6 @@ GrapherWindow::GrapherWindow() { set_title("systemtap grapher"); add(m_Box); - w.setExtents(0.0, 1.0, 5.0, 0.0); - w.setLineWidth(2); - //Create actions for menus and toolbars: diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 737849dc..7358bd2c 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.10.2 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -17,8 +18,9 @@ # Makefile.am --- automake input file for systemtap testsuite VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c @@ -42,6 +44,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = SOURCES = DEJATOOL = $(PACKAGE) ACLOCAL = @ACLOCAL@ @@ -141,15 +144,15 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ - cd $(srcdir) && $(AUTOMAKE) --foreign \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -165,9 +168,10 @@ $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENC $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(srcdir) && $(AUTOCONF) + $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): tags: TAGS TAGS: @@ -229,6 +233,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -248,6 +253,8 @@ dvi-am: html: html-am +html-am: + info: info-am info-am: @@ -256,18 +263,28 @@ install-data-am: install-dvi: install-dvi-am +install-dvi-am: + install-exec-am: install-html: install-html-am +install-html-am: + install-info: install-info-am +install-info-am: + install-man: install-pdf: install-pdf-am +install-pdf-am: + install-ps: install-ps-am +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-am @@ -290,7 +307,7 @@ ps-am: uninstall-am: -.MAKE: install-am install-strip +.MAKE: check-am install-am install-strip .PHONY: all all-am all-local am--refresh check check-DEJAGNU check-am \ check-local clean clean-generic clean-local distclean \ @@ -323,6 +340,7 @@ check-local: installcheck: site.exp -$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU RUNTESTFLAGS="$(RUNTESTFLAGS) --tool_opts \'install $(TOOL_OPTS)\'" if test -n "$(DEJAZILLA)"; then mail $(DEJAZILLA) < systemtap.sum; fi + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/testsuite/aclocal.m4 b/testsuite/aclocal.m4 index a249a8e6..a237cb5a 100644 --- a/testsuite/aclocal.m4 +++ b/testsuite/aclocal.m4 @@ -1,7 +1,7 @@ -# generated automatically by aclocal 1.10.2 -*- Autoconf -*- +# generated automatically by aclocal 1.11 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -31,10 +31,10 @@ To do so, use the procedure documented by the package, typically `autoreconf'.]) # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.10' +[am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.10.2], [], +m4_if([$1], [1.11], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -50,7 +50,7 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.10.2])dnl +[AM_AUTOMAKE_VERSION([1.11])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) @@ -110,14 +110,14 @@ am_aux_dir=`cd $ac_aux_dir && pwd` # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 8 +# serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- @@ -130,6 +130,7 @@ AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' @@ -146,13 +147,13 @@ fi])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2008 Free Software Foundation, Inc. +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 13 +# serial 16 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. @@ -169,7 +170,7 @@ fi])]) # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.60])dnl +[AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl @@ -220,8 +221,8 @@ AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) -AM_PROG_INSTALL_SH -AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. @@ -229,24 +230,37 @@ AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES(OBJC)], - [define([AC_PROG_OBJC], - defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header @@ -269,7 +283,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -280,7 +294,14 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. @@ -307,27 +328,38 @@ AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 4 +# serial 5 +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], -[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) - dnl maintainer-mode is disabled by default - AC_ARG_ENABLE(maintainer-mode, -[ --enable-maintainer-mode enable make rules and dependencies not useful +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful (and sometimes confusing) to the casual installer], - USE_MAINTAINER_MODE=$enableval, - USE_MAINTAINER_MODE=no) + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) - AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE - AC_SUBST(MAINT)dnl + AC_SUBST([MAINT])dnl ] ) @@ -335,14 +367,14 @@ AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 5 +# serial 6 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ @@ -359,7 +391,14 @@ AC_SUBST($1)]) AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " @@ -430,14 +469,14 @@ AC_DEFUN([_AM_IF_OPTION], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 4 +# serial 5 # AM_SANITY_CHECK # --------------- @@ -446,16 +485,29 @@ AC_DEFUN([AM_SANITY_CHECK], # Just in case sleep 1 echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` + set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ @@ -508,18 +560,25 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006 Free Software Foundation, Inc. +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. +# serial 2 + # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. diff --git a/testsuite/configure b/testsuite/configure index 09db931f..6199a3c9 100755 --- a/testsuite/configure +++ b/testsuite/configure @@ -1787,7 +1787,7 @@ ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -am__api_version='1.10' +am__api_version='1.11' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -1887,16 +1887,33 @@ $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + { { $as_echo "$as_me:$LINENO: error: unsafe absolute working directory name" >&5 +$as_echo "$as_me: error: unsafe absolute working directory name" >&2;} + { (exit 1); exit 1; }; };; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + { { $as_echo "$as_me:$LINENO: error: unsafe srcdir value: \`$srcdir'" >&5 +$as_echo "$as_me: error: unsafe srcdir value: \`$srcdir'" >&2;} + { (exit 1); exit 1; }; };; +esac + # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` + set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ @@ -1940,7 +1957,14 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " @@ -1950,6 +1974,115 @@ else $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + { $as_echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then @@ -2132,108 +2265,6 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} - -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:$LINENO: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:$LINENO: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. @@ -2246,6 +2277,7 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + { $as_echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. @@ -2420,6 +2452,7 @@ LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs + if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 diff --git a/testsuite/systemtap.examples/general/grapher.stp b/testsuite/systemtap.examples/general/grapher.stp index 26d35aca..9079cb40 100644 --- a/testsuite/systemtap.examples/general/grapher.stp +++ b/testsuite/systemtap.examples/general/grapher.stp @@ -2,11 +2,13 @@ probe begin { -printf ("%%Title:CPU utilization\n"); -printf ("%%XAxisTitle:Time\n"); -printf ("%%YAxisTitle:Percent\n"); printf ("%%DataSet:cpu 100 00ff00 bar\n"); printf ("%%DataSet:kbd 75 ff0000 discreet\n"); +printf ("%%DataSet:pty 50 0000ff discreet\n"); +printf ("cpu %%Title:CPU utilization\n"); +printf ("cpu %%XAxisTitle:Time\n"); +printf ("cpu %%YAxisTitle:Percent\n"); + } # CPU utilization @@ -31,3 +33,11 @@ probe kernel.function("kbd_event") { if ($event_type == 1 && $value) printf("kbd %d %d\n", gettimeofday_ms(), $event_code) } + +probe kernel.function("pty_write") { + if (count > 0) + printf("pty %d %.5s\n", gettimeofday_ms(), buf) +} + + + -- cgit From 601f4c5a4be6f5a52b56fd8620faf765b63b1a07 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 28 Jul 2009 11:57:27 +0200 Subject: Install yum-utils when yumdownloader is missing first in stapprep.sh. * doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh: Check whether yumdownloader is already available and install yum-utils if not. --- doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh b/doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh index 6905c9cc..3c6bf785 100755 --- a/doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh +++ b/doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh @@ -26,6 +26,10 @@ if [ "$NEEDED" != "" ]; then echo -e "Need to install the following packages:\n$NEEDED" if [ `id -u` = "0" ]; then #attempt download and install DIR=`mktemp -d` || exit 1 + if [ ! -x /usr/bin/yumdownloader ]; then + echo "Need to first install yum-utils for yumdownloader" + yum install -y yum-utils + fi yumdownloader --enablerepo="*debuginfo*" $NEEDED --destdir=$DIR check_error $? "problem downloading rpm(s) $NEEDED" rpm --force -ivh $DIR/*.rpm -- cgit From e25bf3cd072c937fd6235e206e98b082769aa1bb Mon Sep 17 00:00:00 2001 From: David Smith Date: Tue, 28 Jul 2009 14:40:41 -0500 Subject: Improves functionality on rawhide (2.6.31-rcX) kernels. * runtime/transport/ring_buffer.c (struct _stp_iterator): Renamed from _stp_ring_buffer_data. (_stp_data_open_trace): Uses _stp_iterator. (_stp_data_release_trace): Ditto. (_stp_ring_buffer_empty_cpu): Ditto. (_stp_ring_buffer_empty): Ditto. (_stp_ring_buffer_consume): Ditto. (_stp_tracing_wait_pipe): Ditto. (_stp_peek_next_event): Ditto. (_stp_find_next_event): Ditto. (_stp_data_read_trace): Ditto. (_stp_data_write_reserve): Ditto. --- runtime/transport/ring_buffer.c | 178 +++++++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 65 deletions(-) diff --git a/runtime/transport/ring_buffer.c b/runtime/transport/ring_buffer.c index 3af1bf7d..39b79e10 100644 --- a/runtime/transport/ring_buffer.c +++ b/runtime/transport/ring_buffer.c @@ -18,12 +18,14 @@ struct _stp_data_entry { * Trace iterator - used by printout routines who present trace * results to users and which routines might sleep, etc: */ -struct _stp_ring_buffer_data { +struct _stp_iterator { #if 0 struct trace_array *tr; struct tracer *trace; void *private; +#endif int cpu_file; +#if 0 struct mutex mutex; #endif struct ring_buffer_iter *buffer_iter[NR_CPUS]; @@ -44,10 +46,19 @@ struct _stp_ring_buffer_data { #endif }; +/* In bulk mode, we need 1 'struct _stp_iterator' for each cpu. In + * 'normal' mode, we only need 1 'struct _stp_iterator' (since all + * output is sent through 1 file). */ +#ifdef STP_BULKMODE +#define NR_ITERS NR_CPUS +#else +#define NR_ITERS 1 +#endif + struct _stp_relay_data_type { enum _stp_transport_state transport_state; struct ring_buffer *rb; - struct _stp_ring_buffer_data rb_data; + struct _stp_iterator iter[NR_ITERS]; cpumask_var_t trace_reader_cpumask; struct timer_list timer; int overwrite_flag; @@ -99,7 +110,10 @@ fail: static int _stp_data_open_trace(struct inode *inode, struct file *file) { - int cpu_file = (int)(long) inode->i_private; + struct _stp_iterator *iter = inode->i_private; +#ifdef STP_BULKMODE + int cpu_file = iter->cpu_file; +#endif /* We only allow for one reader per cpu */ dbug_trans(1, "trace attach\n"); @@ -123,10 +137,11 @@ static int _stp_data_open_trace(struct inode *inode, struct file *file) static int _stp_data_release_trace(struct inode *inode, struct file *file) { - int cpu_file = (int)(long) inode->i_private; + struct _stp_iterator *iter = inode->i_private; + dbug_trans(1, "trace detach\n"); #ifdef STP_BULKMODE - cpumask_clear_cpu(cpu_file, _stp_relay_data.trace_reader_cpumask); + cpumask_clear_cpu(iter->cpu_file, _stp_relay_data.trace_reader_cpumask); #else cpumask_clear(_stp_relay_data.trace_reader_cpumask); #endif @@ -176,10 +191,14 @@ _stp_event_to_user(struct ring_buffer_event *event, char __user *ubuf, return cnt; } -static int _stp_ring_buffer_empty_cpu(int cpu) +static int _stp_ring_buffer_empty_cpu(struct _stp_iterator *iter) { - if (_stp_relay_data.rb_data.buffer_iter[cpu]) { - if (ring_buffer_iter_empty(_stp_relay_data.rb_data.buffer_iter[cpu])) + int cpu; + +#ifdef STP_BULKMODE + cpu = iter->cpu_file; + if (iter->buffer_iter[cpu]) { + if (ring_buffer_iter_empty(iter->buffer_iter[cpu])) return 1; } else { @@ -187,39 +206,56 @@ static int _stp_ring_buffer_empty_cpu(int cpu) return 1; } return 0; +#else + for_each_possible_cpu(cpu) { + if (iter->buffer_iter[cpu]) { + if (!ring_buffer_iter_empty(iter->buffer_iter[cpu])) + return 0; + } + else { + if (!ring_buffer_empty_cpu(_stp_relay_data.rb, cpu)) + return 0; + } + } + return 1; +#endif } static int _stp_ring_buffer_empty(void) { + struct _stp_iterator *iter; #ifdef STP_BULKMODE - return _stp_ring_buffer_empty_cpu(_stp_relay_data.rb_data.cpu); -#else int cpu; + for_each_possible_cpu(cpu) { - if (! _stp_ring_buffer_empty_cpu(cpu)) + iter = &_stp_relay_data.iter[cpu]; + if (! _stp_ring_buffer_empty_cpu(iter)) return 0; } return 1; +#else + iter = &_stp_relay_data.iter[0]; + return _stp_ring_buffer_empty_cpu(iter); #endif } -static void _stp_ring_buffer_iterator_increment(void) +static void _stp_ring_buffer_iterator_increment(struct _stp_iterator *iter) { - if (_stp_relay_data.rb_data.buffer_iter[_stp_relay_data.rb_data.cpu]) { - ring_buffer_read(_stp_relay_data.rb_data.buffer_iter[_stp_relay_data.rb_data.cpu], NULL); - } + if (iter->buffer_iter[iter->cpu]) + ring_buffer_read(iter->buffer_iter[iter->cpu], NULL); } -static void _stp_ring_buffer_consume(void) +static void _stp_ring_buffer_consume(struct _stp_iterator *iter) { - _stp_ring_buffer_iterator_increment(); - ring_buffer_consume(_stp_relay_data.rb, _stp_relay_data.rb_data.cpu, - &_stp_relay_data.rb_data.ts); + _stp_ring_buffer_iterator_increment(iter); + ring_buffer_consume(_stp_relay_data.rb, iter->cpu, &iter->ts); } static ssize_t _stp_tracing_wait_pipe(struct file *filp) { - if (_stp_ring_buffer_empty()) { + struct _stp_iterator *iter = filp->private_data; + + if (_stp_ring_buffer_empty_cpu(iter)) { if ((filp->f_flags & O_NONBLOCK)) { dbug_trans(1, "returning -EAGAIN\n"); return -EAGAIN; @@ -237,33 +273,32 @@ static ssize_t _stp_tracing_wait_pipe(struct file *filp) return 1; } -static struct ring_buffer_event *_stp_peek_next_event(int cpu, u64 *ts) +static struct ring_buffer_event * +_stp_peek_next_event(struct _stp_iterator *iter, int cpu, u64 *ts) { - if (_stp_relay_data.rb_data.buffer_iter[cpu]) - return ring_buffer_iter_peek(_stp_relay_data.rb_data.buffer_iter[cpu], ts); + if (iter->buffer_iter[cpu]) + return ring_buffer_iter_peek(iter->buffer_iter[cpu], ts); else return ring_buffer_peek(_stp_relay_data.rb, cpu, ts); } /* Find the next real event */ -static struct ring_buffer_event *_stp_find_next_event(int cpu_file) +static struct ring_buffer_event * +_stp_find_next_event(struct _stp_iterator *iter) { struct ring_buffer_event *event; + int cpu_file = iter->cpu_file; #ifdef STP_BULKMODE /* * If we are in a per_cpu trace file, don't bother by iterating over * all cpus and peek directly. */ - if (_stp_ring_buffer_empty_cpu(cpu_file)) + if (ring_buffer_iter_empty(iter->buffer_iter[cpu_file])) return NULL; - event = _stp_peek_next_event(cpu_file, &_stp_relay_data.rb_data.ts); - _stp_relay_data.rb_data.cpu = cpu_file; + event = _stp_peek_next_event(iter, cpu_file, &iter->ts); + iter->cpu = cpu_file; -#if 0 - if (event) - _stp_ring_buffer_iterator_increment(); -#endif return event; #else struct ring_buffer_event *next = NULL; @@ -272,10 +307,13 @@ static struct ring_buffer_event *_stp_find_next_event(int cpu_file) int cpu; for_each_possible_cpu(cpu) { - if (_stp_ring_buffer_empty_cpu(cpu)) + if (iter->buffer_iter[cpu] == NULL) + continue; + + if (ring_buffer_iter_empty(iter->buffer_iter[cpu])) continue; - event = _stp_peek_next_event(cpu, &ts); + event = _stp_peek_next_event(iter, cpu, &ts); /* * Pick the event with the smallest timestamp: @@ -287,12 +325,8 @@ static struct ring_buffer_event *_stp_find_next_event(int cpu_file) } } - _stp_relay_data.rb_data.cpu = next_cpu; - _stp_relay_data.rb_data.ts = next_ts; -#if 0 - if (next) - _stp_ring_buffer_iterator_increment(); -#endif + iter->cpu = next_cpu; + iter->ts = next_ts; return next; #endif } @@ -307,8 +341,10 @@ _stp_data_read_trace(struct file *filp, char __user *ubuf, { ssize_t sret; struct ring_buffer_event *event; - int cpu_file = (int)(long) filp->private_data; -#ifndef STP_BULKMODE + struct _stp_iterator *iter = filp->private_data; +#ifdef STP_BULKMODE + int cpu_file = iter->cpu_file; +#else int cpu; #endif @@ -320,36 +356,34 @@ _stp_data_read_trace(struct file *filp, char __user *ubuf, goto out; #ifdef STP_BULKMODE - _stp_relay_data.rb_data.buffer_iter[cpu_file] + iter->buffer_iter[cpu_file] = ring_buffer_read_start(_stp_relay_data.rb, cpu_file); + if (iter->buffer_iter[cpu_file] == NULL) { + dbug_trans(0, "buffer_iter[%d] was NULL\n", cpu_file); + goto out; + } #else for_each_possible_cpu(cpu) { - _stp_relay_data.rb_data.buffer_iter[cpu] + iter->buffer_iter[cpu] = ring_buffer_read_start(_stp_relay_data.rb, cpu); } #endif - _stp_relay_data.rb_data.ts = 0; + iter->ts = 0; dbug_trans(0, "iterator(s) started\n"); - /* stop when tracing is finished */ - if (_stp_ring_buffer_empty()) { - sret = 0; - goto out; - } - if (cnt >= PAGE_SIZE) cnt = PAGE_SIZE - 1; dbug_trans(1, "sret = %lu\n", (unsigned long)sret); sret = 0; - while ((event = _stp_find_next_event(cpu_file)) != NULL) { + while ((event = _stp_find_next_event(iter)) != NULL) { ssize_t len; len = _stp_event_to_user(event, ubuf, cnt); if (len <= 0) break; - _stp_ring_buffer_consume(); + _stp_ring_buffer_consume(iter); dbug_trans(1, "event consumed\n"); ubuf += len; cnt -= len; @@ -360,16 +394,16 @@ _stp_data_read_trace(struct file *filp, char __user *ubuf, out: #ifdef STP_BULKMODE - if (_stp_relay_data.rb_data.buffer_iter[cpu_file]) { - ring_buffer_read_finish(_stp_relay_data.rb_data.buffer_iter[cpu_file]); - _stp_relay_data.rb_data.buffer_iter[cpu_file] = NULL; + if (iter->buffer_iter[cpu_file]) { + ring_buffer_read_finish(iter->buffer_iter[cpu_file]); + iter->buffer_iter[cpu_file] = NULL; dbug_trans(0, "iterator finished\n"); } #else for_each_possible_cpu(cpu) { - if (_stp_relay_data.rb_data.buffer_iter[cpu]) { - ring_buffer_read_finish(_stp_relay_data.rb_data.buffer_iter[cpu]); - _stp_relay_data.rb_data.buffer_iter[cpu] = NULL; + if (iter->buffer_iter[cpu]) { + ring_buffer_read_finish(iter->buffer_iter[cpu]); + iter->buffer_iter[cpu] = NULL; } } dbug_trans(0, "iterator(s) finished\n"); @@ -381,11 +415,13 @@ out: static unsigned int _stp_data_poll_trace(struct file *filp, poll_table *poll_table) { + struct _stp_iterator *iter = filp->private_data; + dbug_trans(1, "entry\n"); - if (! _stp_ring_buffer_empty()) + if (! _stp_ring_buffer_empty_cpu(iter)) return POLLIN | POLLRDNORM; poll_wait(filp, &_stp_poll_wait, poll_table); - if (! _stp_ring_buffer_empty()) + if (! _stp_ring_buffer_empty_cpu(iter)) return POLLIN | POLLRDNORM; dbug_trans(1, "exit\n"); @@ -446,6 +482,7 @@ _stp_data_write_reserve(size_t size_request, void **entry) #endif if (unlikely(! event)) { int cpu; + struct _stp_iterator *iter; dbug_trans(0, "event = NULL (%p)?\n", event); if (! _stp_relay_data.overwrite_flag) { @@ -457,15 +494,20 @@ _stp_data_write_reserve(size_t size_request, void **entry) * full, take a event out of the buffer and consume it * (throw it away). This should make room for the new * data. */ +#ifdef STP_BULKMODE cpu = raw_smp_processor_id(); - event = _stp_find_next_event(cpu); + iter = &_stp_relay_data.iter[cpu]; +#else + iter = &_stp_relay_data.iter[0]; +#endif + event = _stp_find_next_event(iter); if (event) { ssize_t len; sde = (struct _stp_data_entry *)ring_buffer_event_data(event); if (sde->len < size_request) size_request = sde->len; - _stp_ring_buffer_consume(); + _stp_ring_buffer_consume(iter); /* Try to reserve again. */ #ifdef STAPCONF_RING_BUFFER_FLAGS @@ -595,14 +637,20 @@ static int _stp_transport_data_fs_init(void) __stp_entry[cpu]->d_inode->i_uid = _stp_uid; __stp_entry[cpu]->d_inode->i_gid = _stp_gid; - __stp_entry[cpu]->d_inode->i_private = (void *)(long)cpu; + __stp_entry[cpu]->d_inode->i_private = &_stp_relay_data.iter[cpu]; #ifndef STP_BULKMODE - if (cpu != 0) - break; + break; #endif } +#ifdef STP_BULKMODE + for_each_possible_cpu(cpu) { + _stp_relay_data.iter[cpu].cpu_file = cpu; + _stp_relay_data.iter[cpu].cpu = cpu; + } +#endif + dbug_trans(1, "returning 0...\n"); _stp_relay_data.transport_state = STP_TRANSPORT_INITIALIZED; return 0; -- cgit From fc7e606e053159fad715883ccee2d99324c32f1a Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 28 Jul 2009 17:26:55 -0400 Subject: PR10453: Fix crash.exp not to refer removed file * systemtap.base/crash.exp: Use command-line script instead of removed script file. --- testsuite/systemtap.base/crash.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/systemtap.base/crash.exp b/testsuite/systemtap.base/crash.exp index 9c3e5e05..59c8dadd 100644 --- a/testsuite/systemtap.base/crash.exp +++ b/testsuite/systemtap.base/crash.exp @@ -5,7 +5,7 @@ if {![installtest_p]} { untested $test; return } if {![file exists $env(CRASH_LIBDIR)/staplog.so]} { untested "$test - no staplog.so"; return } # Load a test script -spawn stap $srcdir/$subdir/testlog.stp -m testlog +spawn stap -e {probe begin {print("HelloWorld\n")}} -m testlog expect { -timeout 120 "HelloWorld\r\n" { -- cgit From a0c0ed1c030d8e812eed19b096c626b7ce233358 Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Tue, 28 Jul 2009 19:50:24 -0400 Subject: PR6978: support $$parms for process.syscall * tapset-utrace.cxx (visit_target_symbol_arg): Handle $$parms. * testsuite/systemtap.base/utrace_p4.exp: Add test case. * testsuite/systemtap.base/utrace_p5.exp: Ditto. --- tapset-utrace.cxx | 125 ++++++++++++++++++++++----------- testsuite/systemtap.base/utrace_p4.exp | 19 +++++ testsuite/systemtap.base/utrace_p5.exp | 22 ++++++ 3 files changed, 125 insertions(+), 41 deletions(-) diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index ec20282a..a3a4ca3d 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -407,54 +407,97 @@ utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol* e) void utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { - string argnum_s = e->base_name.substr(4,e->base_name.length()-4); - int argnum = lex_cast(argnum_s); - if (flags != UDPF_SYSCALL) - throw semantic_error ("only \"process(PATH_OR_PID).syscall\" support $argN.", e->tok); + throw semantic_error ("only \"process(PATH_OR_PID).syscall\" support $argN or $$parms.", e->tok); - if (e->components.size() > 0) + if (e->base_name == "$$parms") { - switch (e->components[0].first) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("utrace target variable '$argN' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("utrace target variable '$argN' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of utrace target variable '$argN'", - e->tok); - break; - } - } + // copy from tracepoint + print_format* pf = new print_format; + token* pf_tok = new token(*e->tok); + pf_tok->content = "sprintf"; + pf->tok = pf_tok; + pf->print_to_stream = false; + pf->print_with_format = true; + pf->print_with_delim = false; + pf->print_with_newline = false; + pf->print_char = false; + + target_symbol_seen = true; + + for (unsigned i = 0; i < 6; ++i) + { + if (i > 0) + pf->raw_components += " "; + pf->raw_components += "$arg" + lex_cast(i+1); + target_symbol *tsym = new target_symbol; + tsym->tok = e->tok; + tsym->base_name = "$arg" + lex_cast(i+1); + tsym->saved_conversion_error = 0; + pf->raw_components += "=%#x"; //FIXME: missing type info + + functioncall* n = new functioncall; //same as the following + n->tok = e->tok; + n->function = "_utrace_syscall_arg"; + n->referent = 0; + literal_number *num = new literal_number(i); + num->tok = e->tok; + n->args.push_back(num); + + pf->args.push_back(n); + } + pf->components = print_format::string_to_components(pf->raw_components); + + provide (pf); + } + else // $argN + { + string argnum_s = e->base_name.substr(4,e->base_name.length()-4); + int argnum = lex_cast(argnum_s); + + if (e->components.size() > 0) + { + switch (e->components[0].first) + { + case target_symbol::comp_literal_array_index: + throw semantic_error("utrace target variable '$argN' may not be used as array", + e->tok); + break; + case target_symbol::comp_struct_member: + throw semantic_error("utrace target variable '$argN' may not be used as a structure", + e->tok); + break; + default: + throw semantic_error ("invalid use of utrace target variable '$argN'", + e->tok); + break; + } + } - // FIXME: max argnument number should not be hardcoded. - if (argnum < 1 || argnum > 6) - throw semantic_error ("invalid syscall argument number (1-6)", e->tok); + // FIXME: max argnument number should not be hardcoded. + if (argnum < 1 || argnum > 6) + throw semantic_error ("invalid syscall argument number (1-6)", e->tok); - bool lvalue = is_active_lvalue(e); - if (lvalue) - throw semantic_error("utrace '$argN' variable is read-only", e->tok); + bool lvalue = is_active_lvalue(e); + if (lvalue) + throw semantic_error("utrace '$argN' variable is read-only", e->tok); - // Remember that we've seen a target variable. - target_symbol_seen = true; + // Remember that we've seen a target variable. + target_symbol_seen = true; - // We're going to substitute a synthesized '_utrace_syscall_arg' - // function call for the '$argN' reference. - functioncall* n = new functioncall; - n->tok = e->tok; - n->function = "_utrace_syscall_arg"; - n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session + // We're going to substitute a synthesized '_utrace_syscall_arg' + // function call for the '$argN' reference. + functioncall* n = new functioncall; + n->tok = e->tok; + n->function = "_utrace_syscall_arg"; + n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - literal_number *num = new literal_number(argnum - 1); - num->tok = e->tok; - n->args.push_back(num); + literal_number *num = new literal_number(argnum - 1); + num->tok = e->tok; + n->args.push_back(num); - provide (n); + provide (n); + } } void @@ -542,12 +585,12 @@ utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e) if (e->addressof) throw semantic_error("cannot take address of utrace variable", e->tok); - if (e->base_name.substr(0,4) == "$arg") + if (e->base_name.substr(0,4) == "$arg" || e->base_name == "$$parms") visit_target_symbol_arg(e); else if (e->base_name == "$syscall" || e->base_name == "$return") visit_target_symbol_context(e); else - throw semantic_error ("invalid target symbol for utrace probe, $syscall, $return or $argN expected", + throw semantic_error ("invalid target symbol for utrace probe, $syscall, $return, $argN or $$parms expected", e->tok); } diff --git a/testsuite/systemtap.base/utrace_p4.exp b/testsuite/systemtap.base/utrace_p4.exp index 8d323a8a..c76503cb 100644 --- a/testsuite/systemtap.base/utrace_p4.exp +++ b/testsuite/systemtap.base/utrace_p4.exp @@ -10,6 +10,7 @@ set begin_script {"probe process(\"/bin/ls\").begin { print(\"ls begin\") }"} set end_script {"probe process(\"/bin/ls\").end { print(\"ls end\") }"} set syscall_script {"probe process(\"/bin/ls\").syscall { printf(\"|%d\", \$syscall) }"} +set syscall_parms_script {"probe process(\"/bin/ls\").syscall { printf(\"|%s\", \$\$parms) }"} set syscall_return_script {"probe process(\"/bin/ls\").syscall.return { printf(\"|%d\", \$syscall) }"} set thread_begin_script {"probe process(\"/bin/ls\").thread.begin { print(\"ls thread.begin\") }"} set thread_end_script {"probe process(\"/bin/ls\").thread.end { print(\"ls thread.end\") }"} @@ -18,6 +19,7 @@ set all_begin_script {"probe process.begin { print(\"begin\") }"} set pid_begin_script {"probe process(123).begin { print(\"123 begin\") }"} set pid_end_script {"probe process(123).end { print(\"123 end\") }"} set pid_syscall_script {"probe process(123).syscall { printf(\"|%d\", \$syscall) }"} +set pid_parms_script {"probe process(123).syscall { printf(\"|%s\", \$\$parms) }"} set pid_syscall_return_script {"probe process(123).syscall.return { printf(\"|%d\", \$syscall) }"} set pid_thread_begin_script {"probe process(123).thread.begin { print(\"123 thread.begin\") }"} set pid_thread_end_script {"probe process(123).thread.end { print(\"123 thread.end\") }"} @@ -129,3 +131,20 @@ if {![utrace_p]} { # Try compiling an system-wide begin script stap_compile $TEST_NAME 1 $all_begin_script } + +set TEST_NAME "UTRACE_P4_08" +if {![utrace_p]} { + untested "$TEST_NAME : no kernel utrace support found" +} else { + # Try compiling a syscall parms script using a path + stap_compile $TEST_NAME 1 $syscall_parms_script +} + +set TEST_NAME "UTRACE_P4_09" +if {![utrace_p]} { + untested "$TEST_NAME : no kernel utrace support found" +} else { + # Try compiling a syscall parms script using a pid + stap_compile $TEST_NAME 1 $pid_parms_script +} + diff --git a/testsuite/systemtap.base/utrace_p5.exp b/testsuite/systemtap.base/utrace_p5.exp index 3d432dc3..7062bc0d 100644 --- a/testsuite/systemtap.base/utrace_p5.exp +++ b/testsuite/systemtap.base/utrace_p5.exp @@ -89,6 +89,18 @@ set bz6841_script { } set bz6841_script_output ".+ issues syscall \\d+ times\r\n" +set syscall_parms_script { + global syscall_parms_string + probe begin { printf("systemtap starting probe\n") } + probe process.syscall { syscall_parms_string = $$parms exit() } + probe end { printf("systemtap ending probe\n") + printf("%s\n",syscall_parms_string) + delete syscall_parms_string + } +} +set syscall_parms_script_output "(.+arg\[1-6\]=0x\[0-9a-f\]+)+\r\n" + + # Set up our own copy of /bin/cat, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating # a cross-device link. We can't use 'ln -s' here, since the kernel @@ -202,5 +214,15 @@ if {![utrace_p]} { -e $bz6841_script } +set TEST_NAME "UTRACE_P5_08" +if {![utrace_p]} { + untested "$TEST_NAME : no kernel utrace support found" +} elseif {![installtest_p]} { + untested "$TEST_NAME" +} else { + set script [format $syscall_parms_script "%s"] + stap_run $TEST_NAME no_load $syscall_parms_script_output -e $script +} + # Cleanup exec rm -f $exepath $multi_exepath -- cgit From a7999c82a3355eb5a68a14a57ffebe5e688d8413 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 29 Jul 2009 12:13:40 -0700 Subject: Break up dwarf_var_expanding_visitor::visit_target_symbol This just refactors large chunks of visit_target_symbol into a couple of smaller functions. * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol_context): New (dwarf_var_expanding_visitor::visit_target_symbol_saved_return): New (dwarf_var_expanding_visitor::visit_target_symbol): Call the new ones --- tapsets.cxx | 740 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 379 insertions(+), 361 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 9186ba82..4ddf4160 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1699,6 +1699,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): q(q), scope_die(sd), addr(a), add_block(NULL), add_probe(NULL), visited(false) {} + void visit_target_symbol_saved_return (target_symbol* e); + void visit_target_symbol_context (target_symbol* e); void visit_target_symbol (target_symbol* e); void visit_cast_op (cast_op* e); }; @@ -1758,415 +1760,431 @@ var_expanding_visitor::visit_assignment (assignment* e) void -dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) -{ - assert(e->base_name.size() > 0 && e->base_name[0] == '$'); - visited = true; - - bool lvalue = is_active_lvalue(e); - if (lvalue && !q.sess.guru_mode) - throw semantic_error("write to target variable not permitted", e->tok); - - // See if we need to generate a new probe to save/access function - // parameters from a return probe. PR 1382. - if (q.has_return - && e->base_name != "$return" // not the special return-value variable handled below - && e->base_name != "$$return") // nor the other special variable handled below +dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e) +{ + // Get the full name of the target symbol. + stringstream ts_name_stream; + e->print(ts_name_stream); + string ts_name = ts_name_stream.str(); + + // Check and make sure we haven't already seen this target + // variable in this return probe. If we have, just return our + // last replacement. + map::iterator i = return_ts_map.find(ts_name); + if (i != return_ts_map.end()) { - if (lvalue) - throw semantic_error("write to target variable not permitted in .return probes", e->tok); - - // Get the full name of the target symbol. - stringstream ts_name_stream; - e->print(ts_name_stream); - string ts_name = ts_name_stream.str(); - - // Check and make sure we haven't already seen this target - // variable in this return probe. If we have, just return our - // last replacement. - map::iterator i = return_ts_map.find(ts_name); - if (i != return_ts_map.end()) - { - provide (i->second); - return; - } - - // We've got to do several things here to handle target - // variables in return probes. + provide (i->second); + return; + } - // (1) Synthesize two global arrays. One is the cache of the - // target variable and the other contains a thread specific - // nesting level counter. The arrays will look like - // this: - // - // _dwarf_tvar_{name}_{num} - // _dwarf_tvar_{name}_{num}_ctr + // We've got to do several things here to handle target + // variables in return probes. - string aname = (string("_dwarf_tvar_") - + e->base_name.substr(1) - + "_" + lex_cast(tick++)); - vardecl* vd = new vardecl; - vd->name = aname; - vd->tok = e->tok; - q.sess.globals.push_back (vd); + // (1) Synthesize two global arrays. One is the cache of the + // target variable and the other contains a thread specific + // nesting level counter. The arrays will look like + // this: + // + // _dwarf_tvar_{name}_{num} + // _dwarf_tvar_{name}_{num}_ctr + + string aname = (string("_dwarf_tvar_") + + e->base_name.substr(1) + + "_" + lex_cast(tick++)); + vardecl* vd = new vardecl; + vd->name = aname; + vd->tok = e->tok; + q.sess.globals.push_back (vd); + + string ctrname = aname + "_ctr"; + vd = new vardecl; + vd->name = ctrname; + vd->tok = e->tok; + q.sess.globals.push_back (vd); + + // (2) Create a new code block we're going to insert at the + // beginning of this probe to get the cached value into a + // temporary variable. We'll replace the target variable + // reference with the temporary variable reference. The code + // will look like this: + // + // _dwarf_tvar_tid = tid() + // _dwarf_tvar_{name}_{num}_tmp + // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, + // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] + // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, + // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--] + // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]) + // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid] + + // (2a) Synthesize the tid temporary expression, which will look + // like this: + // + // _dwarf_tvar_tid = tid() + symbol* tidsym = new symbol; + tidsym->name = string("_dwarf_tvar_tid"); + tidsym->tok = e->tok; - string ctrname = aname + "_ctr"; - vd = new vardecl; - vd->name = ctrname; - vd->tok = e->tok; - q.sess.globals.push_back (vd); - - // (2) Create a new code block we're going to insert at the - // beginning of this probe to get the cached value into a - // temporary variable. We'll replace the target variable - // reference with the temporary variable reference. The code - // will look like this: - // - // _dwarf_tvar_tid = tid() - // _dwarf_tvar_{name}_{num}_tmp - // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, - // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] - // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, - // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--] - // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]) - // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid] - - // (2a) Synthesize the tid temporary expression, which will look - // like this: - // - // _dwarf_tvar_tid = tid() - symbol* tidsym = new symbol; - tidsym->name = string("_dwarf_tvar_tid"); - tidsym->tok = e->tok; - - if (add_block == NULL) - { - add_block = new block; - add_block->tok = e->tok; - - // Synthesize a functioncall to grab the thread id. - functioncall* fc = new functioncall; - fc->tok = e->tok; - fc->function = string("tid"); - - // Assign the tid to '_dwarf_tvar_tid'. - assignment* a = new assignment; - a->tok = e->tok; - a->op = "="; - a->left = tidsym; - a->right = fc; - - expr_statement* es = new expr_statement; - es->tok = e->tok; - es->value = a; - add_block->statements.push_back (es); - } + if (add_block == NULL) + { + add_block = new block; + add_block->tok = e->tok; - // (2b) Synthesize an array reference and assign it to a - // temporary variable (that we'll use as replacement for the - // target variable reference). It will look like this: - // - // _dwarf_tvar_{name}_{num}_tmp - // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, - // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] - - arrayindex* ai_tvar_base = new arrayindex; - ai_tvar_base->tok = e->tok; - - symbol* sym = new symbol; - sym->name = aname; - sym->tok = e->tok; - ai_tvar_base->base = sym; - - ai_tvar_base->indexes.push_back(tidsym); - - // We need to create a copy of the array index in its current - // state so we can have 2 variants of it (the original and one - // that post-decrements the second index). - arrayindex* ai_tvar = new arrayindex; - arrayindex* ai_tvar_postdec = new arrayindex; - *ai_tvar = *ai_tvar_base; - *ai_tvar_postdec = *ai_tvar_base; - - // Synthesize the - // "_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]" used as the - // second index into the array. - arrayindex* ai_ctr = new arrayindex; - ai_ctr->tok = e->tok; - - sym = new symbol; - sym->name = ctrname; - sym->tok = e->tok; - ai_ctr->base = sym; - ai_ctr->indexes.push_back(tidsym); - ai_tvar->indexes.push_back(ai_ctr); - - symbol* tmpsym = new symbol; - tmpsym->name = aname + "_tmp"; - tmpsym->tok = e->tok; + // Synthesize a functioncall to grab the thread id. + functioncall* fc = new functioncall; + fc->tok = e->tok; + fc->function = string("tid"); + // Assign the tid to '_dwarf_tvar_tid'. assignment* a = new assignment; a->tok = e->tok; a->op = "="; - a->left = tmpsym; - a->right = ai_tvar; + a->left = tidsym; + a->right = fc; expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; - add_block->statements.push_back (es); + } - // (2c) Add a post-decrement to the second array index and - // delete the array value. It will look like this: - // - // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, - // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--] - - post_crement* pc = new post_crement; - pc->tok = e->tok; - pc->op = "--"; - pc->operand = ai_ctr; - ai_tvar_postdec->indexes.push_back(pc); - - delete_statement* ds = new delete_statement; - ds->tok = e->tok; - ds->value = ai_tvar_postdec; - - add_block->statements.push_back (ds); - - // (2d) Delete the counter value if it is 0. It will look like - // this: - // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]) - // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid] - - ds = new delete_statement; - ds->tok = e->tok; - ds->value = ai_ctr; - - unary_expression *ue = new unary_expression; - ue->tok = e->tok; - ue->op = "!"; - ue->operand = ai_ctr; - - if_statement *ifs = new if_statement; - ifs->tok = e->tok; - ifs->condition = ue; - ifs->thenblock = ds; - ifs->elseblock = NULL; - - add_block->statements.push_back (ifs); - - // (3) We need an entry probe that saves the value for us in the - // global array we created. Create the entry probe, which will - // look like this: - // - // probe kernel.function("{function}") { - // _dwarf_tvar_tid = tid() - // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, - // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] - // = ${param} - // } - - if (add_probe == NULL) + // (2b) Synthesize an array reference and assign it to a + // temporary variable (that we'll use as replacement for the + // target variable reference). It will look like this: + // + // _dwarf_tvar_{name}_{num}_tmp + // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, + // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] + + arrayindex* ai_tvar_base = new arrayindex; + ai_tvar_base->tok = e->tok; + + symbol* sym = new symbol; + sym->name = aname; + sym->tok = e->tok; + ai_tvar_base->base = sym; + + ai_tvar_base->indexes.push_back(tidsym); + + // We need to create a copy of the array index in its current + // state so we can have 2 variants of it (the original and one + // that post-decrements the second index). + arrayindex* ai_tvar = new arrayindex; + arrayindex* ai_tvar_postdec = new arrayindex; + *ai_tvar = *ai_tvar_base; + *ai_tvar_postdec = *ai_tvar_base; + + // Synthesize the + // "_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]" used as the + // second index into the array. + arrayindex* ai_ctr = new arrayindex; + ai_ctr->tok = e->tok; + + sym = new symbol; + sym->name = ctrname; + sym->tok = e->tok; + ai_ctr->base = sym; + ai_ctr->indexes.push_back(tidsym); + ai_tvar->indexes.push_back(ai_ctr); + + symbol* tmpsym = new symbol; + tmpsym->name = aname + "_tmp"; + tmpsym->tok = e->tok; + + assignment* a = new assignment; + a->tok = e->tok; + a->op = "="; + a->left = tmpsym; + a->right = ai_tvar; + + expr_statement* es = new expr_statement; + es->tok = e->tok; + es->value = a; + + add_block->statements.push_back (es); + + // (2c) Add a post-decrement to the second array index and + // delete the array value. It will look like this: + // + // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, + // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--] + + post_crement* pc = new post_crement; + pc->tok = e->tok; + pc->op = "--"; + pc->operand = ai_ctr; + ai_tvar_postdec->indexes.push_back(pc); + + delete_statement* ds = new delete_statement; + ds->tok = e->tok; + ds->value = ai_tvar_postdec; + + add_block->statements.push_back (ds); + + // (2d) Delete the counter value if it is 0. It will look like + // this: + // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]) + // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid] + + ds = new delete_statement; + ds->tok = e->tok; + ds->value = ai_ctr; + + unary_expression *ue = new unary_expression; + ue->tok = e->tok; + ue->op = "!"; + ue->operand = ai_ctr; + + if_statement *ifs = new if_statement; + ifs->tok = e->tok; + ifs->condition = ue; + ifs->thenblock = ds; + ifs->elseblock = NULL; + + add_block->statements.push_back (ifs); + + // (3) We need an entry probe that saves the value for us in the + // global array we created. Create the entry probe, which will + // look like this: + // + // probe kernel.function("{function}") { + // _dwarf_tvar_tid = tid() + // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, + // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] + // = ${param} + // } + + if (add_probe == NULL) + { + add_probe = new probe; + add_probe->tok = e->tok; + + // We need the name of the current probe point, minus the + // ".return" (or anything after it, such as ".maxactive(N)"). + // Create a new probe point, copying all the components, + // stopping when we see the ".return" component. + probe_point* pp = new probe_point; + for (unsigned c = 0; c < q.base_loc->components.size(); c++) { - add_probe = new probe; - add_probe->tok = e->tok; - - // We need the name of the current probe point, minus the - // ".return" (or anything after it, such as ".maxactive(N)"). - // Create a new probe point, copying all the components, - // stopping when we see the ".return" component. - probe_point* pp = new probe_point; - for (unsigned c = 0; c < q.base_loc->components.size(); c++) - { - if (q.base_loc->components[c]->functor == "return") - break; - else - pp->components.push_back(q.base_loc->components[c]); - } - pp->tok = e->tok; - pp->optional = q.base_loc->optional; - add_probe->locations.push_back(pp); - - add_probe->body = new block; - add_probe->body->tok = e->tok; - - // Synthesize a functioncall to grab the thread id. - functioncall* fc = new functioncall; - fc->tok = e->tok; - fc->function = string("tid"); - - // Assign the tid to '_dwarf_tvar_tid'. - assignment* a = new assignment; - a->tok = e->tok; - a->op = "="; - a->left = tidsym; - a->right = fc; - - expr_statement* es = new expr_statement; - es->tok = e->tok; - es->value = a; - add_probe->body = new block(add_probe->body, es); - - vardecl* vd = new vardecl; - vd->tok = e->tok; - vd->name = tidsym->name; - vd->type = pe_long; - vd->set_arity(0); - add_probe->locals.push_back(vd); - } + if (q.base_loc->components[c]->functor == "return") + break; + else + pp->components.push_back(q.base_loc->components[c]); + } + pp->tok = e->tok; + pp->optional = q.base_loc->optional; + add_probe->locations.push_back(pp); - // Save the value, like this: - // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, - // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] - // = ${param} - arrayindex* ai_tvar_preinc = new arrayindex; - *ai_tvar_preinc = *ai_tvar_base; + add_probe->body = new block; + add_probe->body->tok = e->tok; - pre_crement* preinc = new pre_crement; - preinc->tok = e->tok; - preinc->op = "++"; - preinc->operand = ai_ctr; - ai_tvar_preinc->indexes.push_back(preinc); + // Synthesize a functioncall to grab the thread id. + functioncall* fc = new functioncall; + fc->tok = e->tok; + fc->function = string("tid"); - a = new assignment; + // Assign the tid to '_dwarf_tvar_tid'. + assignment* a = new assignment; a->tok = e->tok; a->op = "="; - a->left = ai_tvar_preinc; - a->right = e; + a->left = tidsym; + a->right = fc; - es = new expr_statement; + expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; - add_probe->body = new block(add_probe->body, es); - // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to - // our parent so it can be used as a substitute for the target - // symbol. - provide (tmpsym); - - // (5) Remember this replacement since we might be able to reuse - // it later if the same return probe references this target - // symbol again. - return_ts_map[ts_name] = tmpsym; - return; + vardecl* vd = new vardecl; + vd->tok = e->tok; + vd->name = tidsym->name; + vd->type = pe_long; + vd->set_arity(0); + add_probe->locals.push_back(vd); } - if (e->base_name == "$$vars" - || e->base_name == "$$parms" - || e->base_name == "$$locals" - || (q.has_return && (e->base_name == "$$return"))) - { - Dwarf_Die *scopes; - if (dwarf_getscopes_die (scope_die, &scopes) == 0) - return; + // Save the value, like this: + // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid, + // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]] + // = ${param} + arrayindex* ai_tvar_preinc = new arrayindex; + *ai_tvar_preinc = *ai_tvar_base; + + pre_crement* preinc = new pre_crement; + preinc->tok = e->tok; + preinc->op = "++"; + preinc->operand = ai_ctr; + ai_tvar_preinc->indexes.push_back(preinc); + + a = new assignment; + a->tok = e->tok; + a->op = "="; + a->left = ai_tvar_preinc; + a->right = e; + + es = new expr_statement; + es->tok = e->tok; + es->value = a; + + add_probe->body = new block(add_probe->body, es); + + // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to + // our parent so it can be used as a substitute for the target + // symbol. + provide (tmpsym); + + // (5) Remember this replacement since we might be able to reuse + // it later if the same return probe references this target + // symbol again. + return_ts_map[ts_name] = tmpsym; +} - if (e->addressof) - throw semantic_error("cannot take address of context variable", e->tok); - target_symbol *tsym = new target_symbol; - print_format* pf = new print_format; +void +dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) +{ + Dwarf_Die *scopes; + if (dwarf_getscopes_die (scope_die, &scopes) == 0) + return; - // Convert $$parms to sprintf of a list of parms and active local vars - // which we recursively evaluate + target_symbol *tsym = new target_symbol; + print_format* pf = new print_format; - // NB: we synthesize a new token here rather than reusing - // e->tok, because print_format::print likes to use - // its tok->content. - token* pf_tok = new token; - pf_tok->location = e->tok->location; - pf_tok->type = tok_identifier; - pf_tok->content = "sprint"; + // Convert $$parms to sprintf of a list of parms and active local vars + // which we recursively evaluate - pf->tok = pf_tok; - pf->print_to_stream = false; - pf->print_with_format = true; - pf->print_with_delim = false; - pf->print_with_newline = false; - pf->print_char = false; + // NB: we synthesize a new token here rather than reusing + // e->tok, because print_format::print likes to use + // its tok->content. + token* pf_tok = new token; + pf_tok->location = e->tok->location; + pf_tok->type = tok_identifier; + pf_tok->content = "sprint"; - if (q.has_return && (e->base_name == "$$return")) - { - tsym->tok = e->tok; - tsym->base_name = "$return"; + pf->tok = pf_tok; + pf->print_to_stream = false; + pf->print_with_format = true; + pf->print_with_delim = false; + pf->print_with_newline = false; + pf->print_char = false; - // Ignore any variable that isn't accessible. - tsym->saved_conversion_error = 0; - expression *texp = tsym; - texp = require (texp); // NB: throws nothing ... - if (tsym->saved_conversion_error) // ... but this is how we know it happened. - { + if (q.has_return && (e->base_name == "$$return")) + { + tsym->tok = e->tok; + tsym->base_name = "$return"; + + // Ignore any variable that isn't accessible. + tsym->saved_conversion_error = 0; + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... + if (tsym->saved_conversion_error) // ... but this is how we know it happened. + { - } - else - { - pf->raw_components += "return"; - pf->raw_components += "=%#x "; - pf->args.push_back(texp); - } } else { - // non-.return probe: support $$parms, $$vars, $$locals - Dwarf_Die result; - if (dwarf_child (&scopes[0], &result) == 0) - do + pf->raw_components += "return"; + pf->raw_components += "=%#x "; + pf->args.push_back(texp); + } + } + else + { + // non-.return probe: support $$parms, $$vars, $$locals + Dwarf_Die result; + if (dwarf_child (&scopes[0], &result) == 0) + do + { + switch (dwarf_tag (&result)) { - switch (dwarf_tag (&result)) - { - case DW_TAG_variable: - if (e->base_name == "$$parms") - continue; - break; - case DW_TAG_formal_parameter: - if (e->base_name == "$$locals") - continue; - break; - - default: - continue; - } + case DW_TAG_variable: + if (e->base_name == "$$parms") + continue; + break; + case DW_TAG_formal_parameter: + if (e->base_name == "$$locals") + continue; + break; + + default: + continue; + } - const char *diename = dwarf_diename (&result); - if (! diename) continue; + const char *diename = dwarf_diename (&result); + if (! diename) continue; - tsym->tok = e->tok; - tsym->base_name = "$"; - tsym->base_name += diename; + tsym->tok = e->tok; + tsym->base_name = "$"; + tsym->base_name += diename; - // Ignore any variable that isn't accessible. - tsym->saved_conversion_error = 0; - expression *texp = tsym; - texp = require (texp); // NB: throws nothing ... - if (tsym->saved_conversion_error) // ... but this is how we know it happened. - { - if (q.sess.verbose>2) - { - for (semantic_error *c = tsym->saved_conversion_error; - c != 0; - c = c->chain) { - clog << "variable location problem: " << c->what() << endl; - } - } - - pf->raw_components += diename; - pf->raw_components += "=? "; - } - else + // Ignore any variable that isn't accessible. + tsym->saved_conversion_error = 0; + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... + if (tsym->saved_conversion_error) // ... but this is how we know it happened. + { + if (q.sess.verbose>2) { - pf->raw_components += diename; - pf->raw_components += "=%#x "; - pf->args.push_back(texp); + for (semantic_error *c = tsym->saved_conversion_error; + c != 0; + c = c->chain) { + clog << "variable location problem: " << c->what() << endl; + } } + + pf->raw_components += diename; + pf->raw_components += "=? "; } - while (dwarf_siblingof (&result, &result) == 0); - } + else + { + pf->raw_components += diename; + pf->raw_components += "=%#x "; + pf->args.push_back(texp); + } + } + while (dwarf_siblingof (&result, &result) == 0); + } - pf->components = print_format::string_to_components(pf->raw_components); - provide (pf); + pf->components = print_format::string_to_components(pf->raw_components); + provide (pf); +} + + +void +dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) +{ + assert(e->base_name.size() > 0 && e->base_name[0] == '$'); + visited = true; + + bool lvalue = is_active_lvalue(e); + if (lvalue && !q.sess.guru_mode) + throw semantic_error("write to target variable not permitted", e->tok); + + // See if we need to generate a new probe to save/access function + // parameters from a return probe. PR 1382. + if (q.has_return + && e->base_name != "$return" // not the special return-value variable handled below + && e->base_name != "$$return") // nor the other special variable handled below + { + if (lvalue) + throw semantic_error("write to target variable not permitted in .return probes", e->tok); + + visit_target_symbol_saved_return(e); + return; + } + + if (e->base_name == "$$vars" + || e->base_name == "$$parms" + || e->base_name == "$$locals" + || (q.has_return && (e->base_name == "$$return"))) + { + if (lvalue) + throw semantic_error("cannot write to context variable", e->tok); + + if (e->addressof) + throw semantic_error("cannot take address of context variable", e->tok); + visit_target_symbol_context(e); return; } -- cgit From 8c39844b59f49526240c65b81a79eef311fe4177 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 29 Jul 2009 12:35:29 -0700 Subject: Use a real session flag for -L Rather than relying on 'unoptimized' to tell us that the listing mode should print the variables too, this adds an explicit listing_mode_vars. * session.h (systemtap_session): Add listing_mode_vars * main.cxx (main): Set s.listing_mode_vars appropriately. (printscript): Use the new flag for deciding whether to print locals --- main.cxx | 23 +++++++++++++---------- session.h | 1 + 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/main.cxx b/main.cxx index 9dc658ff..6a9444de 100644 --- a/main.cxx +++ b/main.cxx @@ -193,16 +193,17 @@ printscript(systemtap_session& s, ostream& o) { o << pp; // Print the locals for -L mode only - if (s.unoptimized) { - for (unsigned j=0; jlocals.size(); j++) - { - o << " "; - vardecl* v = p->locals[j]; - v->printsig (o); - } - // Print arguments of probe if there - p->printargs(o); - } + if (s.listing_mode_vars) + { + for (unsigned j=0; jlocals.size(); j++) + { + o << " "; + vardecl* v = p->locals[j]; + v->printsig (o); + } + // Print arguments of probe if there + p->printargs(o); + } o << endl; seen.insert (pp); } @@ -377,6 +378,7 @@ main (int argc, char * const argv []) s.unoptimized = false; s.suppress_warnings = false; s.listing_mode = false; + s.listing_mode_vars = false; #ifdef ENABLE_PROLOGUES s.prologue_searching = true; @@ -665,6 +667,7 @@ main (int argc, char * const argv []) break; case 'L': + s.listing_mode_vars = true; s.unoptimized = true; // This causes retention of variables for listing_mode case 'l': diff --git a/session.h b/session.h index e68cd6df..cd12f495 100644 --- a/session.h +++ b/session.h @@ -103,6 +103,7 @@ struct systemtap_session bool keep_tmpdir; bool guru_mode; bool listing_mode; + bool listing_mode_vars; bool bulk_mode; bool unoptimized; bool merge; -- cgit From 0a98fd42f87ef9217917931bd8a47e272a5664ce Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 29 Jul 2009 14:07:37 -0700 Subject: Enable variable listing (-L) for dwarf probes All $target variables and their C-types are now printed in -L mode. * tapsets.cxx (dwarf_derived_probe::dwarf_derived_probe): Save the local arguments while we still have the dwflpp open. (dwarf_derived_probe::saveargs): New (dwarf_derived_probe::printargs): New --- tapsets.cxx | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tapsets.cxx b/tapsets.cxx index 4ddf4160..a93c2860 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -351,6 +351,10 @@ struct dwarf_derived_probe: public derived_probe void join_group (systemtap_session& s); void emit_probe_local_init(translator_output * o); + string args; + void saveargs(Dwarf_Die* scope_die); + void printargs(std::ostream &o) const; + // Pattern registration helpers. static void register_statement_variants(match_node * root, dwarf_builder * dw); @@ -2046,6 +2050,7 @@ dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) Dwarf_Die *scopes; if (dwarf_getscopes_die (scope_die, &scopes) == 0) return; + auto_free free_scopes(scopes); target_symbol *tsym = new target_symbol; print_format* pf = new print_format; @@ -2637,6 +2642,10 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, } // else - null scope_die - $target variables will produce an error during translate phase + // Save the local variables for listing mode + if (q.sess.listing_mode_vars) + saveargs(scope_die); + // Reset the sole element of the "locations" vector as a // "reverse-engineered" form of the incoming (q.base_loc) probe // point. This allows a user to see what function / file / line @@ -2701,6 +2710,66 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, } +static bool dwarf_type_name(Dwarf_Die& type_die, string& c_type); + +void +dwarf_derived_probe::saveargs(Dwarf_Die* scope_die) +{ + Dwarf_Die *scopes; + if (!null_die(scope_die) && dwarf_getscopes_die (scope_die, &scopes) == 0) + return; + auto_free free_scopes(scopes); + + stringstream argstream; + string type_name; + Dwarf_Attribute type_attr; + Dwarf_Die type_die; + + if (has_return && + dwarf_attr_integrate (scope_die, DW_AT_type, &type_attr) && + dwarf_formref_die (&type_attr, &type_die) && + dwarf_type_name(type_die, type_name)) + argstream << " $return:" << type_name; + + Dwarf_Die arg; + if (dwarf_child (&scopes[0], &arg) == 0) + do + { + switch (dwarf_tag (&arg)) + { + case DW_TAG_variable: + case DW_TAG_formal_parameter: + break; + + default: + continue; + } + + const char *arg_name = dwarf_diename (&arg); + if (!arg_name) + continue; + + type_name.clear(); + if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr) || + !dwarf_formref_die (&type_attr, &type_die) || + !dwarf_type_name(type_die, type_name)) + continue; + + argstream << " $" << arg_name << ":" << type_name; + } + while (dwarf_siblingof (&arg, &arg) == 0); + + args = argstream.str(); +} + + +void +dwarf_derived_probe::printargs(std::ostream &o) const +{ + o << args; +} + + void dwarf_derived_probe::register_statement_variants(match_node * root, dwarf_builder * dw) -- cgit From 9ace370f8b31f8c1e1b27c272f13f4322841d1a3 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 29 Jul 2009 14:34:32 -0700 Subject: Enable variable listing (-L) for uprobes All $target variables and their C-types are now printed in -L mode. * tapsets.cxx (uprobe_derived_probe::uprobe_derived_probe): Save the local arguments while we still have the dwflpp open. (uprobe_derived_probe::saveargs): New (uprobe_derived_probe::printargs): New --- tapsets.cxx | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tapsets.cxx b/tapsets.cxx index a93c2860..81fe3d0c 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -394,6 +394,10 @@ struct uprobe_derived_probe: public derived_probe Dwarf_Addr addr, bool return_p); + string args; + void saveargs(Dwarf_Die* scope_die); + void printargs(std::ostream &o) const; + void printsig (std::ostream &o) const; void join_group (systemtap_session& s); }; @@ -4100,6 +4104,10 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function, } // else - null scope_die - $target variables will produce an error during translate phase + // Save the local variables for listing mode + if (q.sess.listing_mode_vars) + saveargs(scope_die); + // Reset the sole element of the "locations" vector as a // "reverse-engineered" form of the incoming (q.base_loc) probe // point. This allows a user to see what function / file / line @@ -4173,6 +4181,67 @@ uprobe_derived_probe::uprobe_derived_probe (probe *base, } +void +uprobe_derived_probe::saveargs(Dwarf_Die* scope_die) +{ + // same as dwarf_derived_probe::saveargs + + Dwarf_Die *scopes; + if (!null_die(scope_die) && dwarf_getscopes_die (scope_die, &scopes) == 0) + return; + auto_free free_scopes(scopes); + + stringstream argstream; + string type_name; + Dwarf_Attribute type_attr; + Dwarf_Die type_die; + + if (return_p && + dwarf_attr_integrate (scope_die, DW_AT_type, &type_attr) && + dwarf_formref_die (&type_attr, &type_die) && + dwarf_type_name(type_die, type_name)) + argstream << " $return:" << type_name; + + Dwarf_Die arg; + if (dwarf_child (&scopes[0], &arg) == 0) + do + { + switch (dwarf_tag (&arg)) + { + case DW_TAG_variable: + case DW_TAG_formal_parameter: + break; + + default: + continue; + } + + const char *arg_name = dwarf_diename (&arg); + if (!arg_name) + continue; + + type_name.clear(); + if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr) || + !dwarf_formref_die (&type_attr, &type_die) || + !dwarf_type_name(type_die, type_name)) + continue; + + argstream << " $" << arg_name << ":" << type_name; + } + while (dwarf_siblingof (&arg, &arg) == 0); + + args = argstream.str(); +} + + +void +uprobe_derived_probe::printargs(std::ostream &o) const +{ + // same as dwarf_derived_probe::printargs + o << args; +} + + void uprobe_derived_probe::printsig (ostream& o) const { -- cgit From 8823ee6a3fcf47adbb7314c6fd560e6c952c4705 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 29 Jul 2009 23:26:26 +0200 Subject: Remove unused result_string from ustack.tcl. * testsuite/systemtap.exelib/ustack.tcl: Remove result_string. --- testsuite/systemtap.exelib/ustack.tcl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/testsuite/systemtap.exelib/ustack.tcl b/testsuite/systemtap.exelib/ustack.tcl index b70b8334..a670213a 100644 --- a/testsuite/systemtap.exelib/ustack.tcl +++ b/testsuite/systemtap.exelib/ustack.tcl @@ -1,12 +1,3 @@ -set ::result_string {exe: main=main -exe: main_func=main_func -exe: main_func=main_func -exe: main_func=main_func -lib: lib_main=lib_main -lib: lib_func=lib_func -lib: lib_func=lib_func - lib: lib_func=lib_func} - # Only run on make installcheck if {! [installtest_p]} { untested "ustack-$testname"; return } if {! [utrace_p]} { untested "ustack-$testname"; return } -- cgit From 83ca3872dadc89c5a8155150bf76d5c09890dcc9 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 30 Jul 2009 00:06:59 +0200 Subject: PR10459. Disable all warning messages on -w. * stap.1.in: Document that -w disables all warning messages. * dwflpp.cxx (get_module_dwarf): Only output warning when session suppress_warnings is not set. * translate.cxx (dump_unwindsyms): Likewise. (emit_symbol_data_done): Likewise. * tapsets.cxx (query_module_symtab): Likewise. (read_from_elf_file): Take systemtap_session, check suppress_warnings before emitting warning. (read_from_text_file): Likewise. (get_symtab): Call read_from_elf_file and read_from_text_file with session. --- dwflpp.cxx | 2 +- stap.1.in | 2 +- tapsets.cxx | 44 ++++++++++++++++++++++++++------------------ translate.cxx | 14 +++++++------- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index 01cfddaa..e6e7b471 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -124,7 +124,7 @@ dwflpp::get_module_dwarf(bool required, bool report) if (required) throw semantic_error (msg); - else + else if (! sess.suppress_warnings) cerr << "WARNING: " << msg << "\n"; } } diff --git a/stap.1.in b/stap.1.in index 7736a612..0e7a51f4 100644 --- a/stap.1.in +++ b/stap.1.in @@ -132,7 +132,7 @@ debugging information for $target variables. Unoptimized mode. Disable unused code elision during elaboration. .TP .B \-w -Suppressed warnings mode. Disable warning messages for elided code in user script. +Suppressed warnings mode. Disables all warning messages. .TP .BI \-b Use bulk mode (percpu files) for kernel-to-user data transfer. diff --git a/tapsets.cxx b/tapsets.cxx index 81fe3d0c..2d68ddd4 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -290,8 +290,10 @@ symbol_table void add_symbol(const char *name, bool weak, Dwarf_Addr addr, Dwarf_Addr *high_addr); enum info_status read_symbols(FILE *f, const string& path); - enum info_status read_from_elf_file(const string& path); - enum info_status read_from_text_file(const string& path); + enum info_status read_from_elf_file(const string& path, + const systemtap_session &sess); + enum info_status read_from_text_file(const string& path, + const systemtap_session &sess); enum info_status get_from_elf(); void prepare_section_rejection(Dwfl_Module *mod); bool reject_section(GElf_Word section); @@ -816,10 +818,11 @@ dwarf_query::query_module_symtab() fi = sym_table->get_func_containing_address(addr); if (!fi) { - cerr << "Warning: address " - << hex << addr << dec - << " out of range for module " - << dw.module_name; + if (! sess.suppress_warnings) + cerr << "Warning: address " + << hex << addr << dec + << " out of range for module " + << dw.module_name; return; } if (!null_die(&fi->die)) @@ -828,10 +831,11 @@ dwarf_query::query_module_symtab() // the indicated function, but query_module_dwarf() didn't // match addr to any compilation unit, so addr must be // above that cu's address range. - cerr << "Warning: address " - << hex << addr << dec - << " maps to no known compilation unit in module " - << dw.module_name; + if (! sess.suppress_warnings) + cerr << "Warning: address " + << hex << addr << dec + << " maps to no known compilation unit in module " + << dw.module_name; return; } query_func_info(fi->addr, *fi, this); @@ -3779,7 +3783,8 @@ symbol_table::read_symbols(FILE *f, const string& path) // that gives us raw addresses -- which we need for modules -- whereas // nm provides the address relative to the beginning of the section. enum info_status -symbol_table::read_from_elf_file(const string &path) +symbol_table::read_from_elf_file(const string &path, + const systemtap_session &sess) { FILE *f; string cmd = string("/usr/bin/nm -n --defined-only ") + path; @@ -3794,7 +3799,7 @@ symbol_table::read_from_elf_file(const string &path) enum info_status status = read_symbols(f, path); if (pclose(f) != 0) { - if (status == info_present) + if (status == info_present && ! sess.suppress_warnings) cerr << "Warning: nm cannot read symbol table from " << path; return info_absent; } @@ -3802,13 +3807,15 @@ symbol_table::read_from_elf_file(const string &path) } enum info_status -symbol_table::read_from_text_file(const string& path) +symbol_table::read_from_text_file(const string& path, + const systemtap_session &sess) { FILE *f = fopen(path.c_str(), "r"); if (!f) { - cerr << "Warning: cannot read symbol table from " - << path << " -- " << strerror (errno); + if (! sess.suppress_warnings) + cerr << "Warning: cannot read symbol table from " + << path << " -- " << strerror (errno); return info_absent; } enum info_status status = read_symbols(f, path); @@ -3956,12 +3963,13 @@ module_info::get_symtab(dwarf_query *q) sym_table = new symbol_table(this); if (!elf_path.empty()) { - if (name == TOK_KERNEL && !sess.kernel_symtab_path.empty()) + if (name == TOK_KERNEL && !sess.kernel_symtab_path.empty() + && ! sess.suppress_warnings) cerr << "Warning: reading symbol table from " << elf_path << " -- ignoring " << sess.kernel_symtab_path - << endl ;; + << endl; symtab_status = sym_table->get_from_elf(); } else @@ -3977,7 +3985,7 @@ module_info::get_symtab(dwarf_query *q) else { symtab_status = - sym_table->read_from_text_file(sess.kernel_symtab_path); + sym_table->read_from_text_file(sess.kernel_symtab_path, sess); if (symtab_status == info_present) { sess.sym_kprobes_text_start = diff --git a/translate.cxx b/translate.cxx index 9c901065..f2e04d7d 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4779,7 +4779,7 @@ dump_unwindsyms (Dwfl_Module *m, // likely can't do anything about this; backtraces for the // affected module would just get all icky heuristicy. // So only report in verbose mode. - if (c->session.verbose > 2) + if (c->session.verbose > 2 && ! c->session.suppress_warnings) c->session.print_warning ("No unwind data for " + modname + ", " + dwfl_errmsg (-1)); } @@ -5080,12 +5080,12 @@ emit_symbol_data_done (unwindsym_dump_context *ctx, systemtap_session& s) << ";\n"; // Some nonexistent modules may have been identified with "-d". Note them. - for (set::iterator it = ctx->undone_unwindsym_modules.begin(); - it != ctx->undone_unwindsym_modules.end(); - it ++) - { - s.print_warning ("missing unwind/symbol data for module '" + (*it) + "'"); - } + if (! s.suppress_warnings) + for (set::iterator it = ctx->undone_unwindsym_modules.begin(); + it != ctx->undone_unwindsym_modules.end(); + it ++) + s.print_warning ("missing unwind/symbol data for module '" + + (*it) + "'"); } -- cgit From 8bab68f697a6da72ba67d7034f2acdffbe48f918 Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Thu, 30 Jul 2009 17:04:09 -0400 Subject: dtrace.in: Don't interpret -h -o FILE, just use the filename as is. --- dtrace.in | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/dtrace.in b/dtrace.in index 91885977..168bfb18 100755 --- a/dtrace.in +++ b/dtrace.in @@ -137,6 +137,7 @@ i = 1 build_header = False build_source = False add_typedefs = False +h_ext = '.h' filename = "" while (i < len (sys.argv)): if (sys.argv[i] == "-o"): @@ -148,7 +149,6 @@ while (i < len (sys.argv)): elif (sys.argv[i] == "-h"): build_header = True elif (sys.argv[i] == "-G"): - build_header = True build_source = True elif (sys.argv[i] == "--types"): add_typedefs = True @@ -162,22 +162,23 @@ if (build_header == False and build_source == False): if (filename == ""): if (s_filename != ""): (filename,ext) = os.path.splitext(s_filename) - filename = os.path.basename(filename) else: usage sys.exit(1) else: - (filename,ext) = os.path.splitext(filename) - + if (build_header): + h_ext = "" + else: + (filename,ext) = os.path.splitext(filename) if (build_header): providers = provider() - providers.generate(s_filename, filename + ".h", add_typedefs) -if (build_source): + providers.generate(s_filename, filename + h_ext, add_typedefs) +elif (build_source): (basename,ext) = os.path.splitext(s_filename) basename = os.path.basename(basename) (d,fn) = mkstemp(suffix=".c",prefix=basename) f = open(fn,mode='w') - f.write("#include \"" + filename + ".h\"\nstatic __dtrace () {}\n") + f.write("static __dtrace () {}\n") f.close() - call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"], shell=False) + call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", os.path.basename(filename) + ".o"], shell=False) os.remove(fn) -- cgit From f1312b2c2bc1ec7b0475a251f27a2f75779f4ccb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 30 Jul 2009 19:24:17 -0700 Subject: Relax the type-matching in the cmd_parse13 test Dwarf probes are now printing their $target variables in -L, so we need to handle more than just stap types in the regular expression. --- testsuite/systemtap.base/cmd_parse.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/systemtap.base/cmd_parse.exp b/testsuite/systemtap.base/cmd_parse.exp index c6b098a4..b97d9448 100644 --- a/testsuite/systemtap.base/cmd_parse.exp +++ b/testsuite/systemtap.base/cmd_parse.exp @@ -116,7 +116,7 @@ wait;close spawn stap -L syscall.a* expect { -timeout 60 - -re {(syscall\.a[_a-zA-Z0-9]*(\ [_a-zA-Z0-9\$]+:(string|long|unknown|stats))*\r\n)+} { pass "cmd_parse13" } + -re {(syscall\.a[_a-zA-Z0-9]*(\ [_a-zA-Z0-9\$]+:[^:]+?)+\r\n)+} { pass "cmd_parse13" } timeout {fail "cmd_parse13: unexpected timeout"} eof {fail "cmd_parse13: unexpected EOF"} } -- cgit From 6415dddecb81f59996e422e87e1d3da266d743e8 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 31 Jul 2009 18:46:47 +0200 Subject: PR10458. User actual breakpoint address for [ku]probe[ret]. Setup the pt_regs REG_IP to the actual breakpoint address before entering a probe handler for [ku]probe[ret] (and restore it after returning). This helps getting symbol resolution and backtraces more correct and makes it more conform with other probe handlers like the iutrace and profile timers that also provide pt_regs (which untill now exhibited off-by-one errors while unwinding). * tapsets.cxx (dwarf_derived_probe_group::emit_module_decls): Setup REG_IP correctly before calling enter_kprobe_probe and enter_kretprobe_probe, and restore afterwards. (uprobe_derived_probe_group::emit_module_decls): Likewise for enter_uprobe_probe and enter_uretprobe_probe. (kprobe_derived_probe_group::emit_module_decls): Likewise for enter_kprobe2_probe and enter_kretprobe2_probe. * runtime/unwind/i386.h (arch_unw_init_frame_info): Initialize info->call_frame to zero. * runtime/unwind/x86_64.h (arch_unw_init_frame_info): Likewise. --- runtime/unwind/i386.h | 2 +- runtime/unwind/x86_64.h | 2 +- tapsets.cxx | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/runtime/unwind/i386.h b/runtime/unwind/i386.h index 9f488f07..b19df584 100644 --- a/runtime/unwind/i386.h +++ b/runtime/unwind/i386.h @@ -92,7 +92,7 @@ static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, #endif } - info->call_frame = 1; + info->call_frame = 0; } static inline void arch_unw_init_blocked(struct unwind_frame_info *info) diff --git a/runtime/unwind/x86_64.h b/runtime/unwind/x86_64.h index 3c70f206..8860b8ee 100644 --- a/runtime/unwind/x86_64.h +++ b/runtime/unwind/x86_64.h @@ -107,7 +107,7 @@ static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, /*const*/ struct pt_regs *regs) { info->regs = *regs; - info->call_frame = 1; + info->call_frame = 0; } static inline void arch_unw_init_blocked(struct unwind_frame_info *info) diff --git a/tapsets.cxx b/tapsets.cxx index 2d68ddd4..bd33fb0b 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2986,7 +2986,18 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->line() << "];"; common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp"); s.op->newline() << "c->regs = regs;"; + + // Make it look like the IP is set as it wouldn't have been replaced + // by a breakpoint instruction when calling real probe handler. Reset + // IP regs on return, so we don't confuse kprobes. PR10458 + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);"; + s.op->newline() << "REG_IP(regs) = (unsigned long) inst->addr;"; s.op->newline() << "(*sdp->ph) (c);"; + s.op->newline() << "REG_IP(regs) = kprobes_ip;"; + s.op->newline(-1) << "}"; + common_probe_entryfn_epilogue (s.op); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; @@ -3009,7 +3020,18 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s) common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp"); s.op->newline() << "c->regs = regs;"; s.op->newline() << "c->pi = inst;"; // for assisting runtime's backtrace logic + + // Make it look like the IP is set as it wouldn't have been replaced + // by a breakpoint instruction when calling real probe handler. Reset + // IP regs on return, so we don't confuse kprobes. PR10458 + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);"; + s.op->newline() << "REG_IP(regs) = (unsigned long) inst->rp->kp.addr;"; s.op->newline() << "(*sdp->ph) (c);"; + s.op->newline() << "REG_IP(regs) = kprobes_ip;"; + s.op->newline(-1) << "}"; + common_probe_entryfn_epilogue (s.op); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; @@ -4381,7 +4403,18 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "if (sup->spec_index < 0 ||" << "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen s.op->newline() << "c->regs = regs;"; + + // Make it look like the IP is set as it would in the actual user + // task when calling real probe handler. Reset IP regs on return, so + // we don't confuse uprobes. PR10458 + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->regs);"; + s.op->newline() << "REG_IP(regs) = inst->vaddr;"; s.op->newline() << "(*sups->ph) (c);"; + s.op->newline() << "REG_IP(regs) = uprobes_ip;"; + s.op->newline(-1) << "}"; + common_probe_entryfn_epilogue (s.op); s.op->newline(-1) << "}"; @@ -4393,7 +4426,18 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) << "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen // XXX: kretprobes saves "c->pi = inst;" too s.op->newline() << "c->regs = regs;"; + + // Make it look like the IP is set as it would in the actual user + // task when calling real probe handler. Reset IP regs on return, so + // we don't confuse uprobes. PR10458 + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->regs);"; + s.op->newline() << "REG_IP(regs) = inst->rp->u.vaddr;"; s.op->newline() << "(*sups->ph) (c);"; + s.op->newline() << "REG_IP(regs) = uprobes_ip;"; + s.op->newline(-1) << "}"; + common_probe_entryfn_epilogue (s.op); s.op->newline(-1) << "}"; @@ -4882,7 +4926,18 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->line() << "];"; common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp"); s.op->newline() << "c->regs = regs;"; + + // Make it look like the IP is set as it wouldn't have been replaced + // by a breakpoint instruction when calling real probe handler. Reset + // IP regs on return, so we don't confuse kprobes. PR10458 + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);"; + s.op->newline() << "REG_IP(regs) = (unsigned long) inst->addr;"; s.op->newline() << "(*sdp->ph) (c);"; + s.op->newline() << "REG_IP(regs) = kprobes_ip;"; + s.op->newline(-1) << "}"; + common_probe_entryfn_epilogue (s.op); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; @@ -4905,7 +4960,18 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s) common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp"); s.op->newline() << "c->regs = regs;"; s.op->newline() << "c->pi = inst;"; // for assisting runtime's backtrace logic + + // Make it look like the IP is set as it wouldn't have been replaced + // by a breakpoint instruction when calling real probe handler. Reset + // IP regs on return, so we don't confuse kprobes. PR10458 + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);"; + s.op->newline() << "REG_IP(regs) = (unsigned long) inst->rp->kp.addr;"; s.op->newline() << "(*sdp->ph) (c);"; + s.op->newline() << "REG_IP(regs) = kprobes_ip;"; + s.op->newline(-1) << "}"; + common_probe_entryfn_epilogue (s.op); s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; -- cgit From 793e611dc277b6943100a5f81274961d526f9b02 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 31 Jul 2009 19:54:53 +0200 Subject: Add testcase for PR10458, PR10459 and PR10454. Last test currently disabled because PR10454 is still open. * testsuite/systemtap.context/uprobe_stmt_num.exp: New file. * testsuite/systemtap.context/uprobe_stmt_num.stp: Likewise. * testsuite/systemtap.context/uprobe_stmt_num.c: Likewise. --- testsuite/systemtap.context/uprobe_stmt_num.c | 20 +++++++ testsuite/systemtap.context/uprobe_stmt_num.exp | 78 +++++++++++++++++++++++++ testsuite/systemtap.context/uprobe_stmt_num.stp | 4 ++ 3 files changed, 102 insertions(+) create mode 100644 testsuite/systemtap.context/uprobe_stmt_num.c create mode 100644 testsuite/systemtap.context/uprobe_stmt_num.exp create mode 100644 testsuite/systemtap.context/uprobe_stmt_num.stp diff --git a/testsuite/systemtap.context/uprobe_stmt_num.c b/testsuite/systemtap.context/uprobe_stmt_num.c new file mode 100644 index 00000000..887e572a --- /dev/null +++ b/testsuite/systemtap.context/uprobe_stmt_num.c @@ -0,0 +1,20 @@ +static int +func2 (int x, int y) +{ + return x + y; +} + +static int +func (int arg) +{ + int x = 16; + int y = arg - x; + int z = func2(x, y); + return x + y + z; +} + +int +main (int argc, char *argv[], char *envp[]) +{ + return func(42); +} diff --git a/testsuite/systemtap.context/uprobe_stmt_num.exp b/testsuite/systemtap.context/uprobe_stmt_num.exp new file mode 100644 index 00000000..fbb1126a --- /dev/null +++ b/testsuite/systemtap.context/uprobe_stmt_num.exp @@ -0,0 +1,78 @@ +# Tests whether we can put statement probes on all lines of a function, +# even without debuginfo around (in guru mode currently). PR10454. + +set test "uprobe_stmt_num" + +# Only run on make installcheck and utrace present. +if {! [installtest_p]} { untested "$test"; return } +if {! [utrace_p]} { untested "$test"; return } + +set testpath "$srcdir/$subdir" +set testsrc "$testpath/$test.c" +set testexe "[pwd]/$test" +# We want debug info and no optimization (every line counts). +set testflags "additional_flags=-g additional_flags=-O0" +set teststp "$testpath/$test.stp" + +set res [target_compile $testsrc $testexe executable $testflags] +if { $res != "" } { + verbose "target_compile failed: $res" 2 + fail "unable to compile $testsrc" + return +} + +set cmd [concat stap -c $testexe $teststp] +send_log "cmd: $cmd\n" +catch {eval exec $cmd} output +send_log "cmd output: $output\n" + +# There should be at least 6 lines probes +# Function entry, 4 actual source lines and function exit. +set output_lines [split $output "\n"] +set lines [llength $output_lines] +if { $lines >= 6 } { + pass "$test-run-one" +} else { + fail "$test-run-one ($lines)" +} + +# Expect the same output for next runs +set ::result_string $output + +# Sanity check, just run again... +stap_run3 $test-run-two $testpath/$test.stp -c $testexe + +# create a script based on the given statements, +# probe all of them individually. +set fp [open $test-run-statements.stp "w"] +foreach line $output_lines { + puts $fp "probe process(\"uprobe_stmt_num\").statement($line)" + puts $fp "{" + puts $fp " printf(\"0x%x\\n\", uaddr());" + puts $fp "}" +} +close $fp +stap_run3 $test-run-statements $test-run-statements.stp -c $testexe + +# Now strip away the line info and try again (with -g). +set strip_cmd [list "objcopy" "-R" ".debug_line"] +lappend strip_cmd "$testexe" +send_log "Executing: $strip_cmd\n" +eval exec $strip_cmd + +stap_run3 $test-run-statements-nolines -w -g $test-run-statements.stp -c $testexe + +# XXX Last test still fails. PR10454. +return + +# Now strip away all debuginfo. Since the script doesn't need any it +# should still work. +set strip_cmd [list "strip" "-g"] +lappend strip_cmd "$testexe" +send_log "Executing: $strip_cmd\n" +eval exec $strip_cmd + +stap_run3 $test-run-statements-nodebuginfo -w -g $test-run-statements.stp -c $testexe + +# cleanup +eval exec rm $testexe $test-run-statements.stp diff --git a/testsuite/systemtap.context/uprobe_stmt_num.stp b/testsuite/systemtap.context/uprobe_stmt_num.stp new file mode 100644 index 00000000..c2e8d5ba --- /dev/null +++ b/testsuite/systemtap.context/uprobe_stmt_num.stp @@ -0,0 +1,4 @@ +probe process("uprobe_stmt_num").statement("func@uprobe_stmt_num.c:*") +{ + printf("0x%x\n", uaddr()); +} -- cgit From ce91eebdf6c262a0235bdd2d3ad3acd0805bf02a Mon Sep 17 00:00:00 2001 From: Kent Sebastian Date: Fri, 31 Jul 2009 14:45:10 -0400 Subject: PR10204: Place userspace markers in systemtap itself * cache.cxx (add_to_cache,clean_cache): add static markers * main.cxx (main): likewise * runtime/staprun/common.c (send_request): likewise * runtime/staprun/mainloop.c (stp_main_loop): likewise * runtime/staprun/staprun.c (remove_module): likewise * runtime/staprun/staprun.h: include sdt.h * runtime/staprun/staprun_funcs.c (insert_module): likewise * util.cxx (stap_system): likewise * tapset/stap_staticmarkers.stp: new file --- cache.cxx | 8 ++++++++ main.cxx | 26 ++++++++++++++++++++++++++ runtime/staprun/common.c | 1 + runtime/staprun/mainloop.c | 1 + runtime/staprun/staprun.c | 1 + runtime/staprun/staprun.h | 3 +++ runtime/staprun/staprun_funcs.c | 1 + util.cxx | 4 ++++ 8 files changed, 45 insertions(+) diff --git a/cache.cxx b/cache.cxx index bfe2b527..99b88000 100644 --- a/cache.cxx +++ b/cache.cxx @@ -10,6 +10,7 @@ #include "session.h" #include "cache.h" #include "util.h" +#include "sys/sdt.h" #include #include #include @@ -59,6 +60,7 @@ add_to_cache(systemtap_session& s) } string module_src_path = s.tmpdir + "/" + s.module_name + ".ko"; + STAP_PROBE2(stap, cache__add__module, module_src_path.c_str(), s.hash_path.c_str()); if (s.verbose > 1) clog << "Copying " << module_src_path << " to " << s.hash_path << endl; if (copy_file(module_src_path.c_str(), s.hash_path.c_str()) != 0) @@ -79,6 +81,8 @@ add_to_cache(systemtap_session& s) string module_signature_src_path = module_src_path; module_signature_src_path += ".sgn"; + STAP_PROBE2(stap, cache__add__nss, module_signature_src_path.c_str(), module_signature_dest_path.c_str()); + if (s.verbose > 1) clog << "Copying " << module_signature_src_path << " to " << module_signature_dest_path << endl; if (copy_file(module_signature_src_path.c_str(), module_signature_dest_path.c_str()) != 0) @@ -97,6 +101,7 @@ add_to_cache(systemtap_session& s) c_dest_path.resize(c_dest_path.size() - 3); c_dest_path += ".c"; + STAP_PROBE2(stap, cache__add__source, s.translated_source.c_str(), c_dest_path.c_str()); if (s.verbose > 1) clog << "Copying " << s.translated_source << " to " << c_dest_path << endl; @@ -241,6 +246,8 @@ get_from_cache(systemtap_session& s) clog << "Pass 4: using cached " << s.hash_path << endl; } + STAP_PROBE2(stap, cache__get, c_src_path.c_str(), s.hash_path.c_str()); + return true; } @@ -341,6 +348,7 @@ clean_cache(systemtap_session& s) if ( (r_cache_size / 1024 / 1024) < cache_mb_max) //convert r_cache_size to MiB break; + STAP_PROBE1(stap, cache__clean, (i->path).c_str()); //remove this (*i) cache_entry, add to removed list i->unlink(); r_cache_size -= i->size; diff --git a/main.cxx b/main.cxx index 6a9444de..2c1b1c68 100644 --- a/main.cxx +++ b/main.cxx @@ -21,6 +21,7 @@ #include "coveragedb.h" #include "git_version.h" #include "rpm_finder.h" +#include "sys/sdt.h" #include #include @@ -820,6 +821,8 @@ main (int argc, char * const argv []) // PASS 0: setting up s.verbose = s.perpass_verbose[0]; + STAP_PROBE1(stap, pass0__start, &s); + // For PR1477, we used to override $PATH and $LC_ALL and other stuff // here. We seem to use complete pathnames in @@ -871,12 +874,15 @@ main (int argc, char * const argv []) // and reasonably timely exit. setup_signals(&handle_interrupt); + STAP_PROBE1(stap, pass0__end, &s); + struct tms tms_before; times (& tms_before); struct timeval tv_before; gettimeofday (&tv_before, NULL); // PASS 1a: PARSING USER SCRIPT + STAP_PROBE1(stap, pass1a__start, &s); struct stat user_file_stat; int user_file_stat_rc = -1; @@ -928,6 +934,8 @@ main (int argc, char * const argv []) version_suffixes.push_back (""); // PASS 1b: PARSING LIBRARY SCRIPTS + STAP_PROBE1(stap, pass1b__start, &s); + for (unsigned i=0; i (int)sizeof(buf)) { _err("exceeded maximum send_request size.\n"); diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index 7125a7bb..45b142bc 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -485,6 +485,7 @@ int stp_main_loop(void) type = *(uint32_t *) recvbuf; data = (void *)(recvbuf + sizeof(uint32_t)); nb -= sizeof(uint32_t); + STAP_PROBE3(staprun, recv__ctlmsg, type, data, nb); switch (type) { #if STP_TRANSPORT_VERSION == 1 diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c index 42b72ff1..7069cab3 100644 --- a/runtime/staprun/staprun.c +++ b/runtime/staprun/staprun.c @@ -192,6 +192,7 @@ static int remove_module(const char *name, int verb) close_ctl_channel(); dbug(2, "removing module %s\n", name); + STAP_PROBE1(staprun, remove__module, name); ret = delete_module (name, 0); if (ret != 0) { err("Error removing module '%s': %s.\n", name, strerror(errno)); diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 3c9dab3f..1c9aece8 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -38,6 +38,9 @@ /* Include config.h to pick up dependency for --prefix usage. */ #include "config.h" +/* For STAP_PROBE in staprun.c, staprun_funcs.c, mainloop.c and common.c */ +#include "sys/sdt.h" + extern void eprintf(const char *fmt, ...); extern void switch_syslog(const char *name); diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index 781bb999..c19dc3ba 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -94,6 +94,7 @@ int insert_module(const char *path, const char *special_options, char **options) return -1; } + STAP_PROBE1(staprun, insert__module, path); /* Actually insert the module */ ret = init_module(file, sbuf.st_size, opts); saved_errno = errno; diff --git a/util.cxx b/util.cxx index 5c05a1dd..23deb37b 100644 --- a/util.cxx +++ b/util.cxx @@ -16,6 +16,7 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "util.h" +#include "sys/sdt.h" #include #include @@ -303,12 +304,14 @@ static pid_t spawned_pid = 0; int stap_system(const char *command) { + STAP_PROBE1(stap, stap_system__start, command); const char * argv[] = { "sh", "-c", command, NULL }; int ret, status; spawned_pid = 0; ret = posix_spawn(&spawned_pid, "/bin/sh", NULL, NULL, const_cast(argv), environ); + STAP_PROBE2(stap, stap_system__spawn, ret, spawned_pid); if (ret == 0) { if (waitpid(spawned_pid, &status, 0) == spawned_pid) @@ -316,6 +319,7 @@ stap_system(const char *command) else ret = errno; } + STAP_PROBE1(stap, stap_system__complete, ret); spawned_pid = 0; return ret; } -- cgit From 67a31a9f57db3f8108e31522b3cf5a6d7d604f22 Mon Sep 17 00:00:00 2001 From: Kent Sebastian Date: Fri, 31 Jul 2009 16:35:20 -0400 Subject: PR10204: Place userspace markers in systemtap itself * tapset/stap_staticmarkers.stp: new file (for real this time) --- tapset/stap_staticmarkers.stp | 267 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 tapset/stap_staticmarkers.stp diff --git a/tapset/stap_staticmarkers.stp b/tapset/stap_staticmarkers.stp new file mode 100644 index 00000000..ff295771 --- /dev/null +++ b/tapset/stap_staticmarkers.stp @@ -0,0 +1,267 @@ +// stap/staprun/stapio static probes 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. + +/** + * probes stap.pass0, stap.pass0.end + * @session: the systemtap_session variable s + * + * pass0 fires after command line arguments have been parsed. + * pass0.end fires just before the gettimeofday() call for pass1. + */ +probe stap.pass0 = process("stap").mark("pass0__start") { + session = $arg1 +} +probe stap.pass0.end = process("stap").mark("pass0__end") { + session = $arg1 +} + +/** + * probes stap.pass1a, stap.pass1b, stap.pass1.end + * @session: the systemtap_session variable s + * + * pass1a fires just after the call to gettimeofday(), before the + * user script is parsed. + * pass1b fires just before the library scripts are parsed. + * pass1.end fires just before the jump to cleanup if s.last_pass = 1. + */ +probe stap.pass1a = process("stap").mark("pass1a__start") { + session = $arg1 +} +probe stap.pass1b = process("stap").mark("pass1b__start") { + session = $arg1 +} +probe stap.pass1.end = process("stap").mark("pass1__end") { + session = $arg1 +} + +/** + * probes stap.pass2, stap.pass2.end + * @session: the systemtap_session variable s + * + * pass2 fires just after the call to gettimeofday(), just before the + * call to semantic_pass. + * pass2.end fires just before the jump to cleanup if s.last_pass = 2 + */ +probe stap.pass2 = process("stap").mark("pass2__start") { + session = $arg1 +} +probe stap.pass2.end = process("stap").mark("pass2__end") { + session = $arg1 +} + +/** + * probes stap.pass3, stap.pass3.end + * @session: the systemtap_session variable s + * + * pass3 fires just after the call to gettimeofday(), just before the + * call to translate_pass. + * pass3.end fires just before the jump to cleanup if s.last_pass = 3 + */ +probe stap.pass3 = process("stap").mark("pass3__start") { + session = $arg1 +} +probe stap.pass3.end = process("stap").mark("pass3__end") { + session = $arg1 +} + +/** + * probes stap.pass4, stap.pass4.end + * @session: the systemtap_session variable s + * + * pass4 fires just after the call to gettimeofday(), just before the + * call to compile_pass. + * pass4.end fires just before the jump to cleanup if s.last_pass = 4 + */ +probe stap.pass4 = process("stap").mark("pass4__start") { + session = $arg1 +} +probe stap.pass4.end = process("stap").mark("pass4__end") { + session = $arg1 +} + +/** + * probes stap.pass5, stap.pass5.end + * @session: the systemtap_session variable s + * + * pass5 fires just after the call to gettimeofday(), just before the + * call to run_pass. + * pass5.end fires just before the cleanup label + */ +probe stap.pass5 = process("stap").mark("pass5__start") { + session = $arg1 +} +probe stap.pass5.end = process("stap").mark("pass5__end") { + session = $arg1 +} + +/** + * probes stap.pass6, stap.pass6.end + * @session: the systemtap_session variable s + * + * pass6 fires just after the cleanup label, essentially the same spot + * as pass5.end + * pass6.end fires just before main's return. + */ +probe stap.pass6 = process("stap").mark("pass6__start") { + session = $arg1 +} +probe stap.pass6.end = process("stap").mark("pass6__end") { + session = $arg1 +} + +/** + * probe stap.cache_clean + * @path: the path to the .ko/.c file being removed + * + * Fires just before the call to unlink the module/source file. + */ +probe stap.cache_clean = process("stap").mark("cache__clean") { + path = user_string($arg1) +} + +/** + * probe stap.cache_add_mod + * @source_path: the path the .ko file is coming from (incl filename) + * @dest_path: the path the .ko file is going to (incl filename) + * + * Fires just before the file is actually moved. Note: if moving fails, + * cache_add_src and cache_add_nss will not fire. + */ +probe stap.cache_add_mod = process("stap").mark("cache__add__module") { + source_path = user_string($arg1) + dest_path = user_string($arg2) +} + +/** + * probe stap.cache_add_src + * @source_path: the path the .c file is coming from (incl filename) + * @dest_path: the path the .c file is going to (incl filename) + * + * Fires just before the file is actually moved. Note: if moving the + * kernel module fails, this probe will not fire. + */ +probe stap.cache_add_src = process("stap").mark("cache__add__source") { + source_path = user_string($arg1) + dest_path = user_string($arg2) +} + +/** + * probe stap.cache_add_nss + * @source_path: the path the .sgn file is coming from (incl filename) + * @dest_path: the path the .sgn file is coming from (incl filename) + * + * Fires just before the file is actually moved. Note: stap must compiled + * with NSS support; if moving the kernel module fails, this probe will + * not fire. + */ +probe stap.cache_add_nss = process("stap").mark("cache__add__nss") ? { + source_path = user_string($arg1) + dest_path = user_string($arg2) +} + +/** + * probe stap.cache_get + * @source_path: the path of the .c source file + * @module_path: the path of the .ko kernel module file + * + * Fires just before the return of get_from_cache, when the cache grab + * is successful. + */ +probe stap.cache_get = process("stap").mark("cache__get") { + source_path = user_string($arg1) + module_path = user_string($arg2) +} + +/** + * probe stap.system + * @command: the command string to be run by posix_spawn (as sh -c ) + * + * Fires at the entry of the stap_system command. + */ +probe stap.system = process("stap").mark("stap_system__start") { + command = user_string($arg1) +} + +/** + * probe stap.system.spawn + * @ret: the return value from posix_spawn + * @pid: the pid of the spawned process + * + * Fires just after the call to posix_spawn. + */ +probe stap.system.spawn = process("stap").mark("stap_system__spawn") { + /* posix_spawn(3p) for meaning of ret */ + ret = $arg1 + pid = $arg2 +} + +/** + * probe stap.system.return + * @ret: a return code associated with running waitpid on the spawned process; + * a non-zero value indicates error + * + * Fires just before the return of the stap_system function, after waitpid. + */ +probe stap.system.return = process("stap").mark("stap_system__complete") { + ret = $arg1 +} + +/** + * probe staprun.insert_module + * @path: the full path to the .ko kernel module about to be inserted + * + * Fires just before the call to insert the module. + */ +probe staprun.insert_module = process("staprun").mark("insert__module") { + path = user_string($arg1) +} + +/** + * probe staprun.remove_module + * @name: the stap module name to be removed (without the .ko extension) + * + * Fires just before the call to remove the module. + */ +probe staprun.remove_module = process("staprun").mark("remove__module") { + name = user_string($arg1) +} + +/** + * probe staprun.send_control_message + * @type: type of message being send; defined in runtime/transport/transport_msgs.h + * @data: a ptr to a binary blob of data sent as the control message + * @len: the length (in bytes) of the data blob + * + * Fires at the beginning of the send_request function. + */ +probe staprun.send_control_message = process("staprun").mark("send__ctlmsg") { + type = $arg1 + data = $arg2 + len = $arg3 +} + +/** + * probe stapio.receive_control_message + * @type: type of message being send; defined in runtime/transport/transport_msgs.h + * @data: a ptr to a binary blob of data sent as the control message + * @len: the length (in bytes) of the data blob + * + * Fires just after a message was receieved and before it's processed. + */ +/* + *** Due to stapio not being in a user's PATH and the build environment of *** + *** stap, there is no immediate 'good' way to insert the correct path here *** + *** so comment out this probe. Note however, the static marker is still *** + *** present in source. *** +probe stapio.receive_control_message = process("@libexecdir@/systemtap/stapio").mark("recv__ctlmsg") { + type = $arg1 + data = $arg2 + len = $arg3 +} +*/ -- cgit From 76ff718a26fa2b73be43ca8d99fb091b686b1d85 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 31 Jul 2009 17:51:22 -0400 Subject: NEWS: note faster pass-2 --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 8fa10401..a56787bd 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,9 @@ - Systemwide kernel .function.return (kretprobe) maxactive defaults may be overridden with the -DKRETACTIVE=nnn parameter. +- Translation pass 2 is significantly faster by avoiding unnecessary + searching through a kernel build/module directory tree. + * What's new in version 0.9.8 - Miscellaneous new tapset functions: -- cgit From 8eb285ac4ec3a34b29ebf20fde0e28cc647d940f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 13:29:18 -0700 Subject: Drop a couple of unnecessary std:: qualifiers * staptree.cxx (target_symbol::print): Drop std:: from parameter o. (cast_op::print): Ditto. --- staptree.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/staptree.cxx b/staptree.cxx index 9e2ca8da..b14a5c44 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -259,7 +259,7 @@ void symbol::print (ostream& o) const } -void target_symbol::print (std::ostream& o) const +void target_symbol::print (ostream& o) const { if (addressof) o << "&"; @@ -279,7 +279,7 @@ void target_symbol::print (std::ostream& o) const } -void cast_op::print (std::ostream& o) const +void cast_op::print (ostream& o) const { if (addressof) o << "&"; -- cgit From 81931eaba5dcd0727f33328bf4b0ff511b791990 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 13:46:54 -0700 Subject: Refactor parser for target_symbol->components The components were being parsed for both target_symbols and cast_ops, so this change refactors that code into a single function. * parse.cxx (parser::parse_target_symbol_components): New. (parser::parse_symbol): Use the new function. --- parse.cxx | 72 ++++++++++++++++++++++++++------------------------------------- parse.h | 3 +++ 2 files changed, 33 insertions(+), 42 deletions(-) diff --git a/parse.cxx b/parse.cxx index 35c78abe..29d97589 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2346,27 +2346,8 @@ parser::parse_symbol () expect_unknown(tok_string, cop->module); } expect_op(")"); - while (true) - { - string c; - if (peek_op ("->")) - { - next(); - expect_ident_or_keyword (c); - cop->components.push_back - (make_pair (target_symbol::comp_struct_member, c)); - } - else if (peek_op ("[")) - { - next(); - expect_unknown (tok_number, c); - expect_op ("]"); - cop->components.push_back - (make_pair (target_symbol::comp_literal_array_index, c)); - } - else - break; - } + parse_target_symbol_components(cop); + // if there aren't any dereferences, then the cast is pointless if (cop->components.empty()) { @@ -2494,27 +2475,7 @@ parser::parse_symbol () target_symbol *tsym = new target_symbol; tsym->tok = t; tsym->base_name = name; - while (true) - { - string c; - if (peek_op ("->")) - { - next(); - expect_ident_or_keyword (c); - tsym->components.push_back - (make_pair (target_symbol::comp_struct_member, c)); - } - else if (peek_op ("[")) - { - next(); - expect_unknown (tok_number, c); - expect_op ("]"); - tsym->components.push_back - (make_pair (target_symbol::comp_literal_array_index, c)); - } - else - break; - } + parse_target_symbol_components(tsym); return tsym; } @@ -2604,4 +2565,31 @@ parser::parse_symbol () return sym; } + +void +parser::parse_target_symbol_components (target_symbol* e) +{ + while (true) + { + string c; + if (peek_op ("->")) + { + next(); + expect_ident_or_keyword (c); + e->components.push_back + (make_pair (target_symbol::comp_struct_member, c)); + } + else if (peek_op ("[")) + { + next(); + expect_unknown (tok_number, c); + expect_op ("]"); + e->components.push_back + (make_pair (target_symbol::comp_literal_array_index, c)); + } + else + break; + } +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/parse.h b/parse.h index cae49b65..5587586e 100644 --- a/parse.h +++ b/parse.h @@ -112,6 +112,7 @@ struct next_statement; struct continue_statement; struct indexable; struct expression; +struct target_symbol; struct hist_op; class parser @@ -203,6 +204,8 @@ private: // nonterminals expression* parse_crement (); expression* parse_value (); expression* parse_symbol (); + + void parse_target_symbol_components (target_symbol* e); }; -- cgit From c67847a0d05f8c7207513e79378fc8d84563e109 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 17:00:09 -0700 Subject: Make a real type for target_symbol->components Now the dereferences on target_symbol and cast_op are tracked with a struct instead of just a generic pair. The first immediate benefit is that we can track the token for more exact error reporting. * staptree.h (target_symbol): Add a new component type. * staptree.cxx (target_symbol::component::print): New. (operator<<(ostream&, target_symbol::component&): New. (target_symbol::print): Adapt component printing. (cast_op::print): Ditto. * parse.cxx (parser::parse_target_symbol_components): Adapt to the new component construction. * dwflpp.cxx (dwflpp::find_struct_member): take the component as a parameter for a better token in error messages (dwflpp::translate_components): Adapt to the new component type. * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Don't overwrite the token in target_symbol saved errors. (tracepoint_var_expanding_visitor::visit_target_symbol_arg): Ditto. --- dwflpp.cxx | 64 ++++++++++++++++++++++++++++++------------------------ dwflpp.h | 3 +-- parse.cxx | 17 +++++++-------- staptree.cxx | 45 +++++++++++++++++++------------------- staptree.h | 19 +++++++++++++++- tapset-mark.cxx | 4 ++-- tapset-perfmon.cxx | 2 +- tapset-procfs.cxx | 2 +- tapset-utrace.cxx | 4 ++-- tapsets.cxx | 6 ++--- 10 files changed, 94 insertions(+), 72 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index e6e7b471..090aa70a 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1620,9 +1620,8 @@ dwflpp::print_members(Dwarf_Die *vardie, ostream &o) bool -dwflpp::find_struct_member(const string& member, +dwflpp::find_struct_member(const target_symbol::component& c, Dwarf_Die *parentdie, - const target_symbol *e, Dwarf_Die *memberdie, vector& locs) { @@ -1640,7 +1639,7 @@ dwflpp::find_struct_member(const string& member, throw semantic_error (string (dwarf_tag(&die) == DW_TAG_union_type ? "union" : "struct") + string (dwarf_diename_integrate (&die) ?: "") + string (dwarf_errmsg (-1)), - e->tok); + c.tok); } do @@ -1658,10 +1657,10 @@ dwflpp::find_struct_member(const string& member, !dwarf_formref_die (&attr, &subdie)) continue; - if (find_struct_member(member, &subdie, e, memberdie, locs)) + if (find_struct_member(c, &subdie, memberdie, locs)) goto success; } - else if (name == member) + else if (name == c.member) { *memberdie = die; goto success; @@ -1680,9 +1679,9 @@ success: /* Union members don't usually have a location, * but just use the containing union's location. */ else if (dwarf_tag(parentdie) != DW_TAG_union_type) - throw semantic_error ("no location for field '" + member + throw semantic_error ("no location for field '" + c.member + "': " + string(dwarf_errmsg (-1)), - e->tok); + c.tok); return true; } @@ -1709,6 +1708,8 @@ dwflpp::translate_components(struct obstack *pool, while (i < e->components.size()) { + const target_symbol::component& c = e->components[i]; + /* 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. */ #if 0 @@ -1730,39 +1731,45 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_pointer_type: c_translate_pointer (pool, 1, 0 /* PR9768*/, die, tail); - if (e->components[i].first != target_symbol::comp_literal_array_index) + if (c.type != target_symbol::comp_literal_array_index) break; /* else fall through as an array access */ case DW_TAG_array_type: - if (e->components[i].first == target_symbol::comp_literal_array_index) + if (c.type == target_symbol::comp_literal_array_index) { c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, - NULL, lex_cast(e->components[i].second)); + NULL, c.num_index); ++i; } else - throw semantic_error("bad field '" - + e->components[i].second - + "' for array type", - e->tok); + throw semantic_error ("invalid access '" + + lex_cast(c) + + "' for array type", + c.tok); break; case DW_TAG_structure_type: case DW_TAG_union_type: + if (c.type != target_symbol::comp_struct_member) + throw semantic_error ("invalid access '" + + lex_cast(c) + + "' for struct/union type", + c.tok); + if (dwarf_hasattr(die, DW_AT_declaration)) { Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die)); if (tmpdie == NULL) throw semantic_error ("unresolved struct " + string (dwarf_diename_integrate (die) ?: ""), - e->tok); + c.tok); *die_mem = *tmpdie; } { vector locs; - if (!find_struct_member(e->components[i].second, die, e, die, locs)) + if (!find_struct_member(c, die, die, locs)) { string alternatives; stringstream members; @@ -1770,10 +1777,10 @@ dwflpp::translate_components(struct obstack *pool, if (members.str().size() != 0) alternatives = " (alternatives:" + members.str(); throw semantic_error("unable to find member '" + - e->components[i].second + "' for struct " + c.member + "' for struct " + string(dwarf_diename_integrate(die) ?: "") + alternatives, - e->tok); + c.tok); } for (unsigned j = 0; j < locs.size(); ++j) @@ -1784,39 +1791,40 @@ dwflpp::translate_components(struct obstack *pool, break; case DW_TAG_enumeration_type: - throw semantic_error ("field '" - + e->components[i].second + throw semantic_error ("invalid access '" + + lex_cast(c) + "' vs. enum type " + string(dwarf_diename_integrate (die) ?: ""), - e->tok); + c.tok); break; case DW_TAG_base_type: - throw semantic_error ("field '" - + e->components[i].second + throw semantic_error ("invalid access '" + + lex_cast(c) + "' vs. base type " + string(dwarf_diename_integrate (die) ?: ""), - e->tok); + c.tok); break; case -1: throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)), - e->tok); + c.tok); break; default: throw semantic_error (string(dwarf_diename_integrate (die) ?: "") + ": unexpected type tag " + lex_cast(dwarf_tag (die)), - e->tok); + c.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)), e->tok); + throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), + c.tok); } /* For an array index, we need to dereference the final DIE */ - if (e->components.back().first == target_symbol::comp_literal_array_index) + if (e->components.back().type == target_symbol::comp_literal_array_index) die = dwarf_formref_die (attr_mem, die_mem); return die; diff --git a/dwflpp.h b/dwflpp.h index 20bcc0d0..3cada4f8 100644 --- a/dwflpp.h +++ b/dwflpp.h @@ -333,9 +333,8 @@ private: struct location **tail, const target_symbol *e); - bool find_struct_member(const std::string& member, + bool find_struct_member(const target_symbol::component& c, Dwarf_Die *parentdie, - const target_symbol *e, Dwarf_Die *memberdie, std::vector& locs); diff --git a/parse.cxx b/parse.cxx index 29d97589..9d4a06a6 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2571,21 +2571,20 @@ parser::parse_target_symbol_components (target_symbol* e) { while (true) { - string c; if (peek_op ("->")) { - next(); - expect_ident_or_keyword (c); - e->components.push_back - (make_pair (target_symbol::comp_struct_member, c)); + const token* t = next(); + string member; + expect_ident_or_keyword (member); + e->components.push_back (target_symbol::component(t, member)); } else if (peek_op ("[")) { - next(); - expect_unknown (tok_number, c); + const token* t = next(); + int64_t index; + expect_number (index); + e->components.push_back (target_symbol::component(t, index)); expect_op ("]"); - e->components.push_back - (make_pair (target_symbol::comp_literal_array_index, c)); } else break; diff --git a/staptree.cxx b/staptree.cxx index b14a5c44..1231f74d 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -259,23 +259,34 @@ void symbol::print (ostream& o) const } +void target_symbol::component::print (ostream& o) const +{ + switch (type) + { + case comp_struct_member: + o << "->" << member; + break; + case comp_literal_array_index: + o << '[' << num_index << ']'; + break; + } +} + + +std::ostream& operator << (std::ostream& o, const target_symbol::component& c) +{ + c.print (o); + return o; +} + + void target_symbol::print (ostream& o) const { if (addressof) o << "&"; o << base_name; for (unsigned i = 0; i < components.size(); ++i) - { - switch (components[i].first) - { - case comp_literal_array_index: - o << '[' << components[i].second << ']'; - break; - case comp_struct_member: - o << "->" << components[i].second; - break; - } - } + o << components[i]; } @@ -289,17 +300,7 @@ void cast_op::print (ostream& o) const o << ", " << lex_cast_qstring (module); o << ')'; for (unsigned i = 0; i < components.size(); ++i) - { - switch (components[i].first) - { - case comp_literal_array_index: - o << '[' << components[i].second << ']'; - break; - case comp_struct_member: - o << "->" << components[i].second; - break; - } - } + o << components[i]; } diff --git a/staptree.h b/staptree.h index 16f0256a..70746f31 100644 --- a/staptree.h +++ b/staptree.h @@ -229,9 +229,24 @@ struct target_symbol: public symbol comp_struct_member, comp_literal_array_index }; + + struct component + { + const token* tok; + component_type type; + std::string member; // comp_struct_member + int64_t num_index; // comp_literal_array_index + + component(const token* t, const std::string& m): + tok(t), type(comp_struct_member), member(m), num_index(0) {} + component(const token* t, int64_t n): + tok(t), type(comp_literal_array_index), num_index(n) {} + void print (std::ostream& o) const; + }; + bool addressof; std::string base_name; - std::vector > components; + std::vector components; std::string probe_context_var; semantic_error* saved_conversion_error; target_symbol(): addressof(false), saved_conversion_error (0) {} @@ -239,6 +254,8 @@ struct target_symbol: public symbol void visit (visitor* u); }; +std::ostream& operator << (std::ostream& o, const target_symbol::component& c); + struct cast_op: public target_symbol { diff --git a/tapset-mark.cxx b/tapset-mark.cxx index a358a20e..fcde9ed5 100644 --- a/tapset-mark.cxx +++ b/tapset-mark.cxx @@ -105,7 +105,7 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("marker argument may not be used as array", @@ -140,7 +140,7 @@ mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("marker '" + sname + "' may not be used as array", diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx index 0fb567f7..dfdc55e6 100644 --- a/tapset-perfmon.cxx +++ b/tapset-perfmon.cxx @@ -69,7 +69,7 @@ perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("perfmon probe '$counter' variable may not be used as array", diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx index a996ee32..58bb0f0d 100644 --- a/tapset-procfs.cxx +++ b/tapset-procfs.cxx @@ -360,7 +360,7 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("procfs target variable '$value' may not be used as array", diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index a3a4ca3d..3befcbd5 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -457,7 +457,7 @@ utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("utrace target variable '$argN' may not be used as array", @@ -507,7 +507,7 @@ utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (e->components.size() > 0) { - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("utrace target variable '" + sname + "' may not be used as array", diff --git a/tapsets.cxx b/tapsets.cxx index bd33fb0b..70edc7d8 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2244,7 +2244,6 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) // quietly. provide (e); semantic_error* saveme = new semantic_error (er); // copy it - saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines // NB: we can have multiple errors, since a $target variable // may be expanded in several different contexts: // function ("*") { $var } @@ -5263,7 +5262,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) // make sure we're not dereferencing base types if (!e->components.empty() && !arg->isptr) - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("tracepoint variable '" + e->base_name @@ -5323,7 +5322,6 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) // up not being referenced after all, so it can be optimized out // quietly. semantic_error* saveme = new semantic_error (er); // copy it - saveme->tok1 = e->tok; // XXX: token not passed to dw code generation routines // NB: we can have multiple errors, since a target variable // may be expanded in several different contexts: // trace ("*") { $foo->bar } @@ -5396,7 +5394,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) throw semantic_error("write to tracepoint '" + e->base_name + "' not permitted", e->tok); if (!e->components.empty()) - switch (e->components[0].first) + switch (e->components[0].type) { case target_symbol::comp_literal_array_index: throw semantic_error("tracepoint '" + e->base_name + "' may not be used as array", -- cgit From dc5a09fc9a61c8b33078164b6855dea54a33627c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 Jul 2009 17:24:13 -0700 Subject: Unify no-component assertions on target variables There are several tapsets that can't deal with component dereferences on their target variables, and they all check-and-throw in the same way. This refactors the checks into a target_symbol member. * staptree.cxx (target_symbol::assert_no_components): New. * tapsets.cxx (tracepoint_var_expanding_visitor::visit_target_symbol_arg, tracepoint_var_expanding_visitor::visit_target_symbol_context): Use the new assertion function to check for no components. * tapset-mark.cxx (mark_var_expanding_visitor::visit_target_symbol_arg, mark_var_expanding_visitor::visit_target_symbol_context): Ditto. * tapset-perfmon.cxx (perfmon_var_expanding_visitor::visit_target_symbol): Ditto. * tapset-procfs.cxx (procfs_var_expanding_visitor::visit_target_symbol): Ditto. * tapset-utrace.cxx (utrace_var_expanding_visitor::visit_target_symbol_arg, utrace_var_expanding_visitor::visit_target_symbol_context): Ditto. --- staptree.cxx | 24 ++++++++++++++++++++++++ staptree.h | 1 + tapset-mark.cxx | 36 ++---------------------------------- tapset-perfmon.cxx | 19 +------------------ tapset-procfs.cxx | 19 +------------------ tapset-utrace.cxx | 38 ++------------------------------------ tapsets.cxx | 28 +++------------------------- 7 files changed, 34 insertions(+), 131 deletions(-) diff --git a/staptree.cxx b/staptree.cxx index 1231f74d..321650eb 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -186,6 +186,30 @@ operator << (ostream& o, const exp_type& e) } +void +target_symbol::assert_no_components(const std::string& tapset) +{ + if (components.empty()) + return; + + switch (components[0].type) + { + case target_symbol::comp_literal_array_index: + throw semantic_error(tapset + " variable '" + base_name + + "' may not be used as array", + components[0].tok); + case target_symbol::comp_struct_member: + throw semantic_error(tapset + " variable '" + base_name + + "' may not be used as a structure", + components[0].tok); + default: + throw semantic_error ("invalid use of " + tapset + + " variable '" + base_name + "'", + components[0].tok); + } +} + + // ------------------------------------------------------------------------ // parse tree printing diff --git a/staptree.h b/staptree.h index 70746f31..9ade2a42 100644 --- a/staptree.h +++ b/staptree.h @@ -252,6 +252,7 @@ struct target_symbol: public symbol target_symbol(): addressof(false), saved_conversion_error (0) {} void print (std::ostream& o) const; void visit (visitor* u); + void assert_no_components(const std::string& tapset); }; std::ostream& operator << (std::ostream& o, const target_symbol::component& c); diff --git a/tapset-mark.cxx b/tapset-mark.cxx index fcde9ed5..59334729 100644 --- a/tapset-mark.cxx +++ b/tapset-mark.cxx @@ -103,23 +103,7 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (is_active_lvalue (e)) throw semantic_error("write to marker parameter not permitted", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("marker argument may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("marker argument may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid marker argument use", e->tok); - break; - } - } + e->assert_no_components("marker"); // Remember that we've seen a target variable. target_symbol_seen = true; @@ -138,23 +122,7 @@ mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (is_active_lvalue (e)) throw semantic_error("write to marker '" + sname + "' not permitted", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("marker '" + sname + "' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("marker '" + sname + "' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid marker '" + sname + "' use", e->tok); - break; - } - } + e->assert_no_components("marker"); if (e->base_name == "$format" || e->base_name == "$name") { string fname; diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx index dfdc55e6..d524aa03 100644 --- a/tapset-perfmon.cxx +++ b/tapset-perfmon.cxx @@ -67,24 +67,7 @@ perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) if (e->addressof) throw semantic_error("cannot take address of perfmon variable", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("perfmon probe '$counter' variable may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("perfmon probe '$counter' variable may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of perfmon probe '$counter' variable", - e->tok); - break; - } - } + e->assert_no_components("perfmon"); ec->code = "THIS->__retvalue = _pfm_pmd_x[" + lex_cast(counter_number) + "].reg_num;"; diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx index 58bb0f0d..3302057c 100644 --- a/tapset-procfs.cxx +++ b/tapset-procfs.cxx @@ -358,24 +358,7 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) throw semantic_error ("invalid target symbol for procfs probe, $value expected", e->tok); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("procfs target variable '$value' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("procfs target variable '$value' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of procfs target variable '$value'", - e->tok); - break; - } - } + e->assert_no_components("procfs"); bool lvalue = is_active_lvalue(e); if (write_probe && lvalue) diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index 3befcbd5..87053f7d 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -455,24 +455,7 @@ utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = lex_cast(argnum_s); - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("utrace target variable '$argN' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("utrace target variable '$argN' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of utrace target variable '$argN'", - e->tok); - break; - } - } + e->assert_no_components("utrace"); // FIXME: max argnument number should not be hardcoded. if (argnum < 1 || argnum > 6) @@ -505,24 +488,7 @@ utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; - if (e->components.size() > 0) - { - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("utrace target variable '" + sname + "' may not be used as array", - e->tok); - break; - case target_symbol::comp_struct_member: - throw semantic_error("utrace target variable '" + sname + "' may not be used as a structure", - e->tok); - break; - default: - throw semantic_error ("invalid use of utrace target variable '" + sname + "'", - e->tok); - break; - } - } + e->assert_no_components("utrace"); bool lvalue = is_active_lvalue(e); if (lvalue) diff --git a/tapsets.cxx b/tapsets.cxx index 70edc7d8..537c33e7 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5261,19 +5261,8 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) } // make sure we're not dereferencing base types - if (!e->components.empty() && !arg->isptr) - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("tracepoint variable '" + e->base_name - + "' may not be used as array", e->tok); - case target_symbol::comp_struct_member: - throw semantic_error("tracepoint variable '" + e->base_name - + "' may not be used as a structure", e->tok); - default: - throw semantic_error("invalid use of tracepoint variable '" - + e->base_name + "'", e->tok); - } + if (!arg->isptr) + e->assert_no_components("tracepoint"); // we can only write to dereferenced fields, and only if guru mode is on bool lvalue = is_active_lvalue(e); @@ -5393,18 +5382,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (is_active_lvalue (e)) throw semantic_error("write to tracepoint '" + e->base_name + "' not permitted", e->tok); - if (!e->components.empty()) - switch (e->components[0].type) - { - case target_symbol::comp_literal_array_index: - throw semantic_error("tracepoint '" + e->base_name + "' may not be used as array", - e->tok); - case target_symbol::comp_struct_member: - throw semantic_error("tracepoint '" + e->base_name + "' may not be used as a structure", - e->tok); - default: - throw semantic_error("invalid tracepoint '" + e->base_name + "' use", e->tok); - } + e->assert_no_components("tracepoint"); if (e->base_name == "$$name") { -- cgit From 79a7b65cf99ca7ec258d11c41af5d8ab13abf609 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 3 Aug 2009 17:02:03 +0200 Subject: Make sure we pick up our own sdt.h, not the (maybe not installed) system one. * Makefile.am (AM_CPPFLAGS): Add -I$(srcdir)/includes. * Makefile.in: Regenerated. --- Makefile.am | 2 +- Makefile.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 37491eef..c2234d1c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = no-dist foreign pkglibexecdir = ${libexecdir}/${PACKAGE} oldincludedir = ${includedir}/sys -AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' +AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' -I$(srcdir)/includes AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W AM_CXXFLAGS = -Wall -Werror diff --git a/Makefile.in b/Makefile.in index 9410eaae..a1b45add 100644 --- a/Makefile.in +++ b/Makefile.in @@ -358,7 +358,7 @@ top_srcdir = @top_srcdir@ # we don't maintain a ChangeLog, which makes us non-GNU -> foreign AUTOMAKE_OPTIONS = no-dist foreign -AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' +AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' -I$(srcdir)/includes AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W AM_CXXFLAGS = -Wall -Werror man_MANS = stapprobes.3stap stapfuncs.3stap stapvars.3stap \ -- cgit From 28ad563d57d03e0d21936e394061e3380607d83b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 3 Aug 2009 14:20:46 -0700 Subject: PR10475: ensure that loc2c can find its array size * loc2c.c (array_stride): iterate DIEs past typedef/const/volatile --- loc2c.c | 13 +++++++++++++ testsuite/semok/bz10475.stp | 10 ++++++++++ 2 files changed, 23 insertions(+) create mode 100755 testsuite/semok/bz10475.stp diff --git a/loc2c.c b/loc2c.c index f5efccfe..26ca3ba1 100644 --- a/loc2c.c +++ b/loc2c.c @@ -1749,6 +1749,19 @@ array_stride (Dwarf_Die *typedie, struct location *origin) dwarf_diename (typedie) ?: "", dwarf_errmsg (-1)); + int typetag = dwarf_tag(&die_mem); + while (typetag == DW_TAG_typedef || + typetag == DW_TAG_const_type || + typetag == DW_TAG_volatile_type) + { + if (dwarf_attr_integrate (&die_mem, DW_AT_type, &attr_mem) == NULL + || dwarf_formref_die (&attr_mem, &die_mem) == NULL) + FAIL (origin, N_("cannot get inner type of type %s: %s"), + dwarf_diename (&die_mem) ?: "", + dwarf_errmsg (-1)); + typetag = dwarf_tag(&die_mem); + } + if (dwarf_attr_integrate (&die_mem, DW_AT_byte_size, &attr_mem) != NULL) { Dwarf_Word stride; diff --git a/testsuite/semok/bz10475.stp b/testsuite/semok/bz10475.stp new file mode 100755 index 00000000..ee79b07d --- /dev/null +++ b/testsuite/semok/bz10475.stp @@ -0,0 +1,10 @@ +#! stap -p2 +// bz10475: pointer-array confused about array element size + +// struct file *do_filp_open(int dfd, const char *pathname, +// int open_flag, int mode, int acc_mode) +probe kernel.function("do_filp_open") +{ + // check array access on a "complex" pointer type + println($pathname[0]) +} -- cgit From 6fda2dff51c667a8c73545dd397b844108715310 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 3 Aug 2009 14:45:21 -0700 Subject: PR2049: support arbitrary $target-array indexing Rather than just numeric literals, we can now support arbitrary expressions for the index value. Note that loc2c won't allow this for noncontiguous arrays, as the access methods need to be statically computed, but for contiguous arrays and pointers-as-arrays it works just fine. * staptree.h (target_symbol::component): Add expression_array_index. * staptree.cxx (target_symbol::visit_components): New helper. (target_symbol::assert_no_components): Recognize new array type. (target_symbol::component::print): Print subexpressions. (traversing_visitor::visit_target_symbol, visit_cast_op): Visit the indexing components too. (varuse_collecting_visitor::visit_target_symbol): Ditto. (update_visitor::visit_target_symbol, visit_cast_op): Ditto. * elaborate.cxx (void_statement_reducer::visit_target_symbol): New. (void_statement_reducer::visit_cast_op): Save indexes too. * parse.cxx (parser::parse_target_symbol_components): Parse expressions. * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Pass expression-indexes as parameters (indexN) to the dwarf function. (dwarf_cast_expanding_visitor::visit_cast_op): Ditto. (tracepoint_var_expanding_visitor::visit_target_symbol_arg): Ditto. (sdt_var_expanding_visitor::visit_target_symbol): Visit the new @cast. * dwflpp.cxx (dwflpp::translate_components): Use THIS->indexN. * translate.cxx (c_unparser::visit_target_symbol): Correct error msg. * testsuite/systemtap.base/pointer_array.stp: Use a simple index. --- dwflpp.cxx | 13 ++++++- elaborate.cxx | 62 +++++++++++++++++++++++++++++- parse.cxx | 9 +++-- staptree.cxx | 28 +++++++++++++- staptree.h | 11 +++++- tapsets.cxx | 60 ++++++++++++++++++++++++++--- testsuite/systemtap.base/pointer_array.stp | 11 +----- translate.cxx | 2 +- 8 files changed, 171 insertions(+), 25 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index 090aa70a..6ede1d68 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1731,7 +1731,8 @@ dwflpp::translate_components(struct obstack *pool, case DW_TAG_pointer_type: c_translate_pointer (pool, 1, 0 /* PR9768*/, die, tail); - if (c.type != target_symbol::comp_literal_array_index) + if (c.type != target_symbol::comp_literal_array_index && + c.type != target_symbol::comp_expression_array_index) break; /* else fall through as an array access */ @@ -1742,6 +1743,13 @@ dwflpp::translate_components(struct obstack *pool, NULL, c.num_index); ++i; } + else if (c.type == target_symbol::comp_expression_array_index) + { + string index = "THIS->index" + lex_cast(i); + c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, + index.c_str(), 0); + ++i; + } else throw semantic_error ("invalid access '" + lex_cast(c) @@ -1824,7 +1832,8 @@ dwflpp::translate_components(struct obstack *pool, } /* For an array index, we need to dereference the final DIE */ - if (e->components.back().type == target_symbol::comp_literal_array_index) + if (e->components.back().type == target_symbol::comp_literal_array_index || + e->components.back().type == target_symbol::comp_expression_array_index) die = dwarf_formref_die (attr_mem, die_mem); return die; diff --git a/elaborate.cxx b/elaborate.cxx index fafc5e63..d1ebe326 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2534,6 +2534,7 @@ struct void_statement_reducer: public update_visitor void visit_concatenation (concatenation* e); void visit_functioncall (functioncall* e); void visit_print_format (print_format* e); + void visit_target_symbol (target_symbol* e); void visit_cast_op (cast_op* e); // these are a bit hairy to grok due to the intricacies of indexables and @@ -2802,17 +2803,74 @@ void_statement_reducer::visit_print_format (print_format* e) provide (e); } +void +void_statement_reducer::visit_target_symbol (target_symbol* e) +{ + // When target_symbol isn't needed, it's just as good to + // evaluate any array indexes directly + + block *b = new block; + b->tok = e->tok; + + for (unsigned i=0; icomponents.size(); i++ ) + { + if (e->components[i].type != target_symbol::comp_expression_array_index) + continue; + + expr_statement *es = new expr_statement; + es->value = e->components[i].expr_index; + es->tok = es->value->tok; + b->statements.push_back(es); + } + + if (b->statements.empty()) + { + delete b; + provide (e); + return; + } + + if (session.verbose>2) + clog << "Eliding unused target symbol " << *e->tok << endl; + + b->visit(this); + relaxed_p = false; + e = 0; + provide (e); +} + void void_statement_reducer::visit_cast_op (cast_op* e) { // When the result of a cast operation isn't needed, it's just as good to - // evaluate the operand directly + // evaluate the operand and any array indexes directly + + block *b = new block; + b->tok = e->tok; + + expr_statement *es = new expr_statement; + es->value = e->operand; + es->tok = es->value->tok; + b->statements.push_back(es); + + for (unsigned i=0; icomponents.size(); i++ ) + { + if (e->components[i].type != target_symbol::comp_expression_array_index) + continue; + + es = new expr_statement; + es->value = e->components[i].expr_index; + es->tok = es->value->tok; + b->statements.push_back(es); + } if (session.verbose>2) clog << "Eliding unused typecast " << *e->tok << endl; + b->visit(this); relaxed_p = false; - e->operand->visit(this); + e = 0; + provide (e); } diff --git a/parse.cxx b/parse.cxx index 9d4a06a6..41a13ca5 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2581,9 +2581,12 @@ parser::parse_target_symbol_components (target_symbol* e) else if (peek_op ("[")) { const token* t = next(); - int64_t index; - expect_number (index); - e->components.push_back (target_symbol::component(t, index)); + expression* index = parse_expression(); + literal_number* ln = dynamic_cast(index); + if (ln) + e->components.push_back (target_symbol::component(t, ln->value)); + else + e->components.push_back (target_symbol::component(t, index)); expect_op ("]"); } else diff --git a/staptree.cxx b/staptree.cxx index 321650eb..50d9980f 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -195,6 +195,7 @@ target_symbol::assert_no_components(const std::string& tapset) switch (components[0].type) { case target_symbol::comp_literal_array_index: + case target_symbol::comp_expression_array_index: throw semantic_error(tapset + " variable '" + base_name + "' may not be used as array", components[0].tok); @@ -293,6 +294,9 @@ void target_symbol::component::print (ostream& o) const case comp_literal_array_index: o << '[' << num_index << ']'; break; + case comp_expression_array_index: + o << '[' << *expr_index << ']'; + break; } } @@ -1270,6 +1274,22 @@ target_symbol::visit (visitor* u) u->visit_target_symbol(this); } +void +target_symbol::visit_components (visitor* u) +{ + for (unsigned i = 0; i < components.size(); ++i) + if (components[i].type == comp_expression_array_index) + components[i].expr_index->visit (u); +} + +void +target_symbol::visit_components (update_visitor* u) +{ + for (unsigned i = 0; i < components.size(); ++i) + if (components[i].type == comp_expression_array_index) + components[i].expr_index = u->require (components[i].expr_index); +} + void cast_op::visit (visitor* u) { @@ -1638,14 +1658,16 @@ traversing_visitor::visit_symbol (symbol*) } void -traversing_visitor::visit_target_symbol (target_symbol*) +traversing_visitor::visit_target_symbol (target_symbol* e) { + e->visit_components (this); } void traversing_visitor::visit_cast_op (cast_op* e) { e->operand->visit (this); + e->visit_components (this); } void @@ -1740,6 +1762,8 @@ varuse_collecting_visitor::visit_target_symbol (target_symbol *e) if (is_active_lvalue (e)) embedded_seen = true; + + functioncall_traversing_visitor::visit_target_symbol (e); } void @@ -2373,6 +2397,7 @@ update_visitor::visit_symbol (symbol* e) void update_visitor::visit_target_symbol (target_symbol* e) { + e->visit_components (this); provide (e); } @@ -2380,6 +2405,7 @@ void update_visitor::visit_cast_op (cast_op* e) { e->operand = require (e->operand); + e->visit_components (this); provide (e); } diff --git a/staptree.h b/staptree.h index 9ade2a42..146d0e34 100644 --- a/staptree.h +++ b/staptree.h @@ -58,6 +58,7 @@ std::ostream& operator << (std::ostream& o, const exp_type& e); struct token; struct visitor; +struct update_visitor; struct expression { @@ -227,7 +228,8 @@ struct target_symbol: public symbol enum component_type { comp_struct_member, - comp_literal_array_index + comp_literal_array_index, + comp_expression_array_index, }; struct component @@ -236,11 +238,14 @@ struct target_symbol: public symbol component_type type; std::string member; // comp_struct_member int64_t num_index; // comp_literal_array_index + expression* expr_index; // comp_expression_array_index component(const token* t, const std::string& m): - tok(t), type(comp_struct_member), member(m), num_index(0) {} + tok(t), type(comp_struct_member), member(m) {} component(const token* t, int64_t n): tok(t), type(comp_literal_array_index), num_index(n) {} + component(const token* t, expression* e): + tok(t), type(comp_expression_array_index), expr_index(e) {} void print (std::ostream& o) const; }; @@ -252,6 +257,8 @@ struct target_symbol: public symbol target_symbol(): addressof(false), saved_conversion_error (0) {} void print (std::ostream& o) const; void visit (visitor* u); + void visit_components (visitor* u); + void visit_components (update_visitor* u); void assert_no_components(const std::string& tapset); }; diff --git a/tapsets.cxx b/tapsets.cxx index 537c33e7..ba344c51 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2268,6 +2268,18 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) fdecl->name = fname; fdecl->body = ec; + + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + { + vardecl *v = new vardecl; + v->type = pe_long; + v->name = "index" + lex_cast(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a single pe_long formal @@ -2292,6 +2304,11 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + n->args.push_back(require(e->components[i].expr_index)); + if (lvalue) { // Provide the functioncall to our parent, so that it can be @@ -2521,6 +2538,17 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) v1->tok = e->tok; fdecl->formal_args.push_back(v1); + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + { + vardecl *v = new vardecl; + v->type = pe_long; + v->name = "index" + lex_cast(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a second pe_long formal @@ -2549,6 +2577,11 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session n->args.push_back(e->operand); + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + n->args.push_back(require(e->components[i].expr_index)); + if (lvalue) { // Provide the functioncall to our parent, so that it can be @@ -3277,7 +3310,7 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e) cast->type = probe_name + "_arg" + lex_cast(argno); cast->module = process_name; - provide(cast); + cast->visit(this); } @@ -5327,6 +5360,17 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) v1->tok = e->tok; fdecl->formal_args.push_back(v1); + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + { + vardecl *v = new vardecl; + v->type = pe_long; + v->name = "index" + lex_cast(i); + v->tok = e->tok; + fdecl->formal_args.push_back(v); + } + if (lvalue) { // Modify the fdecl so it carries a pe_long formal @@ -5354,10 +5398,16 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - // make the original a bare target symbol for the tracepoint value, - // which will be passed into the dwarf dereferencing code - e->components.clear(); - n->args.push_back(require(e)); + // make a copy of the original as a bare target symbol for the tracepoint + // value, which will be passed into the dwarf dereferencing code + target_symbol* e2 = deep_copy_visitor::deep_copy(e); + e2->components.clear(); + n->args.push_back(require(e2)); + + // Any non-literal indexes need to be passed in too. + for (unsigned i = 0; i < e->components.size(); ++i) + if (e->components[i].type == target_symbol::comp_expression_array_index) + n->args.push_back(require(e->components[i].expr_index)); if (lvalue) { diff --git a/testsuite/systemtap.base/pointer_array.stp b/testsuite/systemtap.base/pointer_array.stp index 1d15ebf4..cd420604 100644 --- a/testsuite/systemtap.base/pointer_array.stp +++ b/testsuite/systemtap.base/pointer_array.stp @@ -2,15 +2,8 @@ probe syscall.execve { if (pid() == target()) { println(user_string($argv[0])) - printf("%c\n", $argv[0][0]) - printf("%c\n", $argv[0][1]) - printf("%c\n", $argv[0][2]) - printf("%c\n", $argv[0][3]) - printf("%c\n", $argv[0][4]) - printf("%c\n", $argv[0][5]) - printf("%c\n", $argv[0][6]) - printf("%c\n", $argv[0][7]) - printf("%c\n", $argv[0][8]) + for (i=0; i<9; ++i) + printf("%c\n", $argv[0][i]) println($argv[0][9]) } } diff --git a/translate.cxx b/translate.cxx index f2e04d7d..a26e4085 100644 --- a/translate.cxx +++ b/translate.cxx @@ -3515,7 +3515,7 @@ c_unparser::visit_target_symbol (target_symbol* e) if (!e->probe_context_var.empty()) o->line() << "l->" << e->probe_context_var; else - throw semantic_error("cannot translate general cast expression", e->tok); + throw semantic_error("cannot translate general target expression", e->tok); } -- cgit From 3a4235b9897b75a188753419a29f0616c1686249 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 3 Aug 2009 15:20:19 -0700 Subject: Strengthen the template types in update_visitor * staptree.h (update_visitor::require, provide): Make the parameters and return values a T*, to make it explicit that we want pointer types. --- staptree.cxx | 2 +- staptree.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/staptree.cxx b/staptree.cxx index 50d9980f..11661442 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -2450,7 +2450,7 @@ update_visitor::visit_hist_op (hist_op* e) } template <> indexable* -update_visitor::require (indexable* src, bool clearok) +update_visitor::require (indexable* src, bool clearok) { indexable *dst = NULL; if (src != NULL) diff --git a/staptree.h b/staptree.h index 146d0e34..bc479559 100644 --- a/staptree.h +++ b/staptree.h @@ -855,21 +855,21 @@ struct throwing_visitor: public visitor struct update_visitor: public visitor { - template T require (T src, bool clearok=false) + template T* require (T* src, bool clearok=false) { - T dst = NULL; + T* dst = NULL; if (src != NULL) { src->visit(this); assert(!targets.empty()); - dst = static_cast(targets.top()); + dst = static_cast(targets.top()); targets.pop(); assert(clearok || dst); } return dst; } - template void provide (T src) + template void provide (T* src) { targets.push(static_cast(src)); } @@ -915,7 +915,7 @@ private: }; template <> indexable* -update_visitor::require (indexable* src, bool clearok); +update_visitor::require (indexable* src, bool clearok); // A visitor which performs a deep copy of the root node it's applied // to. NB: It does not copy any of the variable or function @@ -925,7 +925,7 @@ update_visitor::require (indexable* src, bool clearok); struct deep_copy_visitor: public update_visitor { - template static T deep_copy (T e) + template static T* deep_copy (T* e) { deep_copy_visitor v; return v.require (e); -- cgit From 8b095b454b34e88c04592be6c651153f802eced6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 3 Aug 2009 15:49:40 -0700 Subject: Add update_visitor::replace I noticed that most uses of update_visitor::require() were simply writing the value back to the same place, i.e. foo = require(foo). The new replace() method just encapsulates that paradigm, so we don't have the duplication between the LHS and RHS. * staptree.h (update_visitor::replace): New. * elaborate.cxx, staptree.cxx, tapset-mark.cxx, tapset-perfmon.cxx, tapset-procfs.cxx, tapset-utrace.cxx, tapsets.cxx: Update all require calls that are simply updating the value in-place. --- elaborate.cxx | 38 ++++++++++++------------ staptree.cxx | 86 +++++++++++++++++++++++++++--------------------------- staptree.h | 5 ++++ tapset-mark.cxx | 2 +- tapset-perfmon.cxx | 2 +- tapset-procfs.cxx | 2 +- tapset-utrace.cxx | 2 +- tapsets.cxx | 12 ++++---- 8 files changed, 77 insertions(+), 72 deletions(-) diff --git a/elaborate.cxx b/elaborate.cxx index d1ebe326..9271e847 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -1108,7 +1108,7 @@ semantic_pass_symbols (systemtap_session& s) try { for (unsigned j=0; jbody = s.code_filters[j]->require (fd->body); + s.code_filters[j]->replace (fd->body); sym.current_function = fd; sym.current_probe = 0; @@ -1143,7 +1143,7 @@ semantic_pass_symbols (systemtap_session& s) try { for (unsigned k=0; kbody = s.code_filters[k]->require (dp->body); + s.code_filters[k]->replace (dp->body); sym.current_function = 0; sym.current_probe = dp; @@ -2136,8 +2136,8 @@ struct dead_assignment_remover: public update_visitor void dead_assignment_remover::visit_assignment (assignment* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); symbol* left = get_symbol_within_expression (e->left); vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target @@ -2203,10 +2203,10 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) // This instance may be reused for multiple probe/function body trims. for (unsigned i=0; ibody = dar.require (s.probes[i]->body); + dar.replace (s.probes[i]->body); for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) - it->second->body = dar.require (it->second->body); + dar.replace (it->second->body); // The rewrite operation is performed within the visitor. // XXX: we could also zap write-only globals here @@ -2290,8 +2290,8 @@ dead_stmtexpr_remover::visit_block (block *s) void dead_stmtexpr_remover::visit_if_statement (if_statement *s) { - s->thenblock = require (s->thenblock, true); - s->elseblock = require (s->elseblock, true); + replace (s->thenblock, true); + replace (s->elseblock, true); if (s->thenblock == 0) { @@ -2343,7 +2343,7 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) void dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) { - s->block = require(s->block, true); + replace (s->block, true); if (s->block == 0) { @@ -2357,7 +2357,7 @@ dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) void dead_stmtexpr_remover::visit_for_loop (for_loop *s) { - s->block = require(s->block, true); + replace (s->block, true); if (s->block == 0) { @@ -2446,7 +2446,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (p->locals.begin(), p->locals.end()); - p->body = duv.require(p->body, true); + duv.replace (p->body, true); if (p->body == 0) { if (! s.suppress_warnings @@ -2472,7 +2472,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (s.globals.begin(), s.globals.end()); - fn->body = duv.require(fn->body, true); + duv.replace (fn->body, true); if (fn->body == 0) { if (! s.suppress_warnings) @@ -2556,7 +2556,7 @@ struct void_statement_reducer: public update_visitor void void_statement_reducer::visit_expr_statement (expr_statement* s) { - s->value = require (s->value, true); + replace (s->value, true); // if the expression provides 0, that's our signal that a new // statement has been provided, so we shouldn't provide this one. @@ -2568,8 +2568,8 @@ void void_statement_reducer::visit_if_statement (if_statement* s) { // s->condition is never void - s->thenblock = require (s->thenblock); - s->elseblock = require (s->elseblock); + replace (s->thenblock); + replace (s->elseblock); provide (s); } @@ -2577,7 +2577,7 @@ void void_statement_reducer::visit_for_loop (for_loop* s) { // s->init/cond/incr are never void - s->block = require (s->block); + replace (s->block); provide (s); } @@ -2585,7 +2585,7 @@ void void_statement_reducer::visit_foreach_loop (foreach_loop* s) { // s->indexes/base/limit are never void - s->block = require (s->block); + replace (s->block); provide (s); } @@ -2884,10 +2884,10 @@ void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p) vuv.focal_vars.insert (s.globals.begin(), s.globals.end()); for (unsigned i=0; ibody = vuv.require (s.probes[i]->body); + vuv.replace (s.probes[i]->body); for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) - it->second->body = vuv.require (it->second->body); + vuv.replace (it->second->body); } diff --git a/staptree.cxx b/staptree.cxx index 11661442..8a589167 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -1287,7 +1287,7 @@ target_symbol::visit_components (update_visitor* u) { for (unsigned i = 0; i < components.size(); ++i) if (components[i].type == comp_expression_array_index) - components[i].expr_index = u->require (components[i].expr_index); + u->replace (components[i].expr_index); } void @@ -2205,7 +2205,7 @@ void update_visitor::visit_block (block* s) { for (unsigned i = 0; i < s->statements.size(); ++i) - s->statements[i] = require (s->statements[i]); + replace (s->statements[i]); provide (s); } @@ -2224,26 +2224,26 @@ update_visitor::visit_null_statement (null_statement* s) void update_visitor::visit_expr_statement (expr_statement* s) { - s->value = require (s->value); + replace (s->value); provide (s); } void update_visitor::visit_if_statement (if_statement* s) { - s->condition = require (s->condition); - s->thenblock = require (s->thenblock); - s->elseblock = require (s->elseblock); + replace (s->condition); + replace (s->thenblock); + replace (s->elseblock); provide (s); } void update_visitor::visit_for_loop (for_loop* s) { - s->init = require (s->init); - s->cond = require (s->cond); - s->incr = require (s->incr); - s->block = require (s->block); + replace (s->init); + replace (s->cond); + replace (s->incr); + replace (s->block); provide (s); } @@ -2251,24 +2251,24 @@ void update_visitor::visit_foreach_loop (foreach_loop* s) { for (unsigned i = 0; i < s->indexes.size(); ++i) - s->indexes[i] = require (s->indexes[i]); - s->base = require (s->base); - s->limit = require (s->limit); - s->block = require (s->block); + replace (s->indexes[i]); + replace (s->base); + replace (s->limit); + replace (s->block); provide (s); } void update_visitor::visit_return_statement (return_statement* s) { - s->value = require (s->value); + replace (s->value); provide (s); } void update_visitor::visit_delete_statement (delete_statement* s) { - s->value = require (s->value); + replace (s->value); provide (s); } @@ -2305,29 +2305,29 @@ update_visitor::visit_literal_number (literal_number* e) void update_visitor::visit_binary_expression (binary_expression* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); provide (e); } void update_visitor::visit_unary_expression (unary_expression* e) { - e->operand = require (e->operand); + replace (e->operand); provide (e); } void update_visitor::visit_pre_crement (pre_crement* e) { - e->operand = require (e->operand); + replace (e->operand); provide (e); } void update_visitor::visit_post_crement (post_crement* e) { - e->operand = require (e->operand); + replace (e->operand); provide (e); } @@ -2335,56 +2335,56 @@ update_visitor::visit_post_crement (post_crement* e) void update_visitor::visit_logical_or_expr (logical_or_expr* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); provide (e); } void update_visitor::visit_logical_and_expr (logical_and_expr* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); provide (e); } void update_visitor::visit_array_in (array_in* e) { - e->operand = require (e->operand); + replace (e->operand); provide (e); } void update_visitor::visit_comparison (comparison* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); provide (e); } void update_visitor::visit_concatenation (concatenation* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); provide (e); } void update_visitor::visit_ternary_expression (ternary_expression* e) { - e->cond = require (e->cond); - e->truevalue = require (e->truevalue); - e->falsevalue = require (e->falsevalue); + replace (e->cond); + replace (e->truevalue); + replace (e->falsevalue); provide (e); } void update_visitor::visit_assignment (assignment* e) { - e->left = require (e->left); - e->right = require (e->right); + replace (e->left); + replace (e->right); provide (e); } @@ -2404,7 +2404,7 @@ update_visitor::visit_target_symbol (target_symbol* e) void update_visitor::visit_cast_op (cast_op* e) { - e->operand = require (e->operand); + replace (e->operand); e->visit_components (this); provide (e); } @@ -2412,9 +2412,9 @@ update_visitor::visit_cast_op (cast_op* e) void update_visitor::visit_arrayindex (arrayindex* e) { - e->base = require (e->base); + replace (e->base); for (unsigned i = 0; i < e->indexes.size(); ++i) - e->indexes[i] = require (e->indexes[i]); + replace (e->indexes[i]); provide (e); } @@ -2422,7 +2422,7 @@ void update_visitor::visit_functioncall (functioncall* e) { for (unsigned i = 0; i < e->args.size(); ++i) - e->args[i] = require (e->args[i]); + replace (e->args[i]); provide (e); } @@ -2430,22 +2430,22 @@ void update_visitor::visit_print_format (print_format* e) { for (unsigned i = 0; i < e->args.size(); ++i) - e->args[i] = require (e->args[i]); - e->hist = require (e->hist); + replace (e->args[i]); + replace (e->hist); provide (e); } void update_visitor::visit_stat_op (stat_op* e) { - e->stat = require (e->stat); + replace (e->stat); provide (e); } void update_visitor::visit_hist_op (hist_op* e) { - e->stat = require (e->stat); + replace (e->stat); provide (e); } diff --git a/staptree.h b/staptree.h index bc479559..c9b2bdce 100644 --- a/staptree.h +++ b/staptree.h @@ -874,6 +874,11 @@ struct update_visitor: public visitor targets.push(static_cast(src)); } + template void replace (T*& src, bool clearok=false) + { + src = require(src, clearok); + } + virtual ~update_visitor() { assert(targets.empty()); } virtual void visit_block (block *s); diff --git a/tapset-mark.cxx b/tapset-mark.cxx index 59334729..6b4f47c5 100644 --- a/tapset-mark.cxx +++ b/tapset-mark.cxx @@ -223,7 +223,7 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s, // Now expand the local variables in the probe body mark_var_expanding_visitor v (sess, name, mark_args); - this->body = v.require (this->body); + v.replace (this->body); target_symbol_seen = v.target_symbol_seen; if (sess.verbose > 2) diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx index d524aa03..86806d61 100644 --- a/tapset-perfmon.cxx +++ b/tapset-perfmon.cxx @@ -153,7 +153,7 @@ perfmon_derived_probe::perfmon_derived_probe (probe* p, probe_point* l, // Now expand the local variables in the probe body perfmon_var_expanding_visitor v (sess, probes_allocated-1); - this->body = v.require (this->body); + v.replace (this->body); if (sess.verbose > 1) clog << "perfmon-based probe" << endl; diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx index 3302057c..527b4486 100644 --- a/tapset-procfs.cxx +++ b/tapset-procfs.cxx @@ -94,7 +94,7 @@ procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p, { // Expand local variables in the probe body procfs_var_expanding_visitor v (s, name, path, write); - this->body = v.require (this->body); + v.replace (this->body); target_symbol_seen = v.target_symbol_seen; } diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index 87053f7d..a07e08b8 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -120,7 +120,7 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s, { // Expand local variables in the probe body utrace_var_expanding_visitor v (s, l, name, flags); - this->body = v.require (this->body); + v.replace (this->body); target_symbol_seen = v.target_symbol_seen; // If during target-variable-expanding the probe, we added a new block diff --git a/tapsets.cxx b/tapsets.cxx index ba344c51..a105526c 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2089,7 +2089,7 @@ dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; expression *texp = tsym; - texp = require (texp); // NB: throws nothing ... + replace (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { @@ -2133,7 +2133,7 @@ dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; expression *texp = tsym; - texp = require (texp); // NB: throws nothing ... + replace (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { if (q.sess.verbose>2) @@ -2664,7 +2664,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, if (!null_die(scope_die)) { dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); - this->body = v.require (this->body); + v.replace (this->body); this->access_vars = v.visited; // If during target-variable-expanding the probe, we added a new block @@ -3391,7 +3391,7 @@ sdt_query::handle_query_module() sdt_var_expanding_visitor svv (module_val, probe_name, probe_arg, have_reg_args, probe_type == utrace_type); - new_base->body = svv.require (new_base->body); + svv.replace (new_base->body); unsigned i = results.size(); @@ -4148,7 +4148,7 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function, if (!null_die(scope_die)) { dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! - this->body = v.require (this->body); + v.replace (this->body); // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. @@ -5538,7 +5538,7 @@ tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s, // Now expand the local variables in the probe body tracepoint_var_expanding_visitor v (dw, name, args); - this->body = v.require (this->body); + v.replace (this->body); if (sess.verbose > 2) clog << "tracepoint-based " << name << " tracepoint='" << tracepoint_name -- cgit