+2006-02-23 Frank Ch. Eigler <fche@elastic.org>
+
+ 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 <roland@redhat.com>
* Makefile.am (AUTOMAKE_OPTIONS): New variable, set dist-bzip2.
// 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
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;
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;
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;
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?
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;
// 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
parser::parser (systemtap_session& s, istream& i, bool p):
session (s),
input_name ("<input>"), 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)
{ }
-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)
{ }
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;
}
{
public:
token* scan ();
- lexer (std::istream&, const std::string&);
+ lexer (std::istream&, const std::string&, systemtap_session&);
private:
int input_get ();
std::vector<int> lookahead;
unsigned cursor_line;
unsigned cursor_column;
+ systemtap_session& session;
};
+2006-02-23 Frank Ch. Eigler <fche@elastic.org>
+
+ 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 <fche@elastic.org>
PR 1937
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;
/* 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) {
* 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.
*
*/
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;
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");
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");
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");
.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
.\" -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.
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
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 ... $<NN>
+for casting as a numberic literal and
+.B @1 ... @<NN>
+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
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);";
}
--- /dev/null
+#! /bin/sh
+
+./stap -p2 -e 'probe begin { log (@1 . string($2)) }' hello 0xdeadbeef
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)
{
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);";
+ }
}