]> sourceware.org Git - systemtap.git/commitdiff
PR17073: module probes: support out-of-tree modules
authorJonathan Lebon <jlebon@redhat.com>
Wed, 9 Jul 2014 14:44:43 +0000 (10:44 -0400)
committerJonathan Lebon <jlebon@redhat.com>
Thu, 10 Jul 2014 19:33:47 +0000 (15:33 -0400)
This patch adds support for out-of-tree modules by specifying the
fullpath. This did not work before because both the _stp_module struct
and the stap_dwarf_probe struct were using the full path as the module
name. This caused issues during relocation of module sections/kprobe
addresses.

In this patch, we use the already existing modname_from_path() function
to modify the module member of the dwarf_derived_probe (which later
affects the stap_dwarf_probe struct) and to emit the proper name in
dump_unwindsym_cxt() for the _stp_module struct.

setupdwfl.cxx
setupdwfl.h
tapsets.cxx
translate.cxx

index c92d31c4295fe18927e5e206f5ef010d2211022d..fe44828f8bf18051dab17e41eac70f135029f7b5 100644 (file)
@@ -105,9 +105,13 @@ static const string abrt_path =
                       ? "/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache"
                     : ""));
 
-// The module name is the basename (without the extension) of the
-// module path, with ',' and '-' replaced by '_'.
-static string
+// The module name is the basename (without the extension) of the module path,
+// with ',' and '-' replaced by '_'. This is a (more or less safe) heuristic:
+// the actual name by which the module is known once inside the kernel is not
+// derived from the path, but from the .gnu.linkonce.this_module section of the
+// KO. In practice, modules in /lib/modules/ respect this convention, and we
+// require it as well for out-of-tree kernel modules.
+string
 modname_from_path(const string &path)
 {
   size_t dot = path.rfind('.');
index 2aaf5f07cb74064848872bf40d58dfbfca3430e0..ab441818834f44dec2a8414d11fac22b5f77f576 100644 (file)
@@ -24,6 +24,8 @@ extern "C" {
 #include <elfutils/libdwfl.h>
 }
 
+std::string modname_from_path(const std::string &path);
+
 Dwfl *setup_dwfl_kernel(const std::string &name,
                          unsigned *found,
                          systemtap_session &s);
index 0052054478d2d706f54847b427c2fe98b0e1c64c..44e44e12e409fc5b99234ec89566a7f32569ca3c 100644 (file)
@@ -4671,6 +4671,9 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
                                          // module & section specify a relocation
                                          // base for <addr>, unless section==""
                                          // (equivalently module=="kernel")
+                                         // for userspace, it's a full path, for
+                                         // modules, it's either a full path, or
+                                         // the basename (e.g. 'btrfs')
                                          const string& module,
                                          const string& section,
                                          // NB: dwfl_addr is the virtualized
@@ -4695,6 +4698,10 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
     saved_longs(0), saved_strings(0),
     entry_handler(0)
 {
+  // If we were given a fullpath to a kernel module, then get the simple name
+  if (q.has_module && is_fully_resolved(module, q.dw.sess.sysroot, q.dw.sess.sysenv))
+    this->module = modname_from_path(module);
+
   if (user_lib.size() != 0)
     has_library = true;
 
@@ -4940,7 +4947,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
           check->args[0]->tok = this->tok;
           check->args.push_back(new literal_number(level));
           check->args[1]->tok = this->tok;
-          check->args.push_back(new literal_string(module));
+          check->args.push_back(new literal_string(this->module));
           check->args[2]->tok = this->tok;
           check->args.push_back(new literal_string(caller_section));
           check->args[3]->tok = this->tok;
index b9101a305da3997132d53ff7ed2b828b7ae7996c..4410cbe8eac7e5d04ac82ab083310e344ef95b1c 100644 (file)
@@ -6289,10 +6289,19 @@ dump_unwindsym_cxt (Dwfl_Module *m,
   // For kernel modules just the name itself.
   string mainpath = resolve_path(mainfile);
   string mainname;
-  if (modname[0] == '/') // userspace
+  if (is_user_module(modname)) // userspace
     mainname = lex_cast_qstring (path_remove_sysroot(c->session,mainpath));
   else
-    mainname = lex_cast_qstring (modname);
+    { // kernel module
+
+      // If the module name is the full path to the ko, then we have to retrieve
+      // the actual name by which the module will be known inside the kernel.
+      // Otherwise, section relocations would be mismatched.
+      if (is_fully_resolved(modname, c->session.sysroot, c->session.sysenv))
+        mainname = lex_cast_qstring (modname_from_path(modname));
+      else
+        mainname = lex_cast_qstring (modname);
+    }
 
   c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n";
   c->output << ".name = " << mainname.c_str() << ",\n";
This page took 0.059014 seconds and 5 git commands to generate.