diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2010-02-23 20:38:56 -0500 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2010-02-23 20:38:56 -0500 |
commit | c7005ee1ba902de01a8863661a2031bfd45d3d40 (patch) | |
tree | e8a7bfa55c9afcfac71b5aafa5b54256f356c81a | |
parent | 30263a7389d5c2712536b74656193708bbc64d49 (diff) | |
parent | 10328bcf86d49e5de83c5b22890204b5874740a9 (diff) | |
download | systemtap-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.cxx | 236 | ||||
-rw-r--r-- | parse.cxx | 6 | ||||
-rw-r--r-- | staptree.cxx | 12 | ||||
-rw-r--r-- | staptree.h | 2 | ||||
-rw-r--r-- | tapset-procfs.cxx | 57 | ||||
-rw-r--r-- | tapset/i386/nd_syscalls.stp | 8 | ||||
-rw-r--r-- | tapset/i386/syscalls.stp | 6 | ||||
-rw-r--r-- | tapset/ia64/syscalls.stp | 7 | ||||
-rw-r--r-- | tapset/powerpc/nd_syscalls.stp | 18 | ||||
-rw-r--r-- | tapset/powerpc/syscalls.stp | 13 | ||||
-rw-r--r-- | tapset/x86_64/nd_syscalls.stp | 14 | ||||
-rw-r--r-- | tapset/x86_64/syscalls.stp | 10 | ||||
-rw-r--r-- | tapsets.cxx | 36 | ||||
-rw-r--r-- | tapsets.h | 4 | ||||
-rw-r--r-- | testsuite/systemtap.syscall/mmap.c | 21 |
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 ++; } @@ -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 () { } @@ -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); @@ -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; } |