From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24337 invoked by alias); 9 Jan 2012 14:51:52 -0000 Received: (qmail 24321 invoked by uid 22791); 9 Jan 2012 14:51:49 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL,BAYES_00,TW_RG,TW_TM X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 09 Jan 2012 14:51:30 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1RkGZN-0000jk-DL from wade_farnsworth@mentor.com for systemtap@sourceware.org; Mon, 09 Jan 2012 06:51:29 -0800 Received: from SVR-ORW-FEM-03.mgc.mentorg.com ([147.34.97.39]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Mon, 9 Jan 2012 06:51:14 -0800 Received: from [172.30.8.33] (147.34.91.1) by svr-orw-fem-03.mgc.mentorg.com (147.34.97.39) with Microsoft SMTP Server id 14.1.289.1; Mon, 9 Jan 2012 06:51:28 -0800 Message-ID: <4F0AFEEE.30909@mentor.com> Date: Mon, 09 Jan 2012 14:51:00 -0000 From: Wade Farnsworth User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110424 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: Subject: [PATCH] Add --sysroot option Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2012-q1/txt/msg00012.txt.bz2 This adds a --sysroot option to facilitate different file locations for user-space processes and libraries at compile-time versus run-time when generating stap kernel modules for a remote system. For example if we compile the probe: process("/bin/foo").begin {} while passing "--sysroot=/bar/baz" to stap, symbols will be taken from /bar/baz/bin/foo, but the resulting .ko will still refer to /bin/foo. This allows the probe to be used on a different machine than the one it is compiled on, so long as the compiling machine replicates the necessary files in the sysroot directory. This is a fairly typical use case for embedded Linux. Known limitations: 1. Probes must contain the absolute file path to the process or library. If a relative path is used, it will be assumed to be located in the top level of the sysroot. 2. Similarly probes on scripts containing "#!/usr/bin/env bash" or similar will also assume that the interpreter is located in the sysroot top level. The reason for these limitations is that we do not have access to the target machine's environment compile-time, so some assumptions must necessarily be made. Signed-off-by: Wade Farnsworth --- session.cxx | 16 ++++++++++++++++ session.h | 1 + tapset-itrace.cxx | 5 ++++- tapset-utrace.cxx | 5 ++++- tapsets.cxx | 53 +++++++++++++++++++++++++++++++++++++++++------------ 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/session.cxx b/session.cxx index f4ce8a6..1c1adbf 100644 --- a/session.cxx +++ b/session.cxx @@ -84,6 +84,7 @@ systemtap_session::systemtap_session (): kernel_release = string (buf.release); release = kernel_release; kernel_build_tree = "/lib/modules/" + kernel_release + "/build"; + sysroot = string(); architecture = machine = normalize_machine(buf.machine); for (unsigned i=0; i<5; i++) perpass_verbose[i]=0; @@ -534,6 +535,8 @@ systemtap_session::usage (int exitcode) " yes,no,ask,\n" " --dump-probe-types\n" " show a list of available probe types.\n" + " --sysroot=DIR\n" + " specify sysroot directory where executables are located" , compatible.c_str()) << endl ; @@ -587,6 +590,7 @@ systemtap_session::parse_cmdline (int argc, char * const argv []) #define LONG_OPT_PRIVILEGE 28 #define LONG_OPT_SUPPRESS_HANDLER_ERRORS 29 #define LONG_OPT_MODINFO 30 +#define LONG_OPT_SYSROOT 31 // NB: also see find_hash(), usage(), switch stmt below, stap.1 man page static struct option long_options[] = { { "kelf", 0, &long_opt, LONG_OPT_KELF }, @@ -625,6 +629,7 @@ systemtap_session::parse_cmdline (int argc, char * const argv []) { "privilege", 1, &long_opt, LONG_OPT_PRIVILEGE }, { "suppress-handler-errors", 0, &long_opt, LONG_OPT_SUPPRESS_HANDLER_ERRORS }, { "modinfo", 1, &long_opt, LONG_OPT_MODINFO }, + { "sysroot", 1, &long_opt, LONG_OPT_SYSROOT }, { NULL, 0, NULL, 0 } }; int grc = getopt_long (argc, argv, "hVvtp:I:e:o:R:r:a:m:kgPc:x:D:bs:uqwl:d:L:FS:B:WG:", @@ -1151,6 +1156,17 @@ systemtap_session::parse_cmdline (int argc, char * const argv []) modinfos.push_back (string(optarg)); break; + case LONG_OPT_SYSROOT: + { + const char *spath = canonicalize_file_name (optarg); + if (spath == NULL) { + cerr << _F("ERROR: %s is an invalid directory for --sysroot", optarg) << endl; + return 1; + } + sysroot = string(spath) + "/"; + break; + } + default: // NOTREACHED unless one added a getopt option but not a corresponding switch/case: cerr << _F("Unhandled long argument id %d", long_opt) << endl; diff --git a/session.h b/session.h index 64a22a5..f1a301b 100644 --- a/session.h +++ b/session.h @@ -140,6 +140,7 @@ public: std::string kernel_base_release; std::string kernel_build_tree; std::string kernel_source_tree; + std::string sysroot; std::map kernel_config; std::set kernel_exports; std::string machine; diff --git a/tapset-itrace.cxx b/tapset-itrace.cxx index 1a9bf67..77811d5 100644 --- a/tapset-itrace.cxx +++ b/tapset-itrace.cxx @@ -114,8 +114,11 @@ struct itrace_builder: public derived_probe_builder // If we have a path, we need to validate it. if (has_path) { - path = find_executable (path); + size_t pos; + path = find_executable (sess.sysroot + path); sess.unwindsym_modules.insert (path); + if (!sess.sysroot.empty() && ((pos = path.find(sess.sysroot)) != string::npos)) + path.replace(pos, sess.sysroot.length(), "/"); } finished_results.push_back(new itrace_derived_probe(sess, base, location, diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index 64ba900..11cf292 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -679,8 +679,11 @@ struct utrace_builder: public derived_probe_builder } else if (has_path) { - path = find_executable (path); + size_t pos; + path = find_executable (sess.sysroot + path); sess.unwindsym_modules.insert (path); + if (!sess.sysroot.empty() && ((pos = path.find(sess.sysroot)) != string::npos)) + path.replace(pos, sess.sysroot.length(), "/"); } else if (has_pid) { diff --git a/tapsets.cxx b/tapsets.cxx index 177f565..50464dc 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -584,13 +584,13 @@ base_query::base_query(dwflpp & dw, literal_map_t const & params): has_statement = get_number_param(params, TOK_STATEMENT, statement_num_val); if (has_process) - module_val = find_executable (module_val); + module_val = find_executable (sess.sysroot + module_val); if (has_library) { if (! contains_glob_chars (library_name)) { path = module_val; - module_val = find_executable (library_name, "LD_LIBRARY_PATH"); + module_val = find_executable (sess.sysroot + library_name, "LD_LIBRARY_PATH"); } else path = library_name; @@ -1139,7 +1139,7 @@ dwarf_query::add_probe_point(const string& dw_funcname, { string reloc_section; // base section for relocation purposes Dwarf_Addr reloc_addr; // relocated - const string& module = dw.module_name; // "kernel" or other + string& module = dw.module_name; // "kernel" or other string funcname = dw_funcname; assert (! has_absolute); // already handled in dwarf_builder::build() @@ -1190,6 +1190,14 @@ dwarf_query::add_probe_point(const string& dw_funcname, if (has_process) { + if (!sess.sysroot.empty()) + { + size_t pos; + if ((pos = module.find(sess.sysroot)) != string::npos) + module.replace(pos, sess.sysroot.length(), "/"); + if ((pos = path.find(sess.sysroot)) != string::npos) + path.replace(pos, sess.sysroot.length(), "/"); + } results.push_back (new uprobe_derived_probe(funcname, filename, line, module, reloc_section, addr, reloc_addr, *this, scope_die)); @@ -6548,13 +6556,14 @@ dwarf_builder::build(systemtap_session & sess, } else if (get_param (parameters, TOK_PROCESS, module_name) || has_null_param(parameters, TOK_PROCESS)) { + module_name = sess.sysroot + module_name; if(has_null_param(filled_parameters, TOK_PROCESS)) { wordexp_t words; int rc = wordexp(sess.cmd.c_str(), &words, WRDE_NOCMD|WRDE_UNDEF); if(rc || words.we_wordc <= 0) throw semantic_error(_("unspecified process probe is invalid without a -c COMMAND")); - module_name = words.we_wordv[0]; + module_name = sess.sysroot + words.we_wordv[0]; filled_parameters[TOK_PROCESS] = new literal_string(module_name);// this needs to be used in place of the blank map // in the case of TOK_MARK we need to modify locations as well if(location->components[0]->functor==TOK_PROCESS && @@ -6607,9 +6616,15 @@ dwarf_builder::build(systemtap_session & sess, if (sess.verbose > 1) clog << _F("Expanded process(\"%s\") to process(\"%s\")", module_name.c_str(), eglobbed.c_str()) << endl; + if (!sess.sysroot.empty()) + { + size_t pos; + if ((pos = eglobbed.find(sess.sysroot)) != string::npos) + eglobbed.replace(pos, sess.sysroot.length(), "/"); + } probe_point::component* ppc = new probe_point::component (TOK_PROCESS, - new literal_string (eglobbed)); + new literal_string (eglobbed)); ppc->tok = location->components[0]->tok; // overwrite [0] slot, pattern matched above pp->components[0] = ppc; @@ -6681,12 +6696,12 @@ dwarf_builder::build(systemtap_session & sess, if (p3 != string::npos) { string env_path = path.substr(p3); - user_path = find_executable (env_path); + user_path = find_executable (sess.sysroot + env_path); } } else { - user_path = find_executable (path); + user_path = find_executable (sess.sysroot + path); } struct stat st; @@ -6707,8 +6722,12 @@ dwarf_builder::build(systemtap_session & sess, // synthesize a new probe_point, with the expanded string probe_point *pp = new probe_point (*location); + string user_path_tgt = user_path; + size_t pos; + if (!sess.sysroot.empty() && ((pos = path.find(sess.sysroot)) != string::npos)) + user_path_tgt.replace(pos, sess.sysroot.length(), "/"); probe_point::component* ppc = new probe_point::component (TOK_PROCESS, - new literal_string (user_path.c_str())); + new literal_string (user_path_tgt.c_str())); ppc->tok = location->components[0]->tok; // overwrite [0] slot, pattern matched above pp->components[0] = ppc; @@ -6727,7 +6746,7 @@ dwarf_builder::build(systemtap_session & sess, if(get_param (parameters, TOK_LIBRARY, user_lib) && user_lib.length() && ! contains_glob_chars (user_lib)) - module_name = find_executable (user_lib, "LD_LIBRARY_PATH"); + module_name = find_executable (sess.sysroot + user_lib, "LD_LIBRARY_PATH"); else module_name = user_path; // canonicalize it @@ -8195,7 +8214,7 @@ struct kprobe_builder: public derived_probe_builder void -kprobe_builder::build(systemtap_session &, +kprobe_builder::build(systemtap_session & sess, probe * base, probe_point * location, literal_map_t const & parameters, @@ -8218,9 +8237,19 @@ kprobe_builder::build(systemtap_session &, has_library = get_param (parameters, TOK_LIBRARY, library); if (has_path) - path = find_executable (path); + { + size_t pos; + path = find_executable (sess.sysroot + path); + if (!sess.sysroot.empty() && ((pos = path.find(sess.sysroot)) != string::npos)) + path.replace(pos, sess.sysroot.length(), "/"); + } if (has_library) - library = find_executable (library, "LD_LIBRARY_PATH"); + { + size_t pos; + library = find_executable (sess.sysroot + library, "LD_LIBRARY_PATH"); + if (!sess.sysroot.empty() && ((pos = library.find(sess.sysroot)) != string::npos)) + library.replace(pos, sess.sysroot.length(), "/"); + } if (has_function_str) { -- 1.7.0.4