From 7957875f4439adecdca9d80294f421f785f66f25 Mon Sep 17 00:00:00 2001 From: Lukas Berk Date: Wed, 3 Apr 2013 17:26:40 -0400 Subject: [PATCH] Allow more than one java probe point per script *tapset-method.cxx: add filter to match probe against the class and method, if it doesn't match, then skip the probe point *session.cxx: change how rules are uninstalled --- session.cxx | 28 +++---- session.h | 7 +- tapset-method.cxx | 184 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 170 insertions(+), 49 deletions(-) diff --git a/session.cxx b/session.cxx index 5be5f4188..05c167fdc 100644 --- a/session.cxx +++ b/session.cxx @@ -161,12 +161,10 @@ systemtap_session::systemtap_session (): sysroot = ""; update_release_sysroot = false; suppress_time_limits = false; - java_pid = 0; - java_proc_class = ""; #ifdef HAVE_HELPER bminstall_path = ""; bmsubmit_path = ""; - byteman_script_path = ""; + run_once = false; byteman_log = ""; #endif //HAVE_HELPER @@ -345,6 +343,7 @@ systemtap_session::systemtap_session (const systemtap_session& other, #ifdef HAVE_HELPER + run_once = other.run_once; java_pid = other.java_pid; java_proc_class = other.java_proc_class; bminstall_path = other.bminstall_path; @@ -389,7 +388,7 @@ systemtap_session::~systemtap_session () { #ifdef HAVE_HELPER - if(java_pid != 0 || !java_proc_class.empty()) + // if(!java_pid.empty() || !java_proc_class.empty()) java_detach(); #endif //HAVE_HELPER remove_tmp_dir(); @@ -2015,16 +2014,19 @@ translator_output* systemtap_session::op_create_auxiliary() void systemtap_session::java_detach() { - vector bmcommand; - bmcommand.push_back(bmsubmit_path); - bmcommand.push_back(" -o"); - bmcommand.push_back(byteman_log); - bmcommand.push_back(" -u"); - bmcommand.push_back(byteman_script_path); - (void) stap_system(verbose, bmcommand); - if (verbose>1) - clog << _F("Removed byteman rule: \"%s\"", byteman_script_path.c_str()) << endl; + for(vector::const_iterator it = byteman_script_path.begin(); it != byteman_script_path.end(); ++it) + { + vector bmcommand; + bmcommand.push_back(bmsubmit_path); + bmcommand.push_back(" -o"); + bmcommand.push_back(byteman_log); + bmcommand.push_back(" -u"); + bmcommand.push_back(*it); + (void) stap_system(verbose, bmcommand); + if (verbose>1) + clog << _F("Removed byteman rule: \"%s\"", (*it).c_str()) << endl; + } } #endif diff --git a/session.h b/session.h index a7b8494e3..5a836adac 100644 --- a/session.h +++ b/session.h @@ -202,11 +202,12 @@ public: bool suppress_time_limits; void java_detach(); - int java_pid; - std::string java_proc_class; + bool run_once; + std::vector java_pid; + std::vector java_proc_class; + std::vector byteman_script_path; std::string bminstall_path; std::string bmsubmit_path; - std::string byteman_script_path; std::string byteman_log; enum { kernel_runtime, dyninst_runtime } runtime_mode; diff --git a/tapset-method.cxx b/tapset-method.cxx index bcf54cdaf..68ab5cdd1 100644 --- a/tapset-method.cxx +++ b/tapset-method.cxx @@ -44,7 +44,6 @@ private: typedef pair java_cache_const_iterator_pair_t; java_cache_t java_cache; - // string helper_path; public: java_builder (): cache_initialized (false) {} @@ -99,7 +98,7 @@ java_builder::build (systemtap_session & sess, bool has_method_str = get_param (parameters, TOK_METHOD, method_str_val); int short_method_pos = method_str_val.find ('('); //only if it exists, run check - bool one_arg = false; + bool one_arg = false; // used to check if there is an argument in the method if (short_method_pos) { int second_method_pos = 0; @@ -107,12 +106,45 @@ java_builder::build (systemtap_session & sess, if ((second_method_pos - short_method_pos) >= 1) one_arg = true; } + vector::iterator it; + vector::iterator is; + int _java_pid = 0; + string _java_proc_class = ""; string short_method_str = method_str_val.substr (0, short_method_pos); string class_str_val; // fully qualified class string bool has_class_str = get_param (parameters, TOK_CLASS, class_str_val); - bool has_pid_int = get_number_param (parameters, TOK_JAVA, sess.java_pid); - bool has_pid_str = get_param (parameters, TOK_JAVA, sess.java_proc_class); + bool has_pid_int = get_number_param (parameters, TOK_JAVA, _java_pid); + bool has_pid_str = get_param (parameters, TOK_JAVA, _java_proc_class); + if (has_pid_int) + { + for (it = sess.java_pid.begin(); it != sess.java_pid.end(); ++it) + { + if(*it == _java_pid) //if we work our way though it all and still doesn't + { + break; // match then we push back on the vector + } + else if ((*it != _java_pid) && ++it == sess.java_pid.end()) + { + sess.java_pid.push_back(_java_pid); + } + } + + } + else + { + for (is = sess.java_proc_class.begin(); is != sess.java_proc_class.end(); ++is) + { + if(*is == _java_proc_class) + { + break; + } + else if ((*is != _java_proc_class) && (++is == sess.java_proc_class.end())) + { + sess.java_proc_class.push_back(_java_proc_class); + } + } + } //need to count the number of parameters, exit if more than 10 int method_params_counter = 1; int method_params_count = count (method_str_val.begin (), method_str_val.end (), ','); @@ -128,24 +160,33 @@ java_builder::build (systemtap_session & sess, (void) has_method_str; assert (has_class_str); (void) has_class_str; - + string _tmp = ""; if (! cache_initialized) { - cache_initialized = true; - sess.byteman_script_path = sess.tmpdir + "/stap-byteman.btm"; + // cache_initialized = true; + if(has_pid_int) + { + _tmp = static_cast ( & (ostringstream () + << (_java_pid)))->str (); + + sess.byteman_script_path.push_back(sess.tmpdir + "/stap-byteman-" + _tmp + ".btm"); + } + else + sess.byteman_script_path.push_back(sess.tmpdir + "/stap-byteman-" + _java_proc_class + ".btm"); + if (sess.verbose > 3) { - clog << "byteman script path: " << sess.byteman_script_path + clog << "byteman script path: " << sess.byteman_script_path.at(*it) << endl; } ofstream byteman_script; - byteman_script.open (sess.byteman_script_path.c_str(), ifstream::out); + byteman_script.open ((sess.byteman_script_path.back()).c_str(), ifstream::app); //| ifstream::out); if (! byteman_script) { if (sess.verbose > 3) //TRANSLATORS: Specific path cannot be opened - clog << sess.byteman_script_path << _(" cannot be opened: ") + clog << sess.byteman_script_path.at(*it) << _(" cannot be opened: ") << strerror (errno) << endl; return; } @@ -153,7 +194,7 @@ java_builder::build (systemtap_session & sess, if (sess.verbose > 2) clog << "Writting byteman script" << endl; // none of this should be translated, byteman syntax is specific - byteman_script << "RULE Stap " << sess.base_hash << endl; + byteman_script << "RULE Stap " << sess.base_hash << method_str_val << endl; // we'll need detection here for second type of syntax // XXX change the method name being passed byteman_script << "CLASS " << class_str_val << endl @@ -162,8 +203,9 @@ java_builder::build (systemtap_session & sess, << "AT ENTRY" << endl << "IF TRUE" << endl << "DO METHOD_STAP_PROBE" << method_params_count - << "(\"stap-" << sess.base_hash << "\", \"" - << short_method_str << "\", "; + << "(\"" << class_str_val << "\", \"" + // << short_method_str << "\", "; + << method_str_val << "\", "; // we need increment the var number, while decrementing the count for (method_params_counter = 1; method_params_counter <= method_params_count; @@ -192,14 +234,15 @@ java_builder::build (systemtap_session & sess, if (! (has_pid_int || has_pid_str) ) exit (1); //XXX proper exit with warning message - string arg = static_cast ( & (ostringstream () - << sess.java_pid) )->str (); + const char* java_pid_str; + if (has_pid_int) + java_pid_str = _tmp.c_str(); + else + java_pid_str = _java_proc_class.c_str(); - const char* java_pid_str = arg.c_str (); - sess.bminstall_path = (find_executable ("bminstall.sh")); - if (sess.verbose > 3) + if (sess.verbose > 2) clog << "Reported bminstall.sh path: " << sess.bminstall_path << endl; // XXX check both scripts here, exit if not available @@ -208,10 +251,16 @@ java_builder::build (systemtap_session & sess, if(!has_pid_str) bminstall_cmd.push_back(java_pid_str); else - bminstall_cmd.push_back(sess.java_proc_class); - - (void) stap_system(sess.verbose, bminstall_cmd); - + bminstall_cmd.push_back(_java_proc_class); + //need to properly check this + int ret = stap_system(sess.verbose, bminstall_cmd); + if (sess.verbose > 2) + { + if (ret) + clog << "WARNING: stap_system for bminstall.sh returned error: " << ret << endl; + else + clog << "stap_system for bminstall.sh returned: " << ret << endl; + } vector bmsubmit_cmd; sess.bmsubmit_path = (find_executable ("bmsubmit.sh")); sess.byteman_log = sess.tmpdir + "/byteman.log"; @@ -219,7 +268,11 @@ java_builder::build (systemtap_session & sess, bmsubmit_cmd.push_back(" -o"); bmsubmit_cmd.push_back(sess.byteman_log); bmsubmit_cmd.push_back(" -l"); - bmsubmit_cmd.push_back(sess.byteman_script_path); + + if(has_pid_int) + bmsubmit_cmd.push_back(sess.byteman_script_path.back()); + else + bmsubmit_cmd.push_back(sess.byteman_script_path.back()); (void) stap_system(sess.verbose, bmsubmit_cmd); if (sess.verbose > 3) clog << "Reported bmsubmit.sh path: " << sess.bmsubmit_path << endl; @@ -230,16 +283,81 @@ java_builder::build (systemtap_session & sess, * using a vector, iterate though, changing as needed * redefine functor values with new literal_string("foo") */ - probe_point* new_loc = new probe_point (*loc); - vector java_marker; - java_marker.push_back( new probe_point::component - (TOK_PROCESS, new literal_string ("/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9.x86_64/jre/lib/amd64/libHelperSDT.so"))); - java_marker.push_back( new probe_point::component - (TOK_MARK, new literal_string ("*"))); - probe_point * derived_loc = new probe_point (*new_loc); - derived_loc->components = java_marker; - probe *new_mark_probe = base->create_alias (derived_loc, new_loc); - derive_probes (sess, new_mark_probe, finished_results); + //XXX can this be moved into its own function, or after root->bind'ing takes place + probe_point* new_loc = new probe_point (*loc); + vector java_marker; + java_marker.push_back( new probe_point::component + (TOK_PROCESS, new literal_string (HAVE_HELPER))); + java_marker.push_back( new probe_point::component + (TOK_MARK, new literal_string ("*"))); + probe_point * derived_loc = new probe_point (*new_loc); + + block *b = new block; + b->tok = base->body->tok; + + // first half of argument + target_symbol *cc = new target_symbol; + cc->tok = b->tok; + cc->name = "$provider"; + + functioncall *ccus = new functioncall; + ccus->function = "user_string"; + ccus->type = pe_string; + ccus->tok = b->tok; + ccus->args.push_back(cc); + + // second half of argument + target_symbol *mc = new target_symbol; + mc->tok = b->tok; + mc->name = "$name"; + + + functioncall *mcus = new functioncall; + mcus->function = "user_string"; + mcus->type = pe_string; + mcus->tok = b->tok; + mcus->args.push_back(mc); + + //build if statement + if_statement *ifs = new if_statement; + ifs->thenblock = new next_statement; + ifs->elseblock = NULL; + ifs->tok = b->tok; + ifs->thenblock->tok = b->tok; + + //class comparison + comparison *ce = new comparison; + ce->op = "!="; + ce->tok = b->tok; + ce->left = ccus; + ce->right = new literal_string(class_str_val); + ce->right->tok = b->tok; + ifs->condition = ce; + b->statements.push_back(ifs); + + //method comparision + comparison *me = new comparison; + me->op = "!="; + me->tok = b->tok; + me->left = mcus; + me->right = new literal_string(method_str_val); + me->right->tok = b->tok; + + logical_or_expr *le = new logical_or_expr; + le->op = "||"; + le->tok = b->tok; + le->left = ce; + le->right = me; + ifs->condition = le; + b->statements.push_back(ifs); + + b->statements.push_back(base->body); + base->body = b; + + derived_loc->components = java_marker; + probe *new_mark_probe = base->create_alias (derived_loc, new_loc); + derive_probes (sess, new_mark_probe, finished_results); + #else cerr << _("Cannot probe java method, configure --with-helper=") << endl; #endif -- 2.43.5