Add '__global_' prefix to global functions in the generated code.
Treat selected internal synthetic functions as private.
Fix using a private function in user script and test-cover it.
* elaborate.cxx: Correctly match global function names to respective
functiondecls. Match synthetic private functions coming from
tapset-procfs.cxx (*_procfs_value_*), and tapsets.cxx
(_sdt_arg_get_addr_) to respective functiondecls.
* main.cxx: Update the --dump-functions feature to correctly deal with
new internal function names.
* parse.cxx: Add the "__global_" prefix to global functions in the
generated code.
* staptree.cxx: Update functiondecl::printsig() so that it outputs
unmangled function name.
* tapset-procfs.cxx: Treat internal synthetic functions
'*_procfs_value_get*', '*_procfs_value_set*', '*_procfs_value_append*'
as private.
* tapsets.cxx: Treat internal synthetic functions '*_sdt_arg_get_addr_*'
as private.
* optim_arridx.exp: Adapt the testcase to new naming.
* private.exp: Add subtest examining use of a private function in
user script.
string pname = "__private_" + detox_path(tok->location.file->name) + string(name);
for (unsigned i=0; i<session.globals.size(); i++)
{
- if ((session.globals[i]->name == name && name.substr(0, 9) == "__global_") ||
+ if ((session.globals[i]->name == name && startswith(name, "__global_")) ||
(session.globals[i]->name == gname) ||
(session.globals[i]->name == pname))
{
functiondecl*
symresolution_info::find_function (const string& name, unsigned arity, const token *tok)
{
+ string gname = "__global_" + string(name);
+ string pname = "__private_" + detox_path(tok->location.file->name) + string(name);
+
// the common path
- if (session.functions.find(name) != session.functions.end())
+
+ // internal global functions bypassing the parser, such as __global_dwarf_tvar_[gs]et
+ if ((session.functions.find(name) != session.functions.end()) && startswith(name, "__private_"))
{
functiondecl* fd = session.functions[name];
assert (fd->name == name);
name.c_str(), fd->formal_args.size()), tok, fd->tok);
}
+ // tapset or user script global functions coming from the parser
+ if (session.functions.find(gname) != session.functions.end())
+ {
+ functiondecl* fd = session.functions[gname];
+ assert (fd->name == gname);
+ if (fd->formal_args.size() == arity)
+ return fd;
+
+ throw SEMANTIC_ERROR(_F("arity mismatch found (function '%s' takes %zu args)",
+ name.c_str(), fd->formal_args.size()), tok, fd->tok);
+ }
+
+ // tapset or user script private functions coming from the parser
+ if (session.functions.find(pname) != session.functions.end())
+ {
+ functiondecl* fd = session.functions[pname];
+ assert (fd->name == pname);
+ if (fd->formal_args.size() == arity)
+ return fd;
+
+ throw SEMANTIC_ERROR(_F("arity mismatch found (function '%s' takes %zu args)",
+ name.c_str(), fd->formal_args.size()), tok, fd->tok);
+ }
+
// search library functions
for (unsigned i=0; i<session.library_files.size(); i++)
{
stapfile* f = session.library_files[i];
for (unsigned j=0; j<f->functions.size(); j++)
{
- string pname = "__private_" + detox_path(tok->location.file->name) + string(name);
- if ((f->functions[j]->name == name) ||
+ if ((f->functions[j]->name == gname) ||
(f->functions[j]->name == pname))
{
if (f->functions[j]->formal_args.size() == arity)
functiondecl& curfunc = *func->second;
if (curfunc.synthetic)
continue;
- if (!s.verbose && startswith(curfunc.name, "_"))
+ if (!startswith(curfunc.name, "__global_"))
+ continue;
+ if (!s.verbose && startswith(curfunc.name, "__global__"))
continue;
curfunc.printsigtags(cout, s.verbose>0 /* all_tags */ );
cout << endl;
if (functions[i]->name == t->content)
throw PARSE_ERROR (_("duplicate function name"));
- string name = t->content;
+ string name = "__global_" + string(t->content);
if (priv)
name = "__private_" + detox_path(fname) + string(t->content);
void functiondecl::printsig (ostream& o) const
{
- o << name << ":" << type << " (";
+ o << tok->content << ":" << type << " (";
for (unsigned i=0; i<formal_args.size(); i++)
o << (i>0 ? ", " : "")
<< *formal_args[i]
embeddedcode *ec = new embeddedcode;
ec->tok = e->tok;
- string fname;
+ string fname = "__private_" + detox_path(string(e->tok->location.file->name));
string locvalue = "CONTEXT->ips.procfs_data";
if (! lvalue)
{
- fname = "_procfs_value_get";
+ fname += "_procfs_value_get";
ec->code = string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string("); /* pure */\n")
+ string(" if (!_stp_copy_from_user(STAP_RETVALUE, data->buffer, data->count))\n")
{
if (*op == "=")
{
- fname = "_procfs_value_set";
+ fname += "_procfs_value_set";
ec->code = string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
+ string(" strlcpy(data->buffer, STAP_ARG_value, data->bufsize);\n")
+ string(" if (strlen(STAP_ARG_value) > data->bufsize-1)\n")
}
else if (*op == ".=")
{
- fname = "_procfs_value_append";
+ fname += "_procfs_value_append";
ec->code = string("struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
+ string(" strlcat(data->buffer, STAP_ARG_value, data->bufsize);\n")
+ string(" if (data->count + strlen(STAP_ARG_value) > data->bufsize-1)\n")
expression* pointer=NULL)
{
// Synthesize a functiondecl for the given embedded code string.
+ string fhash = detox_path(string(e->tok->location.file->name));
functiondecl *fdecl = new functiondecl;
fdecl->synthetic = true;
fdecl->tok = e->tok;
- fdecl->name = function_name;
+ fdecl->name = "__private_" + fhash + function_name;
// The fdecl type is generic, but we'll be detailed on the fcall below.
fdecl->type = pe_long;
fdecl->type_details.reset(new exp_type_dwarf(&dw, function_type,
user_int_call->function = precision_to_function(precision);
user_int_call->tok = e->tok;
+ string fhash = detox_path(string(e->tok->location.file->name));
functiondecl *get_addr_decl = new functiondecl;
get_addr_decl->tok = e->tok;
get_addr_decl->synthetic = true;
- get_addr_decl->name = "_sdt_arg_get_addr_" + lex_cast(tick++);
+ get_addr_decl->name = "__private_" + fhash + "_sdt_arg_get_addr_" + lex_cast(tick++);
get_addr_decl->type = pe_long;
// build _stp_umodule_relocate(module, addr, current)
(__global_arr2[(idx2) = (2)]) = (20)
(__global_arr2[3]) = (30)
(__global_arr2[(j) = (4)]) = (40)
-(__global_arr1[fna((k) = (0)), k]) = (1)
+(__global_arr1[__global_fna((k) = (0)), k]) = (1)
(__global_arr1[(b) = (1), b]) = (2)
(__global_arr1[2, 2]) = (3)
(__global_arr3[0]) = (4)
(m) = (1)
for (2; (m) <= (10); (m)++) (__global_arr2[m]) = ((m) * (10))
printf("%d %d %d %d\\n", __global_arr1[0, 0], __global_arr2[0], idx2, j)
-(aa) = (fna(1))
-(bb) = (fnb((cc) = (1), (__global_elide_global_a) = (2)))
+(aa) = (__global_fna(1))
+(bb) = (__global_fnb((cc) = (1), (__global_elide_global_a) = (2)))
for (1; (bb) < (10); (bb)++) (cc) += (bb)
for ((dd) = (1); (dd) < (10); 1) (dd) += (1)
if ((__global_elide_global_b) = (1)) (ee) = (1)
(cc) = ((dd) = (5))
(cc) = ((4) + ((cc) = (1)))
printf("%d %d %d %d %d\\n", aa, bb, cc, dd, ee)
-exit()
+__global_exit()
}
end /* <- end */
# locals
}
catch {close}; catch {wait}
if {$__counter == 1} {pass $subtest} else {fail $subtest}
+
+ # Subtest
+ set subtest "$test private-function-in-user-script"
+ set __counter 0
+ eval spawn "stap --runtime=$runtime -e {private function foo() { println(42) } probe oneshot \{ foo() \}}"
+ expect {
+ -timeout 160
+ -re {^42\r\n} {
+ incr __counter
+ exp_continue
+ }
+ timeout {fail "$subtest (timeout)"}
+ }
+ catch {close}; catch {wait}
+ if {$__counter == 1} {pass $subtest} else {fail $subtest}
}
# Cleanup