From: fche Date: Thu, 23 Feb 2006 22:35:40 +0000 (+0000) Subject: 2006-02-23 Frank Ch. Eigler X-Git-Tag: release-0.5.5~68 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=213bee8fc2b826ca8467fbbe35398450449bf082;p=systemtap.git 2006-02-23 Frank Ch. Eigler PR 1304 * parse.cxx (lexer): Take systemtap_session argument. (lexer::scan): Support $1..$NNNN and @1...@NNNN expansion. * stap.1.in: Document this. * testsuite/semok/args.stp: New test. * translate.cxx (var::init, emit_global): Emit code to allow named module parameters to initialize global string/number scalars. * stap.1.in: Don't document this yet. PR 2334 * main.cxx (main): Clarify "-v" option repeatibility. * stap.1.in: Ditto. --- diff --git a/ChangeLog b/ChangeLog index 469c43b77..ea9c44d79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-02-23 Frank Ch. Eigler + + PR 1304 + * parse.cxx (lexer): Take systemtap_session argument. + (lexer::scan): Support $1..$NNNN and @1...@NNNN expansion. + * stap.1.in: Document this. + * testsuite/semok/args.stp: New test. + * translate.cxx (var::init, emit_global): Emit code to allow + named module parameters to initialize global string/number scalars. + * stap.1.in: Don't document this yet. + + PR 2334 + * main.cxx (main): Clarify "-v" option repeatibility. + * stap.1.in: Ditto. + 2006-02-23 Roland McGrath * Makefile.am (AUTOMAKE_OPTIONS): New variable, set dist-bzip2. diff --git a/main.cxx b/main.cxx index 127e667d8..27e0cdd45 100644 --- a/main.cxx +++ b/main.cxx @@ -1,5 +1,5 @@ // systemtap translator/driver -// Copyright (C) 2005 Red Hat Inc. +// Copyright (C) 2005-2006 Red Hat Inc. // Copyright (C) 2005 IBM Corp. // // This file is part of systemtap, and is free software. You can @@ -405,7 +405,7 @@ main (int argc, char * const argv []) if (rc) cerr << "Pass 1: parse failed. " - << (s.verbose ? "" : "Try again with '-v' (verbose) option.") + << "Try again with more '-v' (verbose) options." << endl; if (rc || s.last_pass == 1) goto cleanup; @@ -486,7 +486,7 @@ main (int argc, char * const argv []) if (rc) cerr << "Pass 2: analysis failed. " - << (s.verbose ? "" : "Try again with '-v' (verbose) option.") + << "Try again with more '-v' (verbose) options." << endl; if (rc || s.last_pass == 2) goto cleanup; @@ -516,7 +516,7 @@ main (int argc, char * const argv []) if (rc) cerr << "Pass 3: translation failed. " - << (s.verbose ? "" : "Try again with '-v' (verbose) option.") + << "Try again with more '-v' (verbose) options." << endl; if (rc || s.last_pass == 3) goto cleanup; @@ -536,7 +536,7 @@ main (int argc, char * const argv []) if (rc) cerr << "Pass 4: compilation failed. " - << (s.verbose ? "" : "Try again with '-v' (verbose) option.") + << "Try again with more '-v' (verbose) options." << endl; // XXX: what to do if rc==0 && last_pass == 4? dump .ko file to stdout? @@ -558,7 +558,7 @@ main (int argc, char * const argv []) if (rc) cerr << "Pass 5: run failed. " - << (s.verbose ? "" : "Try again with '-v' (verbose) option.") + << "Try again with more '-v' (verbose) options." << endl; // if (rc) goto cleanup; diff --git a/parse.cxx b/parse.cxx index dcdb72603..04e01ebc0 100644 --- a/parse.cxx +++ b/parse.cxx @@ -1,5 +1,5 @@ // recursive descent parser for systemtap scripts -// Copyright (C) 2005 Red Hat Inc. +// Copyright (C) 2005-2006 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 @@ -28,14 +28,14 @@ using namespace std; parser::parser (systemtap_session& s, istream& i, bool p): session (s), input_name (""), free_input (0), - input (i, input_name), privileged (p), + input (i, input_name, s), privileged (p), last_t (0), next_t (0), num_errors (0) { } parser::parser (systemtap_session& s, const string& fn, bool p): session (s), input_name (fn), free_input (new ifstream (input_name.c_str(), ios::in)), - input (* free_input, input_name), privileged (p), + input (* free_input, input_name, s), privileged (p), last_t (0), next_t (0), num_errors (0) { } @@ -397,8 +397,8 @@ parser::peek_kw (std::string const & kw) -lexer::lexer (istream& i, const string& in): - input (i), input_name (in), cursor_line (1), cursor_column (1) +lexer::lexer (istream& i, const string& in, systemtap_session& s): + input (i), input_name (in), cursor_line (1), cursor_column (1), session(s) { } @@ -472,6 +472,31 @@ lexer::scan () else break; } + + // Expand command line arguments to literals. $1 .. $999 as + // numbers and @1 .. @999 as strings. + if (n->content[0] == '@' || n->content[0] == '$') + { + string idxstr = n->content.substr(1); + const char* startp = idxstr.c_str(); + char *endp; + errno = 0; + unsigned long idx = strtoul (startp, &endp, 10); + if (endp == startp) + ; // no numbers at all - leave alone as identifier + else + { + // Use @1/$1 as the base, not @0/$0. Thus the idx-1. + if (errno == ERANGE || errno == EINVAL || *endp != '\0' || + idx == 0 || idx-1 >= session.args.size ()) + throw parse_error ("command line argument index invalid or out of range"); + + string arg = session.args[idx-1]; + n->type = (n->content[0] == '@') ? tok_string : tok_number; + n->content = arg; + } + } + return n; } diff --git a/parse.h b/parse.h index 81544eb9f..b9d561527 100644 --- a/parse.h +++ b/parse.h @@ -57,7 +57,7 @@ class lexer { public: token* scan (); - lexer (std::istream&, const std::string&); + lexer (std::istream&, const std::string&, systemtap_session&); private: int input_get (); @@ -67,6 +67,7 @@ private: std::vector lookahead; unsigned cursor_line; unsigned cursor_column; + systemtap_session& session; }; diff --git a/runtime/stpd/ChangeLog b/runtime/stpd/ChangeLog index e72ec4d04..1695cf6ec 100644 --- a/runtime/stpd/ChangeLog +++ b/runtime/stpd/ChangeLog @@ -1,3 +1,10 @@ +2006-02-23 Frank Ch. Eigler + + PR 1304 + * stpd.c (mdooptions): New array. + (main): Populate it with leftover arguments. + * librelay.c (init_stp): Pass it to execve(). + 2005-12-08 Frank Ch. Eigler PR 1937 diff --git a/runtime/stpd/librelay.c b/runtime/stpd/librelay.c index e2beece2d..719f026d1 100644 --- a/runtime/stpd/librelay.c +++ b/runtime/stpd/librelay.c @@ -83,6 +83,7 @@ extern int print_only, quiet, merge, verbose; extern unsigned int buffer_size; extern char *modname; extern char *modpath; +extern char *modoptions[]; extern int target_pid; extern int driver_pid; extern char *target_cmd; @@ -460,11 +461,16 @@ int init_stp(const char *relay_filebase, int print_summary) /* insert module */ sprintf(buf, "_stp_pid=%d", (int)getpid()); + modoptions[0] = "insmod"; + modoptions[1] = modpath; + modoptions[2] = buf; + /* modoptions[3...N] set by command line parser. */ + if ((pid = vfork()) < 0) { perror ("vfork"); exit(-1); } else if (pid == 0) { - if (execl("/sbin/insmod", "insmod", modpath, buf, NULL) < 0) + if (execvp("/sbin/insmod", modoptions) < 0) exit(-1); } if (waitpid(pid, &rstatus, 0) < 0) { diff --git a/runtime/stpd/stpd.c b/runtime/stpd/stpd.c index c12ca0969..c6cc913d4 100644 --- a/runtime/stpd/stpd.c +++ b/runtime/stpd/stpd.c @@ -15,8 +15,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * Copyright (C) IBM Corporation, 2005 - * Copyright (C) Red Hat Inc, 2005 + * Copyright (C) 2005 IBM Corporation + * Copyright (C) 2005-2006 Red Hat, Inc. * */ @@ -41,6 +41,8 @@ int driver_pid = 0; unsigned int buffer_size = 0; char *modname = NULL; char *modpath = NULL; +#define MAXMODOPTIONS 64 +char *modoptions[MAXMODOPTIONS]; char *target_cmd = NULL; char *outfile_name = NULL; @@ -59,7 +61,8 @@ char *stp_check="stp_check"; static void usage(char *prog) { - fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-c cmd ] [-t pid] [-b bufsize] [-o FILE] kmod-name\n", prog); + fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-c cmd ] [-t pid]\n" + "\t[-b bufsize] [-o FILE] kmod-name [kmod-options]\n", prog); fprintf(stderr, "-m Don't merge per-cpu files.\n"); fprintf(stderr, "-p Print only. Don't log to files.\n"); fprintf(stderr, "-q Quiet. Don't display trace to stdout.\n"); @@ -68,8 +71,8 @@ static void usage(char *prog) fprintf(stderr, " _stp_target will contain the pid for the command.\n"); fprintf(stderr, "-t pid. Sets _stp_target to pid.\n"); fprintf(stderr, "-d pid. Pass the systemtap driver's pid.\n"); - fprintf(stderr, "-b buffer size. The systemtap module will specify a buffer size.\n"); fprintf(stderr, "-o FILE. Send output to FILE.\n"); + fprintf(stderr, "-b buffer size. The systemtap module will specify a buffer size.\n"); fprintf(stderr, " Setting one here will override that value. The value should be\n"); fprintf(stderr, " an integer between 1 and 64 which be assumed to be the\n"); fprintf(stderr, " buffer size in MB. That value will be per-cpu if relayfs is used.\n"); @@ -143,6 +146,16 @@ int main(int argc, char **argv) else modname++; /* skip over / */ } + + if (optind < argc) + { + unsigned start_idx = 3; /* reserve three slots in modoptions[] */ + while (optind < argc && start_idx+1 < MAXMODOPTIONS) + modoptions[start_idx++] = argv[optind++]; + /* Redundantly ensure that there is a NULL pointer at the end + of modoptions[]. */ + modoptions[start_idx] = NULL; + } if (!modname) { fprintf (stderr, "Cannot invoke daemon without probe module\n"); diff --git a/stap.1.in b/stap.1.in index 48fc7dcb8..c3ce07257 100644 --- a/stap.1.in +++ b/stap.1.in @@ -24,18 +24,27 @@ stap \- systemtap script translator/driver .I OPTIONS ] .I FILENAME +[ +.I ARGUMENTS +] .br .B stap [ .I OPTIONS ] .B \- +[ +.I ARGUMENTS +] .br .B stap [ .I OPTIONS ] .BI \-e " SCRIPT" +[ +.I ARGUMENTS +] .SH DESCRIPTION @@ -72,7 +81,8 @@ prints a list of supported options. .\" -t test mode .TP .B \-v -Increase verbosity. Produce more informative output. +Increase verbosity. Produce a larger volume of informative (?) output +each time option repeated. .TP .B \-h Show help message. @@ -133,6 +143,11 @@ Start the probes, run CMD, and exit when CMD finishes. Sets target() to PID. This allows scripts to be written that filter on a specific process. +.SH ARGUMENTS + +Any additional arguments on the command line are passed to the script +parser for substitution. See below. + .SH SCRIPT LANGUAGE The systemtap script language resembles @@ -158,6 +173,15 @@ are limited in length to some reasonable value (a few hundred bytes). Integers are 64-bit signed quantities, although the parser also accepts (and wraps around) values above positive 2**63. .PP +In addition, script arguments given at the end of the command line may +be expanded as literals. Use +.B $1 ... $ +for casting as a numberic literal and +.B @1 ... @ +for casting as string literal. These may be used in all contexts +where literals are accepted. Reference to an argument number beyond +what was actually given is an error. +.PP A simple conditional preprocessing stage is run as a part of parsing. The general form is similar to the .RB cond " ? " exp1 " : " exp2 diff --git a/tapsets.cxx b/tapsets.cxx index 31b2515a0..2e2c933ea 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -137,7 +137,7 @@ derived_probe::emit_probe_epilogue (translator_output* o) o->newline(-1) << "}"; o->newline() << "atomic_dec (&c->busy);"; - o->newline(-1) << "probe_epilogue: ;"; + o->newline(-1) << "probe_epilogue:"; o->newline(1) << "local_irq_restore (flags);"; } diff --git a/testsuite/semok/args.stp b/testsuite/semok/args.stp new file mode 100755 index 000000000..004756259 --- /dev/null +++ b/testsuite/semok/args.stp @@ -0,0 +1,3 @@ +#! /bin/sh + +./stap -p2 -e 'probe begin { log (@1 . string($2)) }' hello 0xdeadbeef diff --git a/translate.cxx b/translate.cxx index becb7bcd7..1b08af99a 100644 --- a/translate.cxx +++ b/translate.cxx @@ -371,7 +371,10 @@ public: case pe_string: return qname() + "[0] = '\\0';"; case pe_long: - return qname() + " = 0;"; + if (! local) + return qname() + " = (int64_t) init_" + qname() + ";"; // module_param + else + return qname() + " = 0;"; case pe_stats: switch (sd.type) { @@ -887,24 +890,44 @@ c_unparser::emit_common_header () void c_unparser::emit_global (vardecl *v) { + string vn = c_varname (v->name); + if (v->arity == 0) o->newline() << "static " << c_typename (v->type) << " " - << "global_" << c_varname (v->name) + << "global_" << vn << ";"; else if (v->type == pe_stats) { o->newline() << "static PMAP global_" - << c_varname(v->name) << ";"; + << vn << ";"; } else { o->newline() << "static MAP global_" - << c_varname(v->name) << ";"; + << vn << ";"; } o->newline() << "static rwlock_t " - << "global_" << c_varname (v->name) << "_lock;"; + << "global_" << vn << "_lock;"; + + // Emit module_params for this global, if its type is convenient. + if (v->arity == 0 && v->type == pe_long) + { + // XXX: moduleparam.h does not have a 64-bit type, so let's just + // take a plain long here, and manually copy/widen during + // initialization. See var::init(). + o->newline() << "long init_global_" << vn << ";"; + o->newline() << "module_param_named (" << vn << ", " + << "init_global_" << vn << ", long, 0);"; + } + else if (v->arity == 0 && v->type == pe_string) + { + // NB: no special copying is needed. + o->newline() << "module_param_string (" << vn << ", " + << "global_" << vn + << ", MAXSTRINGLEN, 0);"; + } }