diff options
author | fche <fche> | 2005-07-05 20:38:37 +0000 |
---|---|---|
committer | fche <fche> | 2005-07-05 20:38:37 +0000 |
commit | f4b2849102b2a195dd79bede8ec58f46fb99435e (patch) | |
tree | ce9b211e38fc66caa1171584208595886067876a | |
parent | 6deb8173c053febfbf336d1e962cb01d93a12404 (diff) | |
download | systemtap-steved-f4b2849102b2a195dd79bede8ec58f46fb99435e.tar.gz systemtap-steved-f4b2849102b2a195dd79bede8ec58f46fb99435e.tar.xz systemtap-steved-f4b2849102b2a195dd79bede8ec58f46fb99435e.zip |
2005-07-05 Frank Ch. Eigler <fche@redhat.com>
* elaborate.h (systemtap_session): Add more command-line arguments.
* staptree.h (verbose): Bad global, no donut.
* elaborate.cxx: Temporarily disable verbose variable access.
* main.cxx: Support more arguments, build/run passes. Revamp
temporary file generation and partial-pass output generation.
* tapsets.cxx, translate.cxx: Emit just enough extra punctuation
and fluff to make generated probe pass -Werror.
* buildrun.cxx, buildrun.h: New files for passes 4/5. Partial
support for build pass, nothing on probe execution yet.
* testsuite/transok/*.stp: Force just -p3, now that -p4/5 exist.
* Makefile.am, Makefile.in: Corresponding changes.
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | Makefile.in | 7 | ||||
-rw-r--r-- | buildrun.cxx | 50 | ||||
-rw-r--r-- | buildrun.h | 18 | ||||
-rw-r--r-- | elaborate.cxx | 6 | ||||
-rw-r--r-- | elaborate.h | 19 | ||||
-rw-r--r-- | main.cxx | 267 | ||||
-rw-r--r-- | parse.cxx | 2 | ||||
-rw-r--r-- | staptree.h | 4 | ||||
-rw-r--r-- | tapsets.cxx | 10 | ||||
-rw-r--r-- | translate.cxx | 85 |
13 files changed, 392 insertions, 95 deletions
@@ -1 +1,3 @@ Frank Ch. Eigler <fche@redhat.com> +Graydon Hoare <graydon@redhat.com> + @@ -1,3 +1,17 @@ +2005-07-05 Frank Ch. Eigler <fche@redhat.com> + + * elaborate.h (systemtap_session): Add more command-line arguments. + * staptree.h (verbose): Bad global, no donut. + * elaborate.cxx: Temporarily disable verbose variable access. + * main.cxx: Support more arguments, build/run passes. Revamp + temporary file generation and partial-pass output generation. + * tapsets.cxx, translate.cxx: Emit just enough extra punctuation + and fluff to make generated probe pass -Werror. + * buildrun.cxx, buildrun.h: New files for passes 4/5. Partial + support for build pass, nothing on probe execution yet. + * testsuite/transok/*.stp: Force just -p3, now that -p4/5 exist. + * Makefile.am, Makefile.in: Corresponding changes. + 2005-07-04 Graydon Hoare <graydon@redhat.com> * elaborate.h (symresolution_info::current_derived_probe): New field. diff --git a/Makefile.am b/Makefile.am index 40bcd440..f56f71a0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,8 @@ AM_MAKEFLAGS = 'CXXFLAGS=$(CXXFLAGS)' 'LDFLAGS=$(LDFLAGS)' bin_PROGRAMS = noinst_PROGRAMS = stap stap_SOURCES = main.cxx \ - parse.cxx staptree.cxx elaborate.cxx translate.cxx tapsets.cxx + parse.cxx staptree.cxx elaborate.cxx translate.cxx \ + tapsets.cxx buildrun.cxx AM_CXXFLAGS = -Wall # Get extra libs as needed diff --git a/Makefile.in b/Makefile.in index 479563d5..26edb195 100644 --- a/Makefile.in +++ b/Makefile.in @@ -58,7 +58,8 @@ am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_stap_OBJECTS = main.$(OBJEXT) parse.$(OBJEXT) staptree.$(OBJEXT) \ - elaborate.$(OBJEXT) translate.$(OBJEXT) tapsets.$(OBJEXT) + elaborate.$(OBJEXT) translate.$(OBJEXT) tapsets.$(OBJEXT) \ + buildrun.$(OBJEXT) stap_OBJECTS = $(am_stap_OBJECTS) stap_LDADD = $(LDADD) stap_DEPENDENCIES = @@ -175,7 +176,8 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AM_MAKEFLAGS = 'CXXFLAGS=$(CXXFLAGS)' 'LDFLAGS=$(LDFLAGS)' stap_SOURCES = main.cxx \ - parse.cxx staptree.cxx elaborate.cxx translate.cxx tapsets.cxx + parse.cxx staptree.cxx elaborate.cxx translate.cxx \ + tapsets.cxx buildrun.cxx AM_CXXFLAGS = -Wall @@ -288,6 +290,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buildrun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elaborate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@ diff --git a/buildrun.cxx b/buildrun.cxx new file mode 100644 index 00000000..af22f1c8 --- /dev/null +++ b/buildrun.cxx @@ -0,0 +1,50 @@ +// build/run probes +// Copyright (C) 2005 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. + +#include "config.h" +#include "buildrun.h" + +#include <fstream> + +using namespace std; + + +int +compile_pass (systemtap_session& s) +{ + // fill in a quick Makefile + if (1) + { + // Assumes linux 2.6 kbuild + string makefile_nm = s.tmpdir + "/Makefile"; + ofstream o (makefile_nm.c_str()); + o << "CFLAGS += -Werror" << endl; + o << "CFLAGS += -I \"" << s.runtime_path << "\"" << endl; + o << "CFLAGS += -I \"" << s.runtime_path << "/relayfs\"" << endl; + o << "obj-m := " << s.module_name << ".o" << endl; + } + + // run module make + string module_dir = string("/lib/modules/") + s.kernel_release + "/build"; + string make_cmd = string("make") + + string (" -C \"") + module_dir + string("\""); + if (! s.verbose) make_cmd += " -s"; + make_cmd += string(" M=\"") + s.tmpdir + string("\" modules"); + + if (s.verbose) cerr << "Running " << make_cmd << endl; + int rc = system (make_cmd.c_str()); + if (s.verbose) cerr << "rc=" << rc << endl; + return rc; +} + + +int +run_pass (systemtap_session& s) +{ + return 1; +} diff --git a/buildrun.h b/buildrun.h new file mode 100644 index 00000000..88a63a5e --- /dev/null +++ b/buildrun.h @@ -0,0 +1,18 @@ +// -*- C++ -*- +// Copyright (C) 2005 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. + +#ifndef BUILDRUN_H +#define BUILDRUN_H + +#include "elaborate.h" + +int compile_pass (systemtap_session& s); +int run_pass (systemtap_session& s); + + +#endif // BUILDRUN_H diff --git a/elaborate.cxx b/elaborate.cxx index b6a64164..890d6f4a 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -174,18 +174,18 @@ match_node::find_builder(vector<probe_point::component *> const & components, // an entry in the sub table, and its value matches the rest // of the probe_point. match_key k(*components[pos]); - if (verbose) + if (0) // session.verbose clog << "searching for component " << k.str() << endl; map<match_key, match_node *>::const_iterator i = sub.find(k); if (i == sub.end()) { - if (verbose) + if (0) // session.verbose clog << "no match found" << endl; return NULL; } else { - if (verbose) + if (0) // session.verbose clog << "matched " << k.str() << endl; derived_probe_builder * builder = NULL; if (k.have_parameter) diff --git a/elaborate.h b/elaborate.h index 5855c92d..e61796fa 100644 --- a/elaborate.h +++ b/elaborate.h @@ -195,6 +195,22 @@ struct systemtap_session { systemtap_session (); + // command line args + std::vector<std::string> include_path; + std::vector<std::string> args; + std::string kernel_release; + std::string runtime_path; + std::string module_name; + int last_pass; + bool test_mode; + bool verbose; + bool keep_tmpdir; + + // temporary directory for module builds etc. + // hazardous - it is "rm -rf"'d at exit + std::string tmpdir; + std::string translated_source; // C source code + match_node * pattern_root; void register_library_aliases(); @@ -202,9 +218,6 @@ struct systemtap_session stapfile* user_file; std::vector<stapfile*> library_files; - // configuration options - // bool verbose_resolution; - // resolved globals/functions/probes for the run as a whole std::vector<stapfile*> files; std::vector<vardecl*> globals; @@ -1,4 +1,4 @@ -// systemtap translator driver +// systemtap translator/driver // Copyright (C) 2005 Red Hat Inc. // // This file is part of systemtap, and is free software. You can @@ -11,38 +11,67 @@ #include "parse.h" #include "elaborate.h" #include "translate.h" +#include "buildrun.h" #include <iostream> #include <fstream> #include <sstream> +#include <cerrno> extern "C" { #include <glob.h> #include <unistd.h> +#include <sys/utsname.h> +#include <time.h> } using namespace std; -bool verbose = false; -void usage () +void +usage (systemtap_session& s) { - cerr << "SystemTap translator " - << "(version " << VERSION << " built " << DATE << ")" << endl; - cerr << "Copyright (C) 2005 Red Hat, Inc." << endl; - cerr << "This is free software; see the source for copying conditions." << endl; - cerr << endl; - cerr << "Usage: stap [options] FILE [ARGS ...] Run script in file." << endl; - cerr << " or: stap [options] - [ARGS ...] Run script on stdin." << endl; - cerr << " or: stap [options] -e SCRIPT [ARGS ...] Run given script." << endl; - cerr << endl; - cerr << "Arguments:" << endl; - cerr << " -- No more options after this" << endl; - cerr << " -v verbose" << endl; - cerr << " -p NUM Stop after pass NUM 1-3" << endl; - cerr << " (parse, elaborate, translate)" << endl; - cerr << " -I DIR Look in DIR for additional .stp script files." << endl; - cerr << " -o FILE Send output to file instead of stdout." << endl; + cerr + << "SystemTap translator " + << "(version " << VERSION << " built " << DATE << ")" << endl + << "Copyright (C) 2005 Red Hat, Inc." << endl + << "This is free software; see the source for copying conditions." + << endl + << endl + << "Usage: stap [options] FILE [ARGS ...] Run script in file." + << endl + << " or: stap [options] - [ARGS ...] Run script on stdin." + << endl + << " or: stap [options] -e SCRIPT [ARGS ...] Run given script." + << endl + << endl + << "Arguments:" << endl + << " -- no more options after this" << endl + << " -v verbose" << (s.verbose ? " [set]" : "") + << endl + << " -t test mode" << (s.test_mode ? " [set]" : "") + << endl + << " -p NUM stop after pass NUM 1-5" << endl + << " (parse, elaborate, translate, compile, run)" << endl + << " -I DIR look in DIR for additional .stp script files"; + if (s.include_path.size() == 0) + cerr << endl; + else + cerr << ", instead of" << endl; + for (unsigned i=0; i<s.include_path.size(); i++) + cerr << " " << s.include_path[i] << endl; + cerr + << " -R DIR look in DIR for runtime, instead of " + << s.runtime_path + << endl + << " -r RELEASE use kernel RELEASE, instead of " + << s.kernel_release + << endl + << " -m MODULE set probe module name, insetad of " + << s.module_name + << endl + << " -o FILE send output to file instead of stdout" << endl + << " -k keep temporary directory" << endl; // XXX: other options: // -s: safe mode // -d: dump safety-related external references @@ -51,57 +80,97 @@ void usage () } +// little utility function + +template <typename T> +static string +stringify(T t) +{ + ostringstream s; + s << t; + return s.str (); +} + + int main (int argc, char * const argv []) { - int last_pass = 3; // -p NUM string cmdline_script; // -e PROGRAM string script_file; // FILE bool have_script = false; - string output_file; // -o FILE - vector<string> include_path; // -I DIR - vector<string> args; // ARGS + string output_file = "-"; // -o FILE + + // Initialize defaults + systemtap_session s; + struct utsname buf; + (void) uname (& buf); + s.kernel_release = string (buf.release); + s.verbose = false; + s.test_mode = false; + s.last_pass = 5; + s.runtime_path = "/usr/share/systemtap/runtime"; // XXX + s.module_name = "stap_" + stringify(getuid()) + "_" + stringify(time(0)); + s.keep_tmpdir = false; + while (true) { - int grc = getopt (argc, argv, "vp:I:e:o:"); + int grc = getopt (argc, argv, "vp:I:e:o:tR:r:m:k"); if (grc < 0) break; switch (grc) { case 'v': - verbose = true; + s.verbose = true; break; case 'p': - last_pass = atoi (optarg); - if (last_pass < 1 || last_pass > 3) + s.last_pass = atoi (optarg); + if (s.last_pass < 1 || s.last_pass > 5) { cerr << "Invalid pass number." << endl; - usage (); + usage (s); } break; case 'I': - include_path.push_back (string (optarg)); + s.include_path.push_back (string (optarg)); break; case 'e': if (have_script) - usage (); + usage (s); cmdline_script = string (optarg); have_script = true; break; case 'o': - if (output_file != "") - usage (); output_file = string (optarg); break; + case 't': + s.test_mode = true; + break; + + case 'R': + s.runtime_path = string (optarg); + break; + + case 'm': + s.module_name = string (optarg); + break; + + case 'r': + s.kernel_release = string (optarg); + break; + + case 'k': + s.keep_tmpdir = true; + break; + case '?': case 'h': default: - usage (); + usage (s); } } @@ -113,21 +182,32 @@ main (int argc, char * const argv []) have_script = true; } else - args.push_back (string (argv[i])); + s.args.push_back (string (argv[i])); } // need a user file if (! have_script) - usage(); + usage(s); + + int rc = 0; // arguments parsed; get down to business - int rc = 0; - systemtap_session s; - if (output_file != "") - s.op = new translator_output (output_file); - else - s.op = new translator_output (cout); + // Create a temporary directory to build within. + // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end. + { + char tmpdirt[] = "/tmp/stapXXXXXX"; + const char* tmpdir = mkdtemp (tmpdirt); + if (! tmpdir) + { + const char* e = strerror (errno); + cerr << "mkdtemp (\"" << tmpdir << "\"): " << e << endl; + s.tmpdir = ""; + rc = 1; + } + else + s.tmpdir = tmpdir; + } // PASS 1a: PARSING USER SCRIPT @@ -147,10 +227,10 @@ main (int argc, char * const argv []) rc ++; // PASS 1b: PARSING LIBRARY SCRIPTS - for (unsigned i=0; i<include_path.size(); i++) + for (unsigned i=0; i<s.include_path.size(); i++) { glob_t globbuf; - string dir = include_path[i] + "/*.stp"; + string dir = s.include_path[i] + "/*.stp"; int r = glob(dir.c_str (), 0, NULL, & globbuf); if (r == GLOB_NOSPACE || r == GLOB_ABORTED) rc ++; @@ -168,70 +248,119 @@ main (int argc, char * const argv []) globfree (& globbuf); } - if (last_pass == 1 && rc == 0) + if (rc == 0 && s.last_pass == 1) { - s.op->line() << "# parse tree dump"; - s.user_file->print (s.op->newline()); + cout << "# parse tree dump" << endl; + s.user_file->print (cout); + cout << endl; for (unsigned i=0; i<s.library_files.size(); i++) - s.library_files[i]->print (s.op->newline()); + { + s.library_files[i]->print (cout); + cout << endl; + } } + // PASS 2: ELABORATION - if (rc == 0 && last_pass > 1) + if (rc == 0 && s.last_pass > 1) rc = semantic_pass (s); - if (last_pass == 2 && rc == 0) + + if (rc == 0 && s.last_pass == 2) { if (s.globals.size() > 0) - s.op->line() << "# globals"; + cout << "# globals" << endl; for (unsigned i=0; i<s.globals.size(); i++) { vardecl* v = s.globals[i]; - v->printsig (s.op->newline()); + v->printsig (cout); + cout << endl; } if (s.functions.size() > 0) - s.op->newline() << "# functions"; + cout << "# functions" << endl; for (unsigned i=0; i<s.functions.size(); i++) { functiondecl* f = s.functions[i]; - f->printsig (s.op->newline()); - s.op->indent(1); + f->printsig (cout); + cout << endl; if (f->locals.size() > 0) - s.op->newline(1) << "# locals"; + cout << " # locals" << endl; for (unsigned j=0; j<f->locals.size(); j++) { vardecl* v = f->locals[j]; - v->printsig (s.op->newline()); + cout << " "; + v->printsig (cout); + cout << endl; } - s.op->indent(-1); } if (s.probes.size() > 0) - s.op->newline() << "# probes"; + cout << "# probes" << endl; for (unsigned i=0; i<s.probes.size(); i++) { derived_probe* p = s.probes[i]; - p->printsig (s.op->newline()); - s.op->indent(1); + p->printsig (cout); + cout << endl; if (p->locals.size() > 0) - s.op->newline() << "# locals"; + cout << " # locals" << endl; for (unsigned j=0; j<p->locals.size(); j++) { vardecl* v = p->locals[j]; - v->printsig (s.op->newline()); + cout << " "; + v->printsig (cout); + cout << endl; } - s.op->indent(-1); } - - s.op->newline(); } + // PASS 3: TRANSLATION - if (rc == 0 && last_pass > 2) - rc = translate_pass (s); + if (rc == 0 && s.last_pass > 2) + { + s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c"; + rc = translate_pass (s); + } + + if (rc == 0 && s.last_pass == 3) + { + ifstream i (s.translated_source.c_str()); + cout << i.rdbuf(); + } + + // PASS 4: COMPILATION + if (rc == 0 && s.last_pass > 3) + { + rc = compile_pass (s); + } + + // PASS 5: RUN + if (rc == 0 && s.last_pass > 4) + { + rc = run_pass (s); + } + + // Pull out saved output + if (output_file != "-") + s.op = new translator_output (output_file); + else + s.op = new translator_output (cout); + - s.op->line() << endl; - delete s.op; + // Clean up temporary directory. Obviously, be careful with this. + if (s.tmpdir == "") + ; // do nothing + else + { + if (s.keep_tmpdir) + cerr << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl; + else + { + string cleanupcmd = "/bin/rm -rf "; + cleanupcmd += s.tmpdir; + if (s.verbose) cerr << "Running " << cleanupcmd << endl; + (void) system (cleanupcmd.c_str()); + } + } return rc; } @@ -668,7 +668,7 @@ parser::parse_probe_point () probe_point* pl = new probe_point; // XXX: add support for probe point aliases - // e.g. probe a.b = a.c = a.d = foo + // e.g. probe alias = foo { ... } while (1) { const token* t = next (); @@ -14,7 +14,6 @@ #include <iostream> #include <stdexcept> -extern bool verbose; struct token; // parse.h struct semantic_error: public std::runtime_error @@ -377,7 +376,6 @@ struct probe_point component (); }; std::vector<component*> components; - // XXX: probe aliases const token* tok; // points to first component's functor void print (std::ostream& o); probe_point (); @@ -408,7 +406,7 @@ struct probe_alias }; -// An derived visitor instance is used to visit the entire +// A derived visitor instance is used to visit the entire // statement/expression tree. struct visitor { diff --git a/tapsets.cxx b/tapsets.cxx index a56fb659..160cb2fe 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -70,7 +70,7 @@ be_derived_probe::emit_registrations (translator_output* o, unsigned j) if (begin) for (unsigned i=0; i<locations.size(); i++) { - o->newline() << "enter_" << j << "_" << i << " ()"; + o->newline() << "enter_" << j << "_" << i << " ();"; o->newline() << "rc = errorcount;"; } else @@ -86,7 +86,7 @@ be_derived_probe::emit_deregistrations (translator_output* o, unsigned j) else for (unsigned i=0; i<locations.size(); i++) { - o->newline() << "enter_" << j << "_" << i << " ()"; + o->newline() << "enter_" << j << "_" << i << " ();"; o->newline() << "rc = errorcount;"; } } @@ -99,8 +99,8 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j) { probe_point *l = locations[i]; o->newline() << "/* location " << i << ": " << *l << " */"; - o->newline() << "static void enter_" << j << "_" << i << " ()"; - o->newline() << "{"; + o->newline() << "static void enter_" << j << "_" << i << " (void);"; + o->newline() << "void enter_" << j << "_" << i << " () {"; o->newline(1) << "struct context* c = & contexts [0];"; // XXX: assert #0 is free; need locked search instead o->newline() << "if (c->busy) { errorcount ++; return; }"; @@ -1063,6 +1063,8 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum o->newline(); o->newline() << "static void "; + o->newline() << probe_entry_function_name(probenum) << " (void);"; + o->newline() << "void "; o->newline() << probe_entry_function_name(probenum) << " ()"; o->newline() << "{"; o->newline(1) << "struct context* c = & contexts [0];"; diff --git a/translate.cxx b/translate.cxx index 7336d172..cb25044b 100644 --- a/translate.cxx +++ b/translate.cxx @@ -177,7 +177,13 @@ struct c_tmpcounter: public traversing_visitor void c_unparser::emit_common_header () { - o->newline() << "#include <string.h>"; + o->newline() << "#if TEST_MODE"; + o->newline() << "#include <string.h>"; + o->newline() << "#else"; + o->newline() << "#include <linux/string.h>"; + // XXX: tapsets.cxx should be able to add additional definitions + o->newline() << "#endif"; + o->newline() << "#define NR_CPU 1"; o->newline() << "#define MAXNESTING 30"; o->newline() << "#define MAXCONCURRENCY NR_CPU"; @@ -273,10 +279,14 @@ c_unparser::emit_functionsig (functiondecl* v) void c_unparser::emit_module_init () { - o->newline() << "int STARTUP () {"; + o->newline() << "static int systemtap_module_init (void);"; + o->newline() << "int systemtap_module_init () {"; o->newline(1) << "int anyrc = 0;"; o->newline() << "int rc;"; + // XXX: yuck runtime + o->newline() << "TRANSPORT_OPEN;"; + for (unsigned i=0; i<session->globals.size(); i++) { vardecl* v = session->globals[i]; @@ -315,7 +325,15 @@ c_unparser::emit_module_init () void c_unparser::emit_module_exit () { - o->newline() << "int SHUTDOWN () {"; + // XXX: double-yuck runtime + o->newline() << "void probe_exit () {"; + // need to reference these static functions for -Werror avoidance + o->newline(1) << "if (0) next_fmt ((void *) 0, (void *) 0);"; + o->newline() << "if (0) _stp_dbug(\"\", 0, \"\");"; + o->newline(-1) << "}"; + // + o->newline() << "static void systemtap_module_exit (void);"; + o->newline() << "void systemtap_module_exit () {"; o->newline(1) << "int anyrc = 0;"; o->newline() << "int rc;"; for (unsigned i=0; i<session->probes.size(); i++) @@ -324,7 +342,8 @@ c_unparser::emit_module_exit () o->newline() << "anyrc |= rc;"; } // XXX: uninitialize globals - o->newline() << "return anyrc; /* if (anyrc) log badness */"; + o->newline() << "_stp_transport_close ();"; + // XXX: if anyrc, log badness o->newline(-1) << "}" << endl; } @@ -332,7 +351,7 @@ c_unparser::emit_module_exit () void c_unparser::emit_function (functiondecl* v) { - o->newline() << "static void function_" << c_varname (v->name) + o->newline() << "void function_" << c_varname (v->name) << " (struct context* c) {"; o->indent(1); this->current_probe = 0; @@ -383,7 +402,8 @@ c_unparser::emit_function (functiondecl* v) void c_unparser::emit_probe (derived_probe* v, unsigned i) { - o->newline() << "static void probe_" << i << " (struct context *c) {"; + o->newline() << "static void probe_" << i << " (struct context *c);"; + o->newline() << "void probe_" << i << " (struct context *c) {"; o->indent(1); // initialize frame pointer @@ -1419,36 +1439,83 @@ translate_pass (systemtap_session& s) { int rc = 0; + s.op = new translator_output (s.translated_source); c_unparser cup (& s); s.up = & cup; try { - s.op->newline() << "/* common header */"; + s.op->line() << "#define TEST_MODE " << (s.test_mode ? 1 : 0) + << endl; + + // XXX: until the runtime can handle user-level tests properly + s.op->newline() << "#if ! TEST_MODE"; + s.op->newline() << "#define STP_NETLINK_ONLY"; // XXX + s.op->newline() << "#include \"runtime.h\""; + s.op->newline() << "#endif" << endl; + s.up->emit_common_header (); + s.op->newline() << "/* globals */"; for (unsigned i=0; i<s.globals.size(); i++) s.up->emit_global (s.globals[i]); + s.op->newline() << "/* function signatures */"; for (unsigned i=0; i<s.functions.size(); i++) s.up->emit_functionsig (s.functions[i]); + s.op->newline() << "/* functions */"; for (unsigned i=0; i<s.functions.size(); i++) s.up->emit_function (s.functions[i]); + s.op->newline() << "/* probes */"; for (unsigned i=0; i<s.probes.size(); i++) s.up->emit_probe (s.probes[i], i); - s.op->newline() << "/* module init */"; + s.up->emit_module_init (); - s.op->newline() << "/* module exit */"; s.up->emit_module_exit (); + + s.op->newline(); + s.op->newline() << "#if TEST_MODE"; + + s.op->newline() << "/* test mode mainline */"; + s.op->newline() << "int main () {"; + s.op->newline(1) << "int rc = systemtap_module_init ();"; + s.op->newline() << "if (!rc) rc = systemtap_module_exit ();"; + s.op->newline() << "return rc;"; + s.op->newline(-1) << "}"; + + s.op->newline() << "#else"; + s.op->newline(); + s.op->newline() << "static int __init _systemtap_module_init (void);"; + s.op->newline() << "int _systemtap_module_init () {"; + s.op->newline(1) << "return systemtap_module_init ();"; + s.op->newline(-1) << "}"; + + s.op->newline(); + s.op->newline() << "static void __exit _systemtap_module_exit (void);"; + s.op->newline() << "void _systemtap_module_exit () {"; + s.op->newline(1) << "systemtap_module_exit ();"; + s.op->newline(-1) << "}"; + + s.op->newline(); + s.op->newline() << "module_init (_systemtap_module_init);"; + s.op->newline() << "module_exit (_systemtap_module_exit);"; + s.op->newline() << "MODULE_DESCRIPTION(\"systemtap probe\");"; + s.op->newline() << "MODULE_LICENSE(\"GPL\");"; // XXX + + s.op->newline() << "#endif"; + + s.op->line() << endl; } catch (const semantic_error& e) { s.print_error (e); } + delete s.op; + s.op = 0; s.up = 0; return rc + s.num_errors; } |