summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--elaborate.cxx1
-rw-r--r--parse.cxx1
-rwxr-xr-xruntest.sh7
-rw-r--r--runtime/ChangeLog4
-rw-r--r--runtime/arith.c22
-rw-r--r--tapset/builtin_logging.stp5
-rw-r--r--tapsets.cxx47
-rw-r--r--translate.cxx77
9 files changed, 111 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index 20674647..56df0301 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2005-08-21 Frank Ch. Eigler <fche@redhat.com>
+
+ PR systemtap/1195, systemtap/1193
+ * elaborate.cxx (alias_expansion_builder): Set new block token.
+ * parse.cxx (parse_symbol): Set new target_symbol token.
+ * runtest.sh: Store more pertinent failure data.
+ * tapsets.cxx (emit_probe_entries): Rewrite error-handling path.
+ * translate.cxx (emit_common_header): Goodbye errorcount, hello
+ last_error & last_stmt.
+ (c_unparser::visit_statement): New "header" for all other stmts.
+ (c_assignop, visit_binary_expression): Adapt to last_error.
+ * tapset/builtin_logging.stp: Adapt to last_error.
+
2005-08-19 Frank Ch. Eigler <fche@elastic.org>
PR systemtap/1213
diff --git a/elaborate.cxx b/elaborate.cxx
index 53cab841..232f91a5 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -290,6 +290,7 @@ alias_expansion_builder
// the token location of the use,
n->tok = use->tok;
+ n->body->tok = use->tok;
// and statements representing the concatenation of the alias'
// body with the use's.
diff --git a/parse.cxx b/parse.cxx
index 15f2b0f1..5b25a9c0 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -1621,6 +1621,7 @@ parser::parse_symbol ()
{
// target_symbol time
target_symbol *tsym = new target_symbol;
+ tsym->tok = t;
tsym->base_name = name;
while (true)
{
diff --git a/runtest.sh b/runtest.sh
index 1c548fa4..14bd87c6 100755
--- a/runtest.sh
+++ b/runtest.sh
@@ -18,16 +18,19 @@ export SYSTEMTAP_RUNTIME
dn=`dirname $1`
logfile=testsuite/`basename $dn`-`basename $1`
+env | grep SYSTEMTAP > $logfile.cmd
+echo "$@" >> $logfile.cmd
eval $@ >$logfile.out 2>$logfile.err
rc=$?
+echo "rc=$rc" > $logfile.rc
if expr $1 : '.*ok/.*' >/dev/null; then
if [ $rc -eq 0 ]; then
- rm -f $logfile.out $logfile.err
+ rm -f $logfile.*
fi
else
if [ $rc -eq 1 ]; then
- rm -f $logfile.out $logfile.err
+ rm -f $logfile.*
fi
fi
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index f4f791dd..b9c92140 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,7 @@
+2005-08-21 Frank Ch. Eigler <fche@redhat.com>
+
+ * arith.c (*): Adapt to last_error context variable.
+
2005-08-19 Frank Ch. Eigler <fche@elastic.org>
* arith.c (_stp_random_pm): New function.
diff --git a/runtime/arith.c b/runtime/arith.c
index 0200afa6..b1759e2a 100644
--- a/runtime/arith.c
+++ b/runtime/arith.c
@@ -7,14 +7,14 @@
struct context;
-void _stp_divmod64 (unsigned *errorcount, int64_t x, int64_t y,
+void _stp_divmod64 (const char **error, int64_t x, int64_t y,
int64_t *quo, int64_t *rem);
/** Divide x by y. In case of overflow or division-by-zero,
- * increment context errorcount, and return any old value.
+ * set context error string, and return any old value.
*/
-inline int64_t _stp_div64 (unsigned *errorcount, int64_t x, int64_t y)
+inline int64_t _stp_div64 (const char **error, int64_t x, int64_t y)
{
if (likely ((x >= LONG_MIN && x <= LONG_MAX) &&
(y >= LONG_MIN && y <= LONG_MAX)))
@@ -24,7 +24,7 @@ inline int64_t _stp_div64 (unsigned *errorcount, int64_t x, int64_t y)
// check for division-by-zero and overflow
if (unlikely (yy == 0 || (xx == LONG_MIN && yy == -1)))
{
- (*errorcount) ++;
+ *error = "divisor out of range";
return 0;
}
return xx / yy;
@@ -32,16 +32,16 @@ inline int64_t _stp_div64 (unsigned *errorcount, int64_t x, int64_t y)
else
{
int64_t quo = 0;
- _stp_divmod64 (errorcount, x, y, &quo, NULL);
+ _stp_divmod64 (error, x, y, &quo, NULL);
return quo;
}
}
/** Modulo x by y. In case of overflow or division-by-zero,
- * increment context errorcount, and return any old value.
+ * set context error string, and return any old value.
*/
-inline int64_t _stp_mod64 (unsigned *errorcount, int64_t x, int64_t y)
+inline int64_t _stp_mod64 (const char **error, int64_t x, int64_t y)
{
if (likely ((x >= LONG_MIN && x <= LONG_MAX) &&
(y >= LONG_MIN && y <= LONG_MAX)))
@@ -51,7 +51,7 @@ inline int64_t _stp_mod64 (unsigned *errorcount, int64_t x, int64_t y)
// check for division-by-zero and overflow
if (unlikely (yy == 0 || (xx == LONG_MIN && yy == -1)))
{
- (*errorcount) ++;
+ *error = "divisor out of range";
return 0;
}
return xx % yy;
@@ -59,18 +59,18 @@ inline int64_t _stp_mod64 (unsigned *errorcount, int64_t x, int64_t y)
else
{
int64_t rem = 0;
- _stp_divmod64 (errorcount, x, y, NULL, &rem);
+ _stp_divmod64 (error, x, y, NULL, &rem);
return rem;
}
}
/** Perform general long division/modulus. */
-void _stp_divmod64 (unsigned *errorcount, int64_t x, int64_t y,
+void _stp_divmod64 (const char **error, int64_t x, int64_t y,
int64_t *quo, int64_t *rem)
{
// XXX: wimp out for now
- (*errorcount) ++;
+ *error = "general division unsupported";
if (quo) *quo = 0;
if (rem) *rem = 0;
}
diff --git a/tapset/builtin_logging.stp b/tapset/builtin_logging.stp
index 11b00cab..bf01a0fc 100644
--- a/tapset/builtin_logging.stp
+++ b/tapset/builtin_logging.stp
@@ -25,12 +25,13 @@ function warn (msg) {
}
function exit () %{
- CONTEXT->errorcount ++; /* kill current probe */
+ /* not a NULL pointer, but don't cause _stp_error */
+ CONTEXT->last_error = "";
_stp_exit ();
%}
function _error (msg) %{
- CONTEXT->errorcount ++; /* kill current probe */
+ CONTEXT->last_error = "called error()"; /* kill current probe */
_stp_error ("%s", THIS->msg); /* implies _stp_exit */
%}
diff --git a/tapsets.cxx b/tapsets.cxx
index 45a77a8a..43f18c66 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -118,21 +118,17 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
o->newline() << "c->busy ++;";
o->newline() << "mb ();"; // for smp
- o->newline() << "c->errorcount = 0;";
- o->newline() << "c->actioncount = 0;";
+ o->newline() << "c->last_error = 0;";
o->newline() << "c->nesting = 0;";
o->newline() << "c->regs = 0;";
+ o->newline() << "c->actioncount = 0;";
// NB: locals are initialized by probe function itself
o->newline() << "probe_" << j << " (c);";
- // see translate.cxx: visit_functioncall and elsewhere to see all the
- // possible context indications that a probe exited prematurely
- o->newline() << "if (c->errorcount || c->actioncount > MAXACTION"
- << " || c->nesting+2 >= MAXNESTING) {";
- o->newline(1) << "printk (KERN_ERR \"probe execution failure (e%d,n%d,a%d)\",";
- o->newline(1) << "c->errorcount, c->nesting, c->actioncount);";
- o->newline(-1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+ o->newline() << "if (c->last_error) {";
+ o->newline(1) << "if (c->last_error[0]) _stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
+ o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
o->newline(-1) << "}";
o->newline() << "c->busy --;";
@@ -860,7 +856,7 @@ dwflpp
if (deref) ;
fprintf(memstream,
"deref_fault:\n"
- " c->errorcount++; \n"
+ " c->last_error = \"pointer dereference fault\";\n"
" goto out;\n");
fclose (memstream);
@@ -1460,6 +1456,7 @@ var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
// synthesize a function
functiondecl *fdecl = new functiondecl;
embeddedcode *ec = new embeddedcode;
+ ec->tok = e->tok;
ec->code = q.dw.literal_stmt_for_local(addr,
e->base_name.substr(1),
e->components);
@@ -1709,20 +1706,17 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum
o->newline() << "c->busy ++;";
o->newline() << "mb ();"; // for smp
- o->newline() << "c->errorcount = 0;";
- o->newline() << "c->actioncount = 0;";
+ o->newline() << "c->last_error = 0;";
o->newline() << "c->nesting = 0;";
o->newline() << "c->regs = regs;";
+ o->newline() << "c->actioncount = 0;";
+
// NB: locals are initialized by probe function itself
o->newline() << "probe_" << probenum << " (c);";
- // see translate.cxx: visit_functioncall and elsewhere to see all the
- // possible context indications that a probe exited prematurely
- o->newline() << "if (c->errorcount || c->actioncount > MAXACTION"
- << " || c->nesting+2 >= MAXNESTING) {";
- o->newline(1) << "printk (KERN_ERR \"probe execution failure (e%d,n%d,a%d)\",";
- o->newline(1) << "c->errorcount, c->nesting, c->actioncount);";
- o->newline(-1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+ o->newline() << "if (c->last_error) {";
+ o->newline(1) << "if (c->last_error[0]) _stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
+ o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
o->newline(-1) << "}";
o->newline() << "c->busy --;";
@@ -1876,26 +1870,21 @@ timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
o->newline() << "c->busy ++;";
o->newline() << "mb ();"; // for smp
- o->newline() << "c->errorcount = 0;";
- o->newline() << "c->actioncount = 0;";
+ o->newline() << "c->last_error = 0;";
o->newline() << "c->nesting = 0;";
-
o->newline() << "if (! in_interrupt())";
o->newline(1) << "c->regs = 0;";
o->newline(-1) << "else";
o->newline(1) << "c->regs = task_pt_regs (current);";
o->indent(-1);
+ o->newline() << "c->actioncount = 0;";
// NB: locals are initialized by probe function itself
o->newline() << "probe_" << j << " (c);";
- // see translate.cxx: visit_functioncall and elsewhere to see all the
- // possible context indications that a probe exited prematurely
- o->newline() << "if (c->errorcount || c->actioncount > MAXACTION"
- << " || c->nesting+2 >= MAXNESTING) {";
- o->newline(1) << "printk (KERN_ERR \"probe execution failure (e%d,n%d,a%d)\",";
- o->newline(1) << "c->errorcount, c->nesting, c->actioncount);";
- o->newline(-1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+ o->newline() << "if (c->last_error) {";
+ o->newline(1) << "if (c->last_error[0]) _stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
+ o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
o->newline(-1) << "}";
o->newline() << "c->busy --;";
diff --git a/translate.cxx b/translate.cxx
index 3a8d0bec..9c1167fd 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -95,6 +95,8 @@ struct c_unparser: public unparser, public visitor
set< exp_type > & value_types,
set< vector<exp_type> > & index_types);
+ void visit_statement (statement* s, unsigned actions);
+
void visit_block (block* s);
void visit_embeddedcode (embeddedcode* s);
void visit_null_statement (null_statement* s);
@@ -530,8 +532,9 @@ c_unparser::emit_common_header ()
o->newline() << "struct context {";
o->newline(1) << "unsigned busy;";
o->newline() << "unsigned actioncount;";
- o->newline() << "unsigned errorcount;";
o->newline() << "unsigned nesting;";
+ o->newline() << "const char *last_error;";
+ o->newline() << "const char *last_stmt;";
o->newline() << "struct pt_regs *regs;";
o->newline() << "union {";
o->indent(1);
@@ -767,9 +770,7 @@ c_unparser::emit_function (functiondecl* v)
o->newline() << retvalue.init();
}
- o->newline(1) << "{"; // in case body is embeddedcode with decls
v->body->visit (this);
- o->newline(-1) << "}";
this->current_function = 0;
@@ -1110,10 +1111,10 @@ c_unparser_assignment::c_assignop(tmpvar & res,
else
{
if (macop == "/")
- o->newline() << res << " = _stp_div64 (&c->errorcount, "
+ o->newline() << res << " = _stp_div64 (&c->last_error, "
<< lval << ", " << rval << ");";
else if (macop == "%")
- o->newline() << res << " = _stp_mod64 (&c->errorcount, "
+ o->newline() << res << " = _stp_mod64 (&c->last_error, "
<< lval << ", " << rval << ");";
else
o->newline() << res << " = " << lval << " " << macop << " " << rval << ";";
@@ -1246,20 +1247,37 @@ c_unparser::getiter(foreach_loop *f)
}
+
+// An artificial common "header" for each statement. This is where
+// activity counts limits and error state early exits are enforced.
+void
+c_unparser::visit_statement (statement *s, unsigned actions)
+{
+ o->newline() << "if (unlikely (c->last_error)) goto out;";
+ assert (s->tok);
+ o->newline() << "c->last_stmt = \"" << *s->tok << "\";";
+ if (actions > 0)
+ {
+ o->newline() << "c->actioncount += " << actions << ";";
+ o->newline() << "if (unlikely (c->actioncount > MAXACTION)) {";
+ o->newline(1) << "c->last_error = \"MAXACTION exceeded\";";
+ o->newline() << "goto out;";
+ o->newline(-1) << "}";
+ }
+}
+
+
void
c_unparser::visit_block (block *s)
{
o->newline() << "{";
o->indent (1);
- o->newline() << "c->actioncount += " << s->statements.size() << ";";
- o->newline() << "if (unlikely (c->actioncount > MAXACTION)) goto out;";
+ visit_statement (s, 0);
for (unsigned i=0; i<s->statements.size(); i++)
{
try
{
- // XXX: it's probably not necessary to check this so frequently
- o->newline() << "if (unlikely (c->errorcount)) goto out;";
s->statements[i]->visit (this);
o->newline();
}
@@ -1275,13 +1293,17 @@ c_unparser::visit_block (block *s)
void
c_unparser::visit_embeddedcode (embeddedcode *s)
{
- o->newline() << s->code;
+ visit_statement (s, 1);
+ o->newline() << "{";
+ o->newline(1) << s->code;
+ o->newline(-1) << "}";
}
void
c_unparser::visit_null_statement (null_statement *s)
{
+ visit_statement (s, 0);
o->newline() << "/* null */;";
}
@@ -1289,6 +1311,7 @@ c_unparser::visit_null_statement (null_statement *s)
void
c_unparser::visit_expr_statement (expr_statement *s)
{
+ visit_statement (s, 1);
o->newline() << "(void) ";
s->value->visit (this);
o->line() << ";";
@@ -1298,6 +1321,7 @@ c_unparser::visit_expr_statement (expr_statement *s)
void
c_unparser::visit_if_statement (if_statement *s)
{
+ visit_statement (s, 1);
o->newline() << "if (";
o->indent (1);
s->condition->visit (this);
@@ -1319,6 +1343,8 @@ c_unparser::visit_if_statement (if_statement *s)
void
c_unparser::visit_for_loop (for_loop *s)
{
+ visit_statement (s, 1);
+
s->init->visit (this);
string ctr = stringify (label_counter++);
string contlabel = "continue_" + ctr;
@@ -1326,9 +1352,6 @@ c_unparser::visit_for_loop (for_loop *s)
o->newline() << contlabel << ":";
- o->newline() << "c->actioncount ++;";
- o->newline() << "if (unlikely (c->actioncount > MAXACTION)) goto out;";
-
o->newline() << "if (! (";
if (s->cond->type != pe_long)
throw semantic_error ("expected numeric type", s->cond->tok);
@@ -1359,6 +1382,8 @@ c_tmpcounter::visit_foreach_loop (foreach_loop *s)
void
c_unparser::visit_foreach_loop (foreach_loop *s)
{
+ visit_statement (s, 1);
+
mapvar mv = getmap (s->base_referent, s->tok);
itervar iv = getiter (s);
vector<var> keys;
@@ -1378,7 +1403,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
var v = getvar (s->indexes[i]->referent);
c_assign (v, iv.get_key (v.type(), i), s->tok);
}
-
+
s->block->visit (this);
o->indent (-1);
@@ -1389,6 +1414,8 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
void
c_unparser::visit_return_statement (return_statement* s)
{
+ visit_statement (s, 1);
+
if (current_function == 0)
throw semantic_error ("cannot 'return' from probe", s->tok);
@@ -1404,6 +1431,8 @@ c_unparser::visit_return_statement (return_statement* s)
void
c_unparser::visit_next_statement (next_statement* s)
{
+ visit_statement (s, 1);
+
if (current_probe == 0)
throw semantic_error ("cannot 'next' from function", s->tok);
@@ -1437,7 +1466,7 @@ delete_statement_operand_visitor::visit_arrayindex (arrayindex* e)
{
vector<tmpvar> idx;
parent->load_map_indices (e, idx);
- parent->o->newline() << "if (unlikely (c->errorcount)) goto out;";
+ parent->o->newline() << "if (unlikely (c->last_error)) goto out;";
{
mapvar mvar = parent->getmap (e->referent, e->tok);
varlock guard (*parent, mvar);
@@ -1450,6 +1479,7 @@ delete_statement_operand_visitor::visit_arrayindex (arrayindex* e)
void
c_unparser::visit_delete_statement (delete_statement* s)
{
+ visit_statement (s, 1);
delete_statement_operand_visitor dv (this);
s->value->visit (&dv);
}
@@ -1458,6 +1488,7 @@ c_unparser::visit_delete_statement (delete_statement* s)
void
c_unparser::visit_break_statement (break_statement* s)
{
+ visit_statement (s, 1);
if (loop_break_labels.size() == 0)
throw semantic_error ("cannot 'break' outside loop", s->tok);
@@ -1469,6 +1500,7 @@ c_unparser::visit_break_statement (break_statement* s)
void
c_unparser::visit_continue_statement (continue_statement* s)
{
+ visit_statement (s, 1);
if (loop_continue_labels.size() == 0)
throw semantic_error ("cannot 'continue' outside loop", s->tok);
@@ -1552,7 +1584,7 @@ c_unparser::visit_binary_expression (binary_expression* e)
o->line() << ";";
o->newline() << ((e->op == "/") ? "_stp_div64" : "_stp_mod64")
- << " (&c->errorcount, " << left << ", " << right << ");";
+ << " (&c->last_error, " << left << ", " << right << ");";
o->newline(-1) << "})";
}
@@ -1634,7 +1666,7 @@ c_unparser::visit_array_in (array_in* e)
tmpvar res = gensym (pe_long);
- o->newline() << "if (unlikely (c->errorcount)) goto out;";
+ o->newline() << "if (unlikely (c->last_error)) goto out;";
{
mapvar mvar = getmap (e->operand->referent, e->tok);
@@ -1970,7 +2002,7 @@ c_unparser::visit_arrayindex (arrayindex* e)
// reentrancy issues that pop up with nested expressions:
// e.g. a[a[c]=5] could deadlock
- o->newline() << "if (unlikely (c->errorcount)) goto out;";
+ o->newline() << "if (unlikely (c->last_error)) goto out;";
{
mapvar mvar = getmap (e->referent, e->tok);
@@ -2046,7 +2078,7 @@ c_unparser_assignment::visit_arrayindex (arrayindex *e)
// reentrancy issues that pop up with nested expressions:
// e.g. ++a[a[c]=5] could deadlock
- o->newline() << "if (unlikely (c->errorcount)) goto out;";
+ o->newline() << "if (unlikely (c->last_error)) goto out;";
prepare_rvalue (op, rvar, e->tok);
@@ -2109,9 +2141,10 @@ c_unparser::visit_functioncall (functioncall* e)
}
o->newline();
- o->newline() << "if (unlikely (c->nesting+2 >= MAXNESTING)) goto out;";
- o->newline() << "c->actioncount ++;";
- o->newline() << "if (unlikely (c->actioncount > MAXACTION)) goto out;";
+ o->newline() << "if (unlikely (c->nesting+2 >= MAXNESTING)) {";
+ o->newline(1) << "c->last_error = \"MAXNESTING exceeded\";";
+ o->newline() << "goto out;";
+ o->newline(-1) << "}";
o->newline();
// copy in actual arguments