This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v3 1/3] PR12331: Introduce stap options --sysroot and --sysenv


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 <wade_farnsworth@mentor.com>
---
 cmdline.cxx       |    2 +
 cmdline.h         |    2 +
 dwflpp.cxx        |    4 +-
 hash.cxx          |    3 +-
 main.cxx          |    9 +++++++
 session.cxx       |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 session.h         |    3 ++
 setupdwfl.cxx     |   37 +++++++++++++++++++++++++++----
 setupdwfl.h       |    1 +
 tapset-itrace.cxx |    3 +-
 tapset-utrace.cxx |    3 +-
 tapsets.cxx       |   54 +++++++++++++++++++++++++++++++++------------
 tapsets.h         |    1 +
 translate.cxx     |    4 +-
 util.cxx          |   26 +++++++++++++++++-----
 util.h            |    3 ++
 16 files changed, 184 insertions(+), 33 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 dd42962..6cb2fdb 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<string> &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<string, char*> 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/main.cxx b/main.cxx
index 9e55f8e..4707989 100644
--- a/main.cxx
+++ b/main.cxx
@@ -24,6 +24,7 @@
 #include "csclient.h"
 #include "remote.h"
 #include "tapsets.h"
+#include "setupdwfl.h"
 
 #include <libintl.h>
 #include <locale.h>
@@ -486,6 +487,14 @@ passes_0_4 (systemtap_session &s)
 
   s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
 
+  // Update various paths to include the sysroot, if provided.
+  if (!s.sysroot.empty())
+    {
+      if (s.update_release_sysroot && !s.sysroot.empty())
+        s.kernel_build_tree = s.sysroot + s.kernel_build_tree;
+      debuginfo_path_insert_sysroot(s.sysroot);
+    }
+
   // Now that no further changes to s.kernel_build_tree can occur, let's use it.
   if ((rc = parse_kernel_config (s)) != 0)
     {
diff --git a/session.cxx b/session.cxx
index 24c329a..73b2a19 100644
--- a/session.cxx
+++ b/session.cxx
@@ -149,6 +149,8 @@ systemtap_session::systemtap_session ():
   download_dbinfo = 0;
   suppress_handler_errors = false;
   native_build = true; // presumed
+  sysroot = "";
+  update_release_sysroot = false;
 
   /*  adding in the XDG_DATA_DIRS variable path,
    *  this searches in conjunction with SYSTEMTAP_TAPSET
@@ -310,6 +312,9 @@ systemtap_session::systemtap_session (const systemtap_session& other,
   systemtap_v_check = other.systemtap_v_check;
   download_dbinfo = other.download_dbinfo;
   suppress_handler_errors = other.suppress_handler_errors;
+  sysroot = other.sysroot;
+  update_release_sysroot = other.update_release_sysroot;
+  sysenv = other.sysenv;
 
   include_path = other.include_path;
   runtime_path = other.runtime_path;
@@ -533,6 +538,13 @@ systemtap_session::usage (int exitcode)
     "              yes,no,ask,<timeout value>\n"
     "   --dump-probe-types\n"
     "              show a list of available probe types.\n"
+    "   --sysroot=DIR\n"
+    "              specify sysroot directory where target files (executables,\n"    "              libraries, etc.) 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"
+    "              relative to the sysroot.\n"
     , compatible.c_str()) << endl
   ;
 
@@ -1097,6 +1109,55 @@ 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;
+              }
+              if (!sysroot.empty()) {
+                  cerr << "ERROR: multiple --sysroot options not supported" << 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("/");
+
+                  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;
@@ -1386,6 +1447,7 @@ systemtap_session::setup_kernel_release (const char* kstr)
     }
   else
     {
+      update_release_sysroot = true;
       kernel_release = string (kstr);
       if (!kernel_release.empty())
         kernel_build_tree = "/lib/modules/" + kernel_release + "/build";
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<std::string,char *> sysenv;
+  bool update_release_sysroot;
   std::map<std::string,std::string> kernel_config;
   std::set<std::string> kernel_exports;
   std::string machine;
diff --git a/setupdwfl.cxx b/setupdwfl.cxx
index 82bc42a..91bfd39 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;
diff --git a/setupdwfl.h b/setupdwfl.h
index 48f9105..aa1c800 100644
--- a/setupdwfl.h
+++ b/setupdwfl.h
@@ -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..94a47da 100644
--- a/tapset-itrace.cxx
+++ b/tapset-itrace.cxx
@@ -114,8 +114,9 @@ struct itrace_builder: public derived_probe_builder
     // If we have a path, we need to validate it.
     if (has_path)
       {
-        path = find_executable (path);
+        path = find_executable (path, sess.sysroot, sess.sysenv);
         sess.unwindsym_modules.insert (path);
+        path_remove_sysroot(sess, path);
       }
 
     finished_results.push_back(new itrace_derived_probe(sess, base, location,
diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx
index 64ba900..8c98435 100644
--- a/tapset-utrace.cxx
+++ b/tapset-utrace.cxx
@@ -679,8 +679,9 @@ struct utrace_builder: public derived_probe_builder
       }
     else if (has_path)
       {
-        path = find_executable (path);
+        path = find_executable (path, sess.sysroot, sess.sysenv);
         sess.unwindsym_modules.insert (path);
+        path_remove_sysroot(sess, path);
       }
     else if (has_pid)
       {
diff --git a/tapsets.cxx b/tapsets.cxx
index 716e23c..c2d00bb 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;
@@ -1127,6 +1128,13 @@ bad:
                        base_probe->tok);
 }
 
+void path_remove_sysroot(const systemtap_session& sess, string& path)
+{
+  size_t pos;
+  if (!sess.sysroot.empty() &&
+      (pos = path.find(sess.sysroot)) != string::npos)
+    path.replace(pos, sess.sysroot.length(), "/");
+}
 
 void
 dwarf_query::add_probe_point(const string& dw_funcname,
@@ -1137,7 +1145,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 +1196,8 @@ dwarf_query::add_probe_point(const string& dw_funcname,
 
       if (has_process)
         {
+          path_remove_sysroot(sess, module);
+          path_remove_sysroot(sess, path);
           results.push_back (new uprobe_derived_probe(funcname, filename, line,
                                                       module, reloc_section, addr, reloc_addr,
                                                       *this, scope_die));
@@ -2051,7 +2061,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<probe_point::component*> derived_comps;
@@ -3906,7 +3917,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 +6557,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 +6617,10 @@ 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;
+                  path_remove_sysroot(sess, eglobbed);
 
                   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 +6646,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 +6692,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 +6719,10 @@ 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;
+                  path_remove_sysroot(sess, user_path_tgt);
                   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 +6741,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 +8206,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 +8229,16 @@ kprobe_builder::build(systemtap_session &,
   has_library = get_param (parameters, TOK_LIBRARY, library);
 
   if (has_path)
-    path = find_executable (path);
+    {
+      path = find_executable (path, sess.sysroot, sess.sysenv);
+      path_remove_sysroot(sess, path);
+    }
   if (has_library)
-    library = find_executable (library, "LD_LIBRARY_PATH");
+    {
+      library = find_executable (library, sess.sysroot, sess.sysenv,
+                                 "LD_LIBRARY_PATH");
+      path_remove_sysroot(sess, library);
+    }
 
   if (has_function_str)
     {
diff --git a/tapsets.h b/tapsets.h
index c5fb30c..530bf51 100644
--- a/tapsets.h
+++ b/tapsets.h
@@ -31,6 +31,7 @@ void register_tapset_timers(systemtap_session& sess);
 void register_tapset_perf(systemtap_session& sess);
 void register_tapset_utrace(systemtap_session& sess);
 
+void path_remove_sysroot(const systemtap_session& sess, std::string& path);
 
 // ------------------------------------------------------------------------
 // Generic derived_probe_group: contains an ordinary vector of the
diff --git a/translate.cxx b/translate.cxx
index 97847a8..2b8d012 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/";
 
diff --git a/util.cxx b/util.cxx
index c14695b..7ece67f 100644
--- a/util.cxx
+++ b/util.cxx
@@ -346,7 +346,8 @@ tokenize_cxx(const string& str, vector<string>& 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<string, char*>& sysenv, const string& env_path)
 {
   string retpath;
 
@@ -357,11 +358,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.
@@ -371,7 +376,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<string>::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.
@@ -390,13 +395,22 @@ 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
+          throw runtime_error(_F("find_executable(): file %s not in sysroot %s", cf, sysroot.c_str()));
+      }
       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 <cctype>
 #include <set>
 #include <iomanip>
+#include <map>
 extern "C" {
 #include <libintl.h>
 #include <locale.h>
@@ -51,6 +52,8 @@ void tokenize(const std::string& str, std::vector<std::string>& tokens,
 	      const std::string& delimiters);
 void tokenize_cxx(const std::string& str, std::vector<std::string>& tokens);
 std::string find_executable(const std::string& name,
+			    const std::string& sysroot,
+			    std::map<std::string,char *>& sysenv,
 			    const std::string& env_path = "PATH");
 const std::string cmdstr_quoted(const std::string& cmd);
 const std::string cmdstr_join(const std::vector<std::string>& cmds);
-- 
1.7.0.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]