From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10722 invoked by alias); 9 Feb 2012 18:26:56 -0000 Received: (qmail 10701 invoked by uid 22791); 9 Feb 2012 18:26:52 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL,BAYES_00,TW_CP,TW_DW,TW_FL,TW_RG 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; Thu, 09 Feb 2012 18:26:35 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1RvYhW-0002vy-A3 from wade_farnsworth@mentor.com ; Thu, 09 Feb 2012 10:26:34 -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); Thu, 9 Feb 2012 10:26:26 -0800 Received: from [172.30.9.122] (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; Thu, 9 Feb 2012 10:26:32 -0800 Message-ID: <4F340FD7.9010205@mentor.com> Date: Thu, 09 Feb 2012 18:26: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 v2] PR12331: Introduce stap options --sysroot and --sysenv References: <4F0AFEEE.30909@mentor.com> In-Reply-To: <4F0AFEEE.30909@mentor.com> 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/msg00140.txt.bz2 This adds new command-line options to facilitate different file locations at compile-time versus run-time when generating stap kernel modules for a remote system: 1. --sysroot=DIR Specifies a separate filesystem for the remote system on the local system. The following stap functionalities will make use of this: a. When compiling process and library probes with a remote filesystem path (e.g. process("/bin/foo") with --sysroot=/bar/baz). In this case symbols will be taken from the local filesystem (/bar/baz/bin/foo), but the resulting .ko will still contain paths on the remote filesystem (/bin/foo). b. When passing a kernel release with -r (not a full path), the kernel build directory will be expected in the sysroot. c. When DWARF debug info is contained in a separate file from the executable, the sysroot is used to find the debug info files. d. All calls to find_executable() search the path passed in the argument env_path relative to the sysroot. For example if PATH=/bin/foo, and --sysroot=/bar/baz is provided, then find_executable() called with env_path == "PATH" will search /bar/baz/bin/foo. e. stap attempts to detect if a path in a probe would be outside of the sysroot and errors appropriately. This situation may occur, for example, if the path contains several ".." directories. 2. --sysenv=VAR=VALUE Specifies a different environment variable for the remote system as opposed to the local one, and that the value on the remote system should be used. Currently only valid env_path arguments to find_executable() are handled (i.e. PATH, LD_LIBRARY_PATH). If --sysroot is provided and --sysenv is omitted, then the local environment relative to the sysroot will be used. These options are disabled for systemtap clients. Signed-off-by: Wade Farnsworth --- Josh, I believe I have implemented all of your comments on the previous version of this patch. Any further suggestions are welcome! -v2: Implemented several improvements per Josh Stone's comment. cmdline.cxx | 2 + cmdline.h | 2 + dwflpp.cxx | 4 +- hash.cxx | 3 +- session.cxx | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++- session.h | 3 ++ setupdwfl.cxx | 39 ++++++++++++++++++++++++++---- setupdwfl.h | 3 +- tapset-itrace.cxx | 5 +++- tapset-utrace.cxx | 5 +++- tapsets.cxx | 64 ++++++++++++++++++++++++++++++++++++++------------ translate.cxx | 6 ++-- util.cxx | 28 +++++++++++++++++---- util.h | 3 ++ 14 files changed, 197 insertions(+), 37 deletions(-) diff --git a/cmdline.cxx b/cmdline.cxx index 88e02f9..881a5c3 100644 --- a/cmdline.cxx +++ b/cmdline.cxx @@ -50,5 +50,7 @@ struct option stap_long_options[] = { { "privilege", 1, &stap_long_opt, LONG_OPT_PRIVILEGE }, { "suppress-handler-errors", 0, &stap_long_opt, LONG_OPT_SUPPRESS_HANDLER_ERRORS }, { "modinfo", 1, &stap_long_opt, LONG_OPT_MODINFO }, + { "sysroot", 1, &stap_long_opt, LONG_OPT_SYSROOT }, + { "sysenv", 1, &stap_long_opt, LONG_OPT_SYSENV }, { NULL, 0, NULL, 0 } }; diff --git a/cmdline.h b/cmdline.h index 3229a7b..680f290 100644 --- a/cmdline.h +++ b/cmdline.h @@ -44,6 +44,8 @@ extern "C" { #define LONG_OPT_PRIVILEGE 28 #define LONG_OPT_SUPPRESS_HANDLER_ERRORS 29 #define LONG_OPT_MODINFO 30 +#define LONG_OPT_SYSROOT 31 +#define LONG_OPT_SYSENV 32 // NB: when adding new options, consider very carefully whether they // should be restricted from stap clients (after --client-options)! diff --git a/dwflpp.cxx b/dwflpp.cxx index 4d78187..17fd5c6 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -321,7 +321,7 @@ dwflpp::setup_kernel(const string& name, systemtap_session & s, bool debuginfo_n { if (debuginfo_needed) { // Suggest a likely kernel dir to find debuginfo rpm for - string dir = string("/lib/modules/" + sess.kernel_release ); + string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release ); find_debug_rpms(sess, dir.c_str()); } throw semantic_error (_F("missing %s kernel/module debuginfo under '%s'", @@ -359,7 +359,7 @@ dwflpp::setup_kernel(const vector &names, bool debuginfo_needed) { if (debuginfo_needed) { // Suggest a likely kernel dir to find debuginfo rpm for - string dir = string("/lib/modules/" + sess.kernel_release ); + string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release ); find_debug_rpms(sess, dir.c_str()); } throw semantic_error (_F("missing %s kernel/module debuginfo under '%s'", diff --git a/hash.cxx b/hash.cxx index c435a03..69334f5 100644 --- a/hash.cxx +++ b/hash.cxx @@ -133,6 +133,7 @@ void create_hash_log(const string &type_str, const string &parms, const string & static const hash& get_base_hash (systemtap_session& s) { + map dummy; if (s.base_hash) return *s.base_hash; @@ -158,7 +159,7 @@ get_base_hash (systemtap_session& s) // Hash compiler path, size, and mtime. We're just going to assume // we'll be using gcc. XXX: getting kbuild to spit out out would be // better, especially since this is fooled by ccache. - h.add_path("Compiler ", find_executable("gcc")); + h.add_path("Compiler ", find_executable("gcc", "", dummy)); // Hash the systemtap size and mtime. We could use VERSION/DATE, // but when developing systemtap that doesn't work well (since you diff --git a/session.cxx b/session.cxx index 24c329a..2c5be33 100644 --- a/session.cxx +++ b/session.cxx @@ -20,6 +20,7 @@ #include "util.h" #include "cmdline.h" #include "git_version.h" +#include "setupdwfl.h" #include #include @@ -86,6 +87,8 @@ systemtap_session::systemtap_session (): kernel_release = string (buf.release); release = kernel_release; kernel_build_tree = "/lib/modules/" + kernel_release + "/build"; + sysroot = ""; + update_release_sysroot = false; architecture = machine = normalize_machine(buf.machine); for (unsigned i=0; i<5; i++) perpass_verbose[i]=0; @@ -533,6 +536,13 @@ 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.\n" + " --sysenv=VAR=VALUE\n" + " provide an alternate value for an environment variable\n" + " where the value on a remote system differs. Path\n" + " variables (e.g. PATH, LD_LIBRARY_PATH) are assumed to be\n" + " relatve to the sysroot.\n" , compatible.c_str()) << endl ; @@ -1097,6 +1107,56 @@ systemtap_session::parse_cmdline (int argc, char * const argv []) modinfos.push_back (string(optarg)); break; + case LONG_OPT_SYSROOT: + if (client_options) { + cerr << _F("ERROR: %s invalid with %s", "--sysroot", "--client-options") << endl; + return 1; + } else { + 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); + if (sysroot[sysroot.size() - 1] != '/') + sysroot.append("/"); + + if (update_release_sysroot) + kernel_build_tree = sysroot + kernel_build_tree; + + debuginfo_path_insert_sysroot(sysroot); + + break; + } + case LONG_OPT_SYSENV: + if (client_options) { + cerr << _F("ERROR: %s invalid with %s", "--sysenv", "--client-options") << endl; + return 1; + } else { + string sysenv_str = optarg; + string value_str; + char * value; + size_t pos; + if (sysroot.empty()) { + cerr << "ERROR: --sysenv must follow --sysroot" << endl; + return 1; + } + + pos = sysenv_str.find("="); + if (pos == string::npos) { + cerr << _F("ERROR: %s is an invalid argument for --sysenv", optarg) << endl; + return 1; + } + + value_str = sysenv_str.substr(pos + 1); + value = new char[value_str.size()+1]; + strcpy(value, value_str.c_str()); + sysenv[sysenv_str.substr(0, pos)] = value; + + break; + } + default: // NOTREACHED unless one added a getopt option but not a corresponding switch/case: cerr << _F("Unhandled long argument id %d", stap_long_opt) << endl; @@ -1387,8 +1447,13 @@ systemtap_session::setup_kernel_release (const char* kstr) else { kernel_release = string (kstr); - if (!kernel_release.empty()) + if (!kernel_release.empty()) { kernel_build_tree = "/lib/modules/" + kernel_release + "/build"; + if (sysroot.empty()) + update_release_sysroot = true; + else + kernel_build_tree = sysroot + kernel_build_tree; + } // PR10745 // Let's not look for the kernel_source_tree; it's definitely diff --git a/session.h b/session.h index e128b2f..b5b8d82 100644 --- a/session.h +++ b/session.h @@ -140,6 +140,9 @@ public: std::string kernel_base_release; std::string kernel_build_tree; std::string kernel_source_tree; + std::string sysroot; + std::map sysenv; + bool update_release_sysroot; std::map kernel_config; std::set kernel_exports; std::string machine; diff --git a/setupdwfl.cxx b/setupdwfl.cxx index 82bc42a..fbffaf0 100644 --- a/setupdwfl.cxx +++ b/setupdwfl.cxx @@ -39,14 +39,14 @@ extern "C" { // XXX: also consider adding $HOME/.debug/ for perf build-id-cache static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug:build"; static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH"); -static const char *debuginfo_path = (debuginfo_env_arr ?: debuginfo_path_arr); +static char *debuginfo_path = (char *)(debuginfo_env_arr ?: debuginfo_path_arr); // NB: kernel_build_tree doesn't enter into this, as it's for // kernel-side modules only. // XXX: also consider adding $HOME/.debug/ for perf build-id-cache static const char *debuginfo_usr_path_arr = "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug"; -static const char *debuginfo_usr_path = (debuginfo_env_arr - ?: debuginfo_usr_path_arr); +static char *debuginfo_usr_path = (char *)(debuginfo_env_arr + ?: debuginfo_usr_path_arr); // A pointer to the current systemtap session for use only by a few // dwfl calls. DO NOT rely on this, as it is cleared after use. @@ -146,7 +146,10 @@ setup_mod_deps() } else { - modulesdep = "/lib/modules/"; + string sysroot = ""; + if (current_session_for_find_debuginfo) + sysroot = current_session_for_find_debuginfo->sysroot; + modulesdep = sysroot + "/lib/modules/"; modulesdep += elfutils_kernel_path; modulesdep += "/modules.dep"; } @@ -280,6 +283,30 @@ setup_dwfl_report_kernel_p(const char* modname, const char* filename) } } +static char * path_insert_sysroot(string sysroot, string path) +{ + char * path_new; + size_t pos = 1; + if (path[0] == '/') + path.replace(0, 1, sysroot); + while (true) { + pos = path.find(":/", pos); + if (pos == string::npos) + break; + path.replace(pos, 2, ":" + sysroot); + ++pos; + } + path_new = new char[path.size()+1]; + strcpy (path_new, path.c_str()); + return path_new; +} + +void debuginfo_path_insert_sysroot(string sysroot) +{ + debuginfo_path = path_insert_sysroot(sysroot, debuginfo_path); + debuginfo_usr_path = path_insert_sysroot(sysroot, debuginfo_usr_path); +} + static DwflPtr setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) { @@ -295,7 +322,7 @@ setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) // no way to set the dwfl_callback.debuginfo_path and always // passs the plain kernel_release here. So instead we have to // hard-code this magic here. - if (s.kernel_build_tree == string("/lib/modules/" + if (s.kernel_build_tree == string(s.sysroot + "/lib/modules/" + s.kernel_release + "/build")) elfutils_kernel_path = s.kernel_release; @@ -413,7 +440,7 @@ setup_dwfl_kernel(const std::set &names, } DwflPtr -setup_dwfl_user(const std::string &name) +setup_dwfl_user(const std::string &name, systemtap_session &s) { if (user_dwfl != NULL && user_modset.size() == 1 diff --git a/setupdwfl.h b/setupdwfl.h index 48f9105..4686574 100644 --- a/setupdwfl.h +++ b/setupdwfl.h @@ -50,7 +50,7 @@ DwflPtr setup_dwfl_kernel(const std::set &names, unsigned *found, systemtap_session &s); -DwflPtr setup_dwfl_user(const std::string &name); +DwflPtr setup_dwfl_user(const std::string &name, systemtap_session &s); DwflPtr setup_dwfl_user(std::vector::const_iterator &begin, const std::vector::const_iterator &end, bool all_needed, systemtap_session &s); @@ -69,5 +69,6 @@ int internal_find_debuginfo (Dwfl_Module *mod, int execute_abrt_action_install_debuginfo_to_abrt_cache (std::string hex); std::string get_kernel_build_id (systemtap_session &s); int download_kernel_debuginfo (systemtap_session &s, std::string hex); +void debuginfo_path_insert_sysroot(std::string sysroot); #endif diff --git a/tapset-itrace.cxx b/tapset-itrace.cxx index 1a9bf67..0e623fe 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 (path, sess.sysroot, sess.sysenv); 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..133d42a 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 (path, sess.sysroot, sess.sysenv); 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 cb56170..6cdb8e1 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -584,13 +584,14 @@ 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 (module_val, sess.sysroot, sess.sysenv); 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 (library_name, sess.sysroot, + sess.sysenv, "LD_LIBRARY_PATH"); } else path = library_name; @@ -1137,7 +1138,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() @@ -1188,6 +1189,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)); @@ -2051,7 +2060,8 @@ query_one_library (const char *library, dwflpp & dw, { if (dw.function_name_matches_pattern(library, user_lib)) { - string library_path = find_executable (library, "LD_LIBRARY_PATH"); + string library_path = find_executable (library, "", dw.sess.sysenv, + "LD_LIBRARY_PATH"); probe_point* specific_loc = new probe_point(*base_loc); specific_loc->optional = true; vector derived_comps; @@ -3906,7 +3916,7 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) } else { - module = find_executable (module); // canonicalize it + module = find_executable (module, "", s.sysenv); // canonicalize it dw = db.get_user_dw(s, module); } } @@ -6546,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 && @@ -6605,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; @@ -6633,7 +6650,7 @@ dwarf_builder::build(systemtap_session & sess, // PR13338: unquote glob results module_name = unescape_glob_chars (module_name); - user_path = find_executable (module_name); // canonicalize it + user_path = find_executable (module_name, "", sess.sysenv); // canonicalize it // if the executable starts with "#!", we look for the interpreter of the script { @@ -6679,12 +6696,13 @@ 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 (env_path, sess.sysroot, + sess.sysenv); } } else { - user_path = find_executable (path); + user_path = find_executable (path, sess.sysroot, sess.sysenv); } struct stat st; @@ -6705,8 +6723,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; @@ -6725,7 +6747,8 @@ 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 (user_lib, sess.sysroot, sess.sysenv, + "LD_LIBRARY_PATH"); else module_name = user_path; // canonicalize it @@ -8189,7 +8212,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, @@ -8212,9 +8235,20 @@ 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 (path, sess.sysroot, sess.sysenv); + 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 (library, sess.sysroot, sess.sysenv, + "LD_LIBRARY_PATH"); + if (!sess.sysroot.empty() && ((pos = library.find(sess.sysroot)) != string::npos)) + library.replace(pos, sess.sysroot.length(), "/"); + } if (has_function_str) { diff --git a/translate.cxx b/translate.cxx index 97847a8..70c4751 100644 --- a/translate.cxx +++ b/translate.cxx @@ -6242,10 +6242,10 @@ add_unwindsym_vdso (systemtap_session &s) // having the BUILDDIR we need to do a deep search (the specific // arch name dir in the kernel build tree is unknown). string vdso_dir; - if (s.kernel_build_tree == string("/lib/modules/" + if (s.kernel_build_tree == string(s.sysroot + "/lib/modules/" + s.kernel_release + "/build")) - vdso_dir = "/lib/modules/" + s.kernel_release + "/vdso"; + vdso_dir = s.sysroot + "/lib/modules/" + s.kernel_release + "/vdso"; else vdso_dir = s.kernel_build_tree + "/arch/"; @@ -6353,7 +6353,7 @@ emit_symbol_data (systemtap_session& s) string modname = *it; assert (modname.length() != 0); if (! is_user_module (modname)) continue; - DwflPtr dwfl_ptr = setup_dwfl_user (modname); + DwflPtr dwfl_ptr = setup_dwfl_user (modname, s); Dwfl *dwfl = dwfl_ptr.get()->dwfl; if (dwfl != NULL) // tolerate missing data; will warn below { diff --git a/util.cxx b/util.cxx index 93cf12a..4158f0d 100644 --- a/util.cxx +++ b/util.cxx @@ -345,7 +345,8 @@ tokenize_cxx(const string& str, vector& tokens) // same policy as execvp(). A program name not containing a slash // will be searched along the $PATH. -string find_executable(const string& name, const string& env_path) +string find_executable(const string& name, const string& sysroot, + map& sysenv, const string& env_path) { string retpath; @@ -356,11 +357,15 @@ string find_executable(const string& name, const string& env_path) if (name.find('/') != string::npos) // slash in the path already? { - retpath = name; + retpath = sysroot + name; } else // Nope, search $PATH. { - char *path = getenv(env_path.c_str()); + char *path; + if (sysenv.count(env_path) != 0) + path = sysenv[env_path]; + else + path = getenv(env_path.c_str()); if (path) { // Split PATH up. @@ -370,7 +375,7 @@ string find_executable(const string& name, const string& env_path) // Search the path looking for the first executable of the right name. for (vector::iterator i = dirs.begin(); i != dirs.end(); i++) { - string fname = *i + "/" + name; + string fname = sysroot + *i + "/" + name; const char *f = fname.c_str(); // Look for a normal executable file. @@ -389,13 +394,24 @@ string find_executable(const string& name, const string& env_path) // Could not find the program on the $PATH. We'll just fall back to // the unqualified name, which our caller will probably fail with. if (retpath == "") - retpath = name; + retpath = sysroot + name; // Canonicalize the path name. char *cf = canonicalize_file_name (retpath.c_str()); if (cf) { - retpath = string(cf); + string scf = string(cf); + if (sysroot.empty()) + retpath = scf; + else { + int pos = scf.find(sysroot); + if (pos == 0) + retpath = scf; + else { + cerr << _F("ERROR: file %s not in sysroot %s", cf, sysroot.c_str()) << endl; + exit(1); + } + } free (cf); } diff --git a/util.h b/util.h index e576036..44e41e4 100644 --- a/util.h +++ b/util.h @@ -12,6 +12,7 @@ #include #include #include +#include extern "C" { #include #include @@ -51,6 +52,8 @@ void tokenize(const std::string& str, std::vector& tokens, const std::string& delimiters); void tokenize_cxx(const std::string& str, std::vector& tokens); std::string find_executable(const std::string& name, + const std::string& sysroot, + std::map& sysenv, const std::string& env_path = "PATH"); const std::string cmdstr_quoted(const std::string& cmd); const std::string cmdstr_join(const std::vector& cmds); -- 1.7.0.4