summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2010-02-23 20:38:56 -0500
committerFrank Ch. Eigler <fche@elastic.org>2010-02-23 20:38:56 -0500
commitc7005ee1ba902de01a8863661a2031bfd45d3d40 (patch)
treee8a7bfa55c9afcfac71b5aafa5b54256f356c81a
parent30263a7389d5c2712536b74656193708bbc64d49 (diff)
parent10328bcf86d49e5de83c5b22890204b5874740a9 (diff)
downloadsystemtap-steved-c7005ee1ba902de01a8863661a2031bfd45d3d40.tar.gz
systemtap-steved-c7005ee1ba902de01a8863661a2031bfd45d3d40.tar.xz
systemtap-steved-c7005ee1ba902de01a8863661a2031bfd45d3d40.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
* 'master' of ssh://sources.redhat.com/git/systemtap: PR10719 part 1: Partial constant folding Simplify null_statement construction Fixed PR 11269 by properly handling mmap syscall 'fd' argument. Removed rvalue operator check. PR 10690 (partial fix). Handle '.=' operator in procfs probes. Conflicts: tapsets.h
-rw-r--r--elaborate.cxx236
-rw-r--r--parse.cxx6
-rw-r--r--staptree.cxx12
-rw-r--r--staptree.h2
-rw-r--r--tapset-procfs.cxx57
-rw-r--r--tapset/i386/nd_syscalls.stp8
-rw-r--r--tapset/i386/syscalls.stp6
-rw-r--r--tapset/ia64/syscalls.stp7
-rw-r--r--tapset/powerpc/nd_syscalls.stp18
-rw-r--r--tapset/powerpc/syscalls.stp13
-rw-r--r--tapset/x86_64/nd_syscalls.stp14
-rw-r--r--tapset/x86_64/syscalls.stp10
-rw-r--r--tapsets.cxx36
-rw-r--r--tapsets.h4
-rw-r--r--testsuite/systemtap.syscall/mmap.c21
15 files changed, 392 insertions, 58 deletions
diff --git a/elaborate.cxx b/elaborate.cxx
index 127e0bda..4e5c63c8 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -2421,6 +2421,7 @@ dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
if (s->block == 0)
{
+ // XXX what if s->limit has side effects?
if (session.verbose>2)
clog << "Eliding side-effect-free foreach statement " << *s->tok << endl;
s = 0; // yeah, baby
@@ -2450,8 +2451,7 @@ dead_stmtexpr_remover::visit_for_loop (for_loop *s)
else
{
// Can't elide this whole statement; put a null in there.
- s->block = new null_statement();
- s->block->tok = s->tok;
+ s->block = new null_statement(s->tok);
}
}
provide (s);
@@ -2527,8 +2527,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
&& ! s.timing) // PR10070
s.print_warning ("side-effect-free probe '" + p->name + "'", p->tok);
- p->body = new null_statement();
- p->body->tok = p->tok;
+ p->body = new null_statement(p->tok);
// XXX: possible duplicate warnings; see below
}
@@ -2552,8 +2551,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
if (! s.suppress_warnings)
s.print_warning ("side-effect-free function '" + fn->name + "'", fn->tok);
- fn->body = new null_statement();
- fn->body->tok = fn->tok;
+ fn->body = new null_statement(fn->tok);
// XXX: the next iteration of the outer optimization loop may
// take this new null_statement away again, and thus give us a
@@ -2983,6 +2981,231 @@ void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
}
+struct const_folder: public update_visitor
+{
+ systemtap_session& session;
+ bool& relaxed_p;
+
+ const_folder(systemtap_session& s, bool& r):
+ session(s), relaxed_p(r), last_number(0), last_string(0) {}
+
+ literal_number* last_number;
+ literal_number* get_number(expression*& e);
+ void visit_literal_number (literal_number* e);
+
+ literal_string* last_string;
+ literal_string* get_string(expression*& e);
+ void visit_literal_string (literal_string* e);
+
+ void visit_if_statement (if_statement* s);
+ void visit_for_loop (for_loop* s);
+ void visit_foreach_loop (foreach_loop* s);
+ void visit_binary_expression (binary_expression* e);
+ void visit_unary_expression (unary_expression* e);
+ void visit_logical_or_expr (logical_or_expr* e);
+ void visit_logical_and_expr (logical_and_expr* e);
+ void visit_comparison (comparison* e);
+ void visit_concatenation (concatenation* e);
+ void visit_ternary_expression (ternary_expression* e);
+};
+
+literal_number*
+const_folder::get_number(expression*& e)
+{
+ replace (e);
+ return (e == last_number) ? last_number : NULL;
+}
+
+void
+const_folder::visit_literal_number (literal_number* e)
+{
+ last_number = e;
+ provide (e);
+}
+
+literal_string*
+const_folder::get_string(expression*& e)
+{
+ replace (e);
+ return (e == last_string) ? last_string : NULL;
+}
+
+void
+const_folder::visit_literal_string (literal_string* e)
+{
+ last_string = e;
+ provide (e);
+}
+
+void
+const_folder::visit_if_statement (if_statement* s)
+{
+ literal_number* cond = get_number (s->condition);
+ if (!cond)
+ {
+ replace (s->thenblock);
+ replace (s->elseblock);
+ provide (s);
+ }
+ else
+ {
+ if (session.verbose>2)
+ clog << "Collapsing constant if-statement " << *s->tok << endl;
+ relaxed_p = false;
+
+ statement* n = cond->value ? s->thenblock : s->elseblock;
+ if (n)
+ n->visit (this);
+ else
+ provide (new null_statement (s->tok));
+ }
+}
+
+void
+const_folder::visit_for_loop (for_loop* s)
+{
+ literal_number* cond = get_number (s->cond);
+ if (!cond || cond->value)
+ {
+ replace (s->init);
+ replace (s->incr);
+ replace (s->block);
+ provide (s);
+ }
+ else
+ {
+ if (session.verbose>2)
+ clog << "Collapsing constantly-false for-loop " << *s->tok << endl;
+ relaxed_p = false;
+
+ if (s->init)
+ s->init->visit (this);
+ else
+ provide (new null_statement (s->tok));
+ }
+}
+
+void
+const_folder::visit_foreach_loop (foreach_loop* s)
+{
+ literal_number* limit = get_number (s->limit);
+ if (!limit || limit->value > 0)
+ {
+ for (unsigned i = 0; i < s->indexes.size(); ++i)
+ replace (s->indexes[i]);
+ replace (s->base);
+ replace (s->block);
+ provide (s);
+ }
+ else
+ {
+ if (session.verbose>2)
+ clog << "Collapsing constantly-limited foreach-loop " << *s->tok << endl;
+ relaxed_p = false;
+
+ provide (new null_statement (s->tok));
+ }
+}
+
+void
+const_folder::visit_binary_expression (binary_expression* e)
+{
+ // TODO
+ update_visitor::visit_binary_expression (e);
+}
+
+void
+const_folder::visit_unary_expression (unary_expression* e)
+{
+ literal_number* operand = get_number (e->operand);
+ if (!operand)
+ provide (e);
+ else
+ {
+ if (session.verbose>2)
+ clog << "Collapsing constant unary " << *e->tok << endl;
+ relaxed_p = false;
+
+ literal_number* n = new literal_number (*operand);
+ n->tok = e->tok;
+ if (e->op == "+")
+ ; // nothing to do
+ else if (e->op == "-")
+ n->value = -n->value;
+ else if (e->op == "!")
+ n->value = !n->value;
+ else if (e->op == "~")
+ n->value = ~n->value;
+ else
+ throw semantic_error ("unsupported unary operator " + e->op);
+ n->visit (this);
+ }
+}
+
+void
+const_folder::visit_logical_or_expr (logical_or_expr* e)
+{
+ // TODO
+ update_visitor::visit_logical_or_expr (e);
+}
+
+void
+const_folder::visit_logical_and_expr (logical_and_expr* e)
+{
+ // TODO
+ update_visitor::visit_logical_and_expr (e);
+}
+
+void
+const_folder::visit_comparison (comparison* e)
+{
+ // TODO
+ update_visitor::visit_comparison (e);
+}
+
+void
+const_folder::visit_concatenation (concatenation* e)
+{
+ // TODO
+ update_visitor::visit_concatenation (e);
+}
+
+void
+const_folder::visit_ternary_expression (ternary_expression* e)
+{
+ literal_number* cond = get_number (e->cond);
+ if (!cond)
+ {
+ replace (e->truevalue);
+ replace (e->falsevalue);
+ provide (e);
+ }
+ else
+ {
+ if (session.verbose>2)
+ clog << "Collapsing constant ternary " << *e->tok << endl;
+ relaxed_p = false;
+
+ expression* n = cond->value ? e->truevalue : e->falsevalue;
+ n->visit (this);
+ }
+}
+
+static void semantic_pass_const_fold (systemtap_session& s, bool& relaxed_p)
+{
+ // Let's simplify statements with constant values.
+
+ const_folder cf (s, relaxed_p);
+ // This instance may be reused for multiple probe/function body trims.
+
+ for (unsigned i=0; i<s.probes.size(); i++)
+ cf.replace (s.probes[i]->body);
+ for (map<string,functiondecl*>::iterator it = s.functions.begin();
+ it != s.functions.end(); it++)
+ cf.replace (it->second->body);
+}
+
+
struct duplicate_function_remover: public functioncall_traversing_visitor
{
systemtap_session& s;
@@ -3107,6 +3330,7 @@ semantic_pass_optimize1 (systemtap_session& s)
semantic_pass_opt3 (s, relaxed_p);
semantic_pass_opt4 (s, relaxed_p);
semantic_pass_opt5 (s, relaxed_p);
+ semantic_pass_const_fold (s, relaxed_p);
iterations ++;
}
diff --git a/parse.cxx b/parse.cxx
index b867f98d..b2daa178 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -1289,11 +1289,7 @@ parser::parse_statement ()
statement *ret;
const token* t = peek ();
if (t && t->type == tok_operator && t->content == ";")
- {
- null_statement* n = new null_statement ();
- n->tok = next ();
- return n;
- }
+ return new null_statement (next ());
else if (t && t->type == tok_operator && t->content == "{")
return parse_stmt_block (); // Don't squash semicolons.
else if (t && t->type == tok_keyword && t->content == "if")
diff --git a/staptree.cxx b/staptree.cxx
index 9a69d11b..b6ee3fdf 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -42,6 +42,18 @@ statement::statement ():
}
+statement::statement (const token* tok):
+ tok (tok)
+{
+}
+
+
+null_statement::null_statement (const token* tok):
+ statement(tok)
+{
+}
+
+
statement::~statement ()
{
}
diff --git a/staptree.h b/staptree.h
index 5bd69124..62ce37fe 100644
--- a/staptree.h
+++ b/staptree.h
@@ -500,6 +500,7 @@ struct statement
virtual void visit (visitor* u) = 0;
const token* tok;
statement ();
+ statement (const token* tok);
virtual ~statement ();
};
@@ -555,6 +556,7 @@ struct null_statement: public statement
{
void print (std::ostream& o) const;
void visit (visitor* u);
+ null_statement (const token* tok);
};
diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx
index c4eb54f3..1926582b 100644
--- a/tapset-procfs.cxx
+++ b/tapset-procfs.cxx
@@ -74,9 +74,7 @@ public:
struct procfs_var_expanding_visitor: public var_expanding_visitor
{
procfs_var_expanding_visitor(systemtap_session& s, const string& pn,
- string path, bool write_probe):
- sess (s), probe_name (pn), path (path), write_probe (write_probe),
- target_symbol_seen (false) {}
+ string path, bool write_probe);
systemtap_session& sess;
string probe_name;
@@ -342,6 +340,18 @@ procfs_derived_probe_group::emit_module_exit (systemtap_session& s)
}
+procfs_var_expanding_visitor::procfs_var_expanding_visitor (systemtap_session& s,
+ const string& pn,
+ string path,
+ bool write_probe):
+ sess (s), probe_name (pn), path (path), write_probe (write_probe),
+ target_symbol_seen (false)
+{
+ // procfs probes can also handle '.='.
+ valid_ops.insert (".=");
+}
+
+
void
procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e)
{
@@ -371,21 +381,40 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e)
embeddedcode *ec = new embeddedcode;
ec->tok = e->tok;
- string fname = (string(lvalue ? "_procfs_value_set" : "_procfs_value_get"));
+ string fname;
string locvalue = "CONTEXT->data";
if (! lvalue)
- ec->code = string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string("); /* pure */\n")
+ {
+ fname = "_procfs_value_get";
+ ec->code = string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string("); /* pure */\n")
- + string(" _stp_copy_from_user(THIS->__retvalue, data->buffer, data->count);\n")
- + string(" THIS->__retvalue[data->count] = '\\0';\n");
- else
- ec->code = string("int bytes = 0;\n")
- + string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
- + string(" bytes = strnlen(THIS->value, MAXSTRINGLEN - 1);\n")
- + string(" memcpy((void *)data->buffer, THIS->value, bytes);\n")
- + string(" data->buffer[bytes] = '\\0';\n")
- + string(" data->count = bytes;\n");
+ + string(" _stp_copy_from_user(THIS->__retvalue, data->buffer, data->count);\n")
+ + string(" THIS->__retvalue[data->count] = '\\0';\n");
+ }
+ else // lvalue
+ {
+ if (*op == "=")
+ {
+ fname = "_procfs_value_set";
+ ec->code = string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
+ + string(" strlcpy(data->buffer, THIS->value, MAXSTRINGLEN);\n")
+ + string(" data->count = strlen(data->buffer);\n");
+ }
+ else if (*op == ".=")
+ {
+ fname = "_procfs_value_append";
+ ec->code = string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
+ + string(" strlcat(data->buffer, THIS->value, MAXSTRINGLEN);\n")
+ + string(" data->count = strlen(data->buffer);\n");
+ }
+ else
+ {
+ throw semantic_error ("Only the following assign operators are"
+ " implemented on procfs read target variables:"
+ " '=', '.='", e->tok);
+ }
+ }
fdecl->name = fname;
fdecl->body = ec;
diff --git a/tapset/i386/nd_syscalls.stp b/tapset/i386/nd_syscalls.stp
index 92befeb5..2b13cbd7 100644
--- a/tapset/i386/nd_syscalls.stp
+++ b/tapset/i386/nd_syscalls.stp
@@ -79,17 +79,19 @@ probe nd_syscall.mmap2 = kprobe.function("sys_mmap2") ?
// length = $len
// prot = $prot
// flags = $flags
- // fd = $fd
+ // fd = __int32($fd)
// pgoffset = $pgoff
// argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr,
// $len, _mprotect_prot_str($prot), _mmap_flags($flags),
- // $fd, $pgoff)
+ // __int32($fd), $pgoff)
asmlinkage()
start = ulong_arg(1)
length = ulong_arg(2)
prot = ulong_arg(3)
flags = ulong_arg(4)
- fd = ulong_arg(5)
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = int_arg(5)
pgoffset = ulong_arg(6)
argstr = sprintf("%p, %d, %s, %s, %d, %d", start,
length, _mprotect_prot_str(prot), _mmap_flags(flags),
diff --git a/tapset/i386/syscalls.stp b/tapset/i386/syscalls.stp
index 821d77d4..2d1a282b 100644
--- a/tapset/i386/syscalls.stp
+++ b/tapset/i386/syscalls.stp
@@ -68,11 +68,13 @@ probe syscall.mmap2 = kernel.function("sys_mmap2") ?
length = $len
prot = $prot
flags = $flags
- fd = $fd
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = __int32($fd)
pgoffset = $pgoff
argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr,
$len, _mprotect_prot_str($prot), _mmap_flags($flags),
- $fd, $pgoff)
+ __int32($fd), $pgoff)
}
probe syscall.mmap2.return = kernel.function("sys_mmap2").return ?
{
diff --git a/tapset/ia64/syscalls.stp b/tapset/ia64/syscalls.stp
index c57ab7e6..9601ac08 100644
--- a/tapset/ia64/syscalls.stp
+++ b/tapset/ia64/syscalls.stp
@@ -10,10 +10,13 @@ probe syscall.mmap = kernel.function("sys_mmap") ?
len = $len
prot = $prot
flags = $flags
- fd = $fd
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = __int32($fd)
offset = $off
argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len,
- _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $off)
+ _mprotect_prot_str($prot), _mmap_flags($flags),
+ __int32($fd), $off)
}
probe syscall.mmap.return = kernel.function("sys_mmap").return ?
diff --git a/tapset/powerpc/nd_syscalls.stp b/tapset/powerpc/nd_syscalls.stp
index 46267507..0723c393 100644
--- a/tapset/powerpc/nd_syscalls.stp
+++ b/tapset/powerpc/nd_syscalls.stp
@@ -637,19 +637,23 @@ probe nd_syscall.mmap = kprobe.function("sys_mmap") ?
// len = $len
// prot = $prot
// flags = $flags
- // fd = $fd
+ // fd = __int32($fd)
// offset = $offset
// argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len,
- // _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $offset)
+ // _mprotect_prot_str($prot), _mmap_flags($flags),
+ // __int32($fd), $offset)
asmlinkage()
start = ulong_arg(1)
len = ulong_arg(2)
prot = ulong_arg(3)
flags = ulong_arg(4)
- fd = ulong_arg(5)
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = int_arg(5)
offset = ulong_arg(6)
argstr = sprintf("%p, %d, %s, %s, %d, %d", start, len,
- _mprotect_prot_str(prot), _mmap_flags(flags), fd, offset)
+ _mprotect_prot_str(prot), _mmap_flags(flags),
+ fd, offset)
}
probe nd_syscall.mmap.return = kprobe.function("sys_mmap").return ?
{
@@ -673,7 +677,7 @@ probe nd_syscall.mmap2 = kprobe.function("sys_mmap2") ?,
// length = $len
// prot = $prot
// flags = $flags
- // fd = $fd
+ // fd = __int32($fd)
// pgoffset = $pgoff
// argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr,
// $len, _mprotect_prot_str($prot), _mmap_flags($flags),
@@ -683,7 +687,9 @@ probe nd_syscall.mmap2 = kprobe.function("sys_mmap2") ?,
length = ulong_arg(2)
prot = ulong_arg(3)
flags = ulong_arg(4)
- fd = ulong_arg(5)
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = int_arg(5)
pgoffset = ulong_arg(6)
argstr = sprintf("%p, %d, %s, %s, %d, %d", start,
length, _mprotect_prot_str(prot), _mmap_flags(flags),
diff --git a/tapset/powerpc/syscalls.stp b/tapset/powerpc/syscalls.stp
index 0518d486..aa90eb92 100644
--- a/tapset/powerpc/syscalls.stp
+++ b/tapset/powerpc/syscalls.stp
@@ -511,10 +511,13 @@ probe syscall.mmap = kernel.function("sys_mmap") ?
len = $len
prot = $prot
flags = $flags
- fd = $fd
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = __int32($fd)
offset = $offset
argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len,
- _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $offset)
+ _mprotect_prot_str($prot), _mmap_flags($flags),
+ __int32($fd), $offset)
}
probe syscall.mmap.return = kernel.function("sys_mmap").return ?
@@ -539,11 +542,13 @@ probe syscall.mmap2 = kernel.function("sys_mmap2") ?,
length = $len
prot = $prot
flags = $flags
- fd = $fd
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = __int32($fd)
pgoffset = $pgoff
argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr,
$len, _mprotect_prot_str($prot), _mmap_flags($flags),
- $fd, $pgoff)
+ __int32($fd), $pgoff)
}
probe syscall.mmap2.return = kernel.function("sys_mmap2").return ?,
kernel.function("compat_sys_mmap2").return ?
diff --git a/tapset/x86_64/nd_syscalls.stp b/tapset/x86_64/nd_syscalls.stp
index a8157160..80c092a8 100644
--- a/tapset/x86_64/nd_syscalls.stp
+++ b/tapset/x86_64/nd_syscalls.stp
@@ -98,16 +98,19 @@ probe nd_syscall.mmap = kprobe.function("sys_mmap") ?
// len = $len
// prot = $prot
// flags = $flags
- // fd = $fd
+ // fd = __int32($fd)
// offset = $off
// argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len,
- // _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $off)
+ // _mprotect_prot_str($prot), _mmap_flags($flags),
+ // __int32($fd), $off)
asmlinkage()
start = ulong_arg(1)
len = ulong_arg(2)
prot = ulong_arg(3)
flags = ulong_arg(4)
- fd = ulong_arg(5)
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = int_arg(5)
offset = ulong_arg(6)
argstr = sprintf("%p, %d, %s, %s, %d, %d", start, len,
_mprotect_prot_str(prot), _mmap_flags(flags), fd, offset)
@@ -142,11 +145,12 @@ probe nd_syscall.mmap2 = kprobe.function("sys32_mmap2")
{
name = "mmap2"
// argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len,
- // _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $pgoff)
+ // _mprotect_prot_str($prot), _mmap_flags($flags),
+ // __int32($fd), $pgoff)
asmlinkage()
argstr = sprintf("%p, %d, %s, %s, %d, %d", ulong_arg(1), ulong_arg(2),
_mprotect_prot_str(ulong_arg(3)), _mmap_flags(ulong_arg(4)),
- ulong_arg(5), ulong_arg(6))
+ int_arg(5), ulong_arg(6))
}
probe nd_syscall.mmap2.return = kprobe.function("sys32_mmap2").return
{
diff --git a/tapset/x86_64/syscalls.stp b/tapset/x86_64/syscalls.stp
index 5ad064a2..28fa2969 100644
--- a/tapset/x86_64/syscalls.stp
+++ b/tapset/x86_64/syscalls.stp
@@ -85,10 +85,13 @@ probe syscall.mmap = kernel.function("sys_mmap") ?
len = $len
prot = $prot
flags = $flags
- fd = $fd
+ # Although the kernel gets an unsigned long fd, on the
+ # user-side it is a signed int. Fix this.
+ fd = __int32($fd)
offset = $off
argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len,
- _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $off)
+ _mprotect_prot_str($prot), _mmap_flags($flags),
+ __int32($fd), $off)
}
probe syscall.mmap.return = kernel.function("sys_mmap").return ?
@@ -119,7 +122,8 @@ probe syscall.mmap2 = kernel.function("sys32_mmap2") ?
{
name = "mmap2"
argstr = sprintf("%p, %d, %s, %s, %d, %d", $addr, $len,
- _mprotect_prot_str($prot), _mmap_flags($flags), $fd, $pgoff)
+ _mprotect_prot_str($prot), _mmap_flags($flags),
+ __int32($fd), $pgoff)
}
probe syscall.mmap2.return = kernel.function("sys32_mmap2").return ?
diff --git a/tapsets.cxx b/tapsets.cxx
index 097cddc8..fcb22e03 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1859,6 +1859,19 @@ private:
unsigned var_expanding_visitor::tick = 0;
+
+var_expanding_visitor::var_expanding_visitor ()
+{
+ // FIXME: for the time being, by default we only support plain '$foo
+ // = bar', not '+=' or any other op= variant. This is fixable, but a
+ // bit ugly.
+ //
+ // If derived classes desire to add additional operator support, add
+ // new operators to this list in the derived class constructor.
+ valid_ops.insert ("=");
+}
+
+
void
var_expanding_visitor::visit_assignment (assignment* e)
{
@@ -1877,6 +1890,9 @@ var_expanding_visitor::visit_assignment (assignment* e)
functioncall *fcall = NULL;
expression *new_left, *new_right;
+ // Let visit_target_symbol know what operator it should handle.
+ op = &e->op;
+
target_symbol_setter_functioncalls.push (&fcall);
new_left = require (e->left);
target_symbol_setter_functioncalls.pop ();
@@ -1890,12 +1906,20 @@ var_expanding_visitor::visit_assignment (assignment* e)
// right child spliced in as sole argument -- in place of
// ourselves, in the var expansion we're in the middle of making.
- // FIXME: for the time being, we only support plan $foo = bar,
- // not += or any other op= variant. This is fixable, but a bit
- // ugly.
- if (e->op != "=")
- throw semantic_error ("Operator-assign expressions on target "
- "variables not implemented", e->tok);
+ if (valid_ops.find (e->op) == valid_ops.end ())
+ {
+ // Build up a list of supported operators.
+ string ops;
+ std::set<string>::iterator i;
+ for (i = valid_ops.begin(); i != valid_ops.end(); i++)
+ ops += " " + *i + ",";
+ ops.resize(ops.size() - 1); // chop off the last ','
+
+ // Throw the error.
+ throw semantic_error ("Only the following assign operators are"
+ " implemented on target variables:" + ops,
+ e->tok);
+ }
assert (new_left == fcall);
fcall->args.push_back (new_right);
diff --git a/tapsets.h b/tapsets.h
index bdaf3201..1d5ba942 100644
--- a/tapsets.h
+++ b/tapsets.h
@@ -50,8 +50,10 @@ struct var_expanding_visitor: public update_visitor
static unsigned tick;
std::stack<functioncall**> target_symbol_setter_functioncalls;
std::stack<defined_op*> defined_ops;
+ std::set<std::string> valid_ops;
+ std::string *op;
- var_expanding_visitor() {}
+ var_expanding_visitor ();
void visit_assignment (assignment* e);
void visit_defined_op (defined_op* e);
};
diff --git a/testsuite/systemtap.syscall/mmap.c b/testsuite/systemtap.syscall/mmap.c
index a09888b4..bc788227 100644
--- a/testsuite/systemtap.syscall/mmap.c
+++ b/testsuite/systemtap.syscall/mmap.c
@@ -1,6 +1,7 @@
-/* COVERAGE: mmap2 munmap msync mlock mlockall munlock munlockall fstat open close */
+/* COVERAGE: mmap2 munmap msync mlock mlockall munlock munlockall mprotect mremap fstat open close */
#include <sys/types.h>
#include <sys/stat.h>
+#define __USE_GNU
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
@@ -49,5 +50,23 @@ int main()
munmap(r, fs.st_size);
//staptest// munmap (XXXX, 1030) = 0
+ r = mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ //staptest// mmap[2]* (XXXX, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = XXXX
+
+ mprotect(r, 4096, PROT_READ);
+ //staptest// mprotect (XXXX, 4096, PROT_READ) = 0
+
+ munmap(r, 12288);
+ //staptest// munmap (XXXX, 12288) = 0
+
+ r = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ //staptest// mmap[2]* (XXXX, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = XXXX
+
+ r = mremap(r, 8192, 4096, 0);
+ //// mremap (XXXX, 8192, 4096, 0) = XXXX
+
+ munmap(r, 4096);
+ //// munmap (XXXX, 4096) = 0
+
return 0;
}