diff options
author | dsmith <dsmith> | 2006-06-05 21:49:14 +0000 |
---|---|---|
committer | dsmith <dsmith> | 2006-06-05 21:49:14 +0000 |
commit | e19fda4e952815ed64646a8183c479824bf58444 (patch) | |
tree | cc106c4c6a5a8bf11a133b62533ff7aad9044be0 /tapsets.cxx | |
parent | c641b2813f6fd069dc10cdc66736f09e4531c551 (diff) | |
download | systemtap-steved-e19fda4e952815ed64646a8183c479824bf58444.tar.gz systemtap-steved-e19fda4e952815ed64646a8183c479824bf58444.tar.xz systemtap-steved-e19fda4e952815ed64646a8183c479824bf58444.zip |
2006-06-05 David Smith <dsmith@redhat.com>
* tapsets.cxx (dwflpp::express_as_string): New function.
Extracted from dwflpp::literal_stmt_for_local() so that
dwflpp::literal_stmt_for_return() could also call it.
(dwflpp::literal_stmt_for_local): Portion extracted to create
dwflpp::express_as_string().
(dwflpp::literal_stmt_for_return): New function. Adds support for
new symbolic access ("$return") to return value in .return
probes. Fixes PR 1132.
(target_variable_flavour_calculating_visitor::visit_target_symbol):
Calls dwflpp::literal_stmt_for_return() when in a return probe and
the variable name is "$return".
(dwarf_var_expanding_copy_visitor::visit_target_symbol): Ditto.
* stapfuncs.5.in: Noted that the retval() function is deprecated.
* stapprobes.5.in: Corrected the name of the return value
variable.
* tapset/return.stp: Marked the retval() function as deprecated.
* testsuite/semko/return01.stp: Added new test.
* testsuite/semko/return02.stp: Ditto.
Diffstat (limited to 'tapsets.cxx')
-rw-r--r-- | tapsets.cxx | 169 |
1 files changed, 130 insertions, 39 deletions
diff --git a/tapsets.cxx b/tapsets.cxx index 866c6757..92655070 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1479,6 +1479,42 @@ dwflpp } } + string + express_as_string (string prelude, + string postlude, + struct location *head) + { + size_t bufsz = 1024; + char *buf = static_cast<char*>(malloc(bufsz)); + assert(buf); + + FILE *memstream = open_memstream (&buf, &bufsz); + assert(memstream); + + fprintf(memstream, "{\n"); + fprintf(memstream, prelude.c_str()); + bool deref = c_emit_location (memstream, head, 1); + fprintf(memstream, postlude.c_str()); + fprintf(memstream, " goto out;\n"); + + // dummy use of deref_fault label, to disable warning if deref() not used + fprintf(memstream, "if (0) goto deref_fault;\n"); + + // XXX: deref flag not reliable; emit fault label unconditionally + // XXX: print the faulting address, like the user_string/kernel_string + // tapset functions do + if (deref) ; + fprintf(memstream, + "deref_fault:\n" + " c->last_error = \"pointer dereference fault\";\n" + " goto out;\n"); + fprintf(memstream, "}\n"); + + fclose (memstream); + string result(buf); + free (buf); + return result; + } string literal_stmt_for_local (Dwarf_Die *scope_die, @@ -1546,39 +1582,75 @@ dwflpp prelude, postlude, ty); /* Write the translation to a string. */ + return express_as_string(prelude, postlude, head); + } - size_t bufsz = 1024; - char *buf = static_cast<char*>(malloc(bufsz)); - assert(buf); - FILE *memstream = open_memstream (&buf, &bufsz); - assert(memstream); + string + literal_stmt_for_return (Dwarf_Die *scope_die, + Dwarf_Addr pc, + vector<pair<target_symbol::component_type, + std::string> > const & components, + bool lvalue, + exp_type & ty) + { + if (sess.verbose>2) + clog << "literal_stmt_for_return: finding return value for " + << dwarf_diename (scope_die) + << "(" + << dwarf_diename (cu) + << ")\n"; - fprintf(memstream, "{\n"); - fprintf(memstream, prelude.c_str()); - bool deref = c_emit_location (memstream, head, 1); - fprintf(memstream, postlude.c_str()); - fprintf(memstream, " goto out;\n"); + struct obstack pool; + obstack_init (&pool); + struct location *tail = NULL; - // dummy use of deref_fault label, to disable warning if deref() not used - fprintf(memstream, "if (0) goto deref_fault;\n"); + /* Given $return->bar->baz[NN], translate the location of return. */ + const Dwarf_Op *locops; + int nlocops = dwfl_module_return_value_location (module, scope_die, + &locops); + if (nlocops < 0) + { + throw semantic_error("failed to retrieve return value location"); + } + // the function has no return value (e.g. "void" in C) + else if (nlocops == 0) + { + throw semantic_error("function has no return value"); + } - // XXX: deref flag not reliable; emit fault label unconditionally - // XXX: print the faulting address, like the user_string/kernel_string - // tapset functions do - if (deref) ; - fprintf(memstream, - "deref_fault:\n" - " c->last_error = \"pointer dereference fault\";\n" - " goto out;\n"); - fprintf(memstream, "}\n"); + struct location *head = c_translate_location (&pool, &loc2c_error, this, + &loc2c_emit_address, + 1, module_bias, + pc, locops, nlocops, + &tail, NULL); - fclose (memstream); - string result(buf); - free (buf); - return result; - } + /* Translate the ->bar->baz[NN] parts. */ + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = dwarf_attr (scope_die, DW_AT_type, &attr_mem); + + Dwarf_Die vardie_mem; + Dwarf_Die *vardie = dwarf_formref_die (attr, &vardie_mem); + + Dwarf_Die die_mem, *die = NULL; + die = translate_components (&pool, &tail, pc, components, + vardie, &die_mem, &attr_mem); + + /* Translate the assignment part, either + x = $return->bar->baz[NN] + or + $return->bar->baz[NN] = x + */ + + string prelude, postlude; + translate_final_fetch_or_store (&pool, &tail, module_bias, + die, &attr_mem, lvalue, + prelude, postlude, ty); + + /* Write the translation to a string. */ + return express_as_string(prelude, postlude, head); + } ~dwflpp() @@ -1996,12 +2068,19 @@ target_variable_flavour_calculating_visitor::visit_target_symbol (target_symbol string expr; try { - expr = q.dw.literal_stmt_for_local(scope_die, - addr, - e->base_name.substr(1), - e->components, - lvalue, - ty); + if (q.has_return && e->base_name == "$return") + expr = q.dw.literal_stmt_for_return (scope_die, + addr, + e->components, + lvalue, + ty); + else + expr = q.dw.literal_stmt_for_local(scope_die, + addr, + e->base_name.substr(1), + e->components, + lvalue, + ty); } catch (const semantic_error& e) { @@ -2747,17 +2826,29 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) + "_" + e->base_name.substr(1) + "_" + lex_cast<string>(tick++)); - if (q.has_return) + if (q.has_return && e->base_name != "$return") throw semantic_error ("target variables not available to .return probes"); try { - ec->code = q.dw.literal_stmt_for_local (scope_die, - addr, - e->base_name.substr(1), - e->components, - lvalue, - fdecl->type); + if (q.has_return && e->base_name == "$return") + { + ec->code = q.dw.literal_stmt_for_return (scope_die, + addr, + e->components, + lvalue, + fdecl->type); + } + else + { + ec->code = q.dw.literal_stmt_for_local (scope_die, + addr, + e->base_name.substr(1), + e->components, + lvalue, + fdecl->type); + } + if (! lvalue) ec->code += "/* pure */"; } |