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]

Re: Accessing user-space global variables in timer.profile?


Hello!

On Mon, Apr 22, 2013 at 6:23 PM, Josh Stone wrote:
> So we'll need a @var which at least hints which module holds it, as
> described in http://sourceware.org/bugzilla/show_bug.cgi?id=11096#c5
>
> That's talking about functions, but timer.profile is similarly context-free.
>

Okay, I've come up with a (naive) patch to implement
@var("somevar@somefile", "somemodule") for stap user functions and
context-free probe handlers (see below). It works for me on Fedora 17,
both in a function or in timer.profile.

There's some minor things that I'm not very sure though:

1. It may not be a good idea to expand such @var in
dwarf_cast_expanding_visitor. Maybe I should add another ad-hoc
visitor like dwarf_var_early_expanding_visitor?

2. There's some code duplication between this early @var expansion and
the existing dwarf_var_expanding_visitor. Maybe we could merge them
two or just abstract out some common logic?

Because I'm very new to the systemtap code base, I'd highly appreciate
any suggestions or other comments!

Thanks!
-agentzh

>From 6a8bbb53e3252e1cfe47e8c17dd6e3301adcab69 Mon Sep 17 00:00:00 2001
From: "agentzh (Yichun Zhang)" <agentzh@gmail.com>
Date: Wed, 29 May 2013 20:49:06 -0700
Subject: [PATCH] Allow use of @var("somevar@somefile", "somemodule") in stap
 functions and context-free probes.

---
 parse.cxx   |   5 ++
 staptree.h  |   3 +-
 tapsets.cxx | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 173 insertions(+), 1 deletion(-)

diff --git a/parse.cxx b/parse.cxx
index bbdc2ad..dfcc1c3 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -3661,6 +3661,11 @@ target_symbol* parser::parse_target_symbol
(const token* t)
  tsym->cu_name = tsym->target_name.substr(found_at + 1);
       else
  tsym->cu_name = "";
+      if (peek_op (","))
+        {
+          swallow ();
+          expect_unknown(tok_string, tsym->module);
+        }
       expect_op(")");
       parse_target_symbol_components(tsym);
       tsym->addressof = addressof;
diff --git a/staptree.h b/staptree.h
index 8eac23d..8913151 100644
--- a/staptree.h
+++ b/staptree.h
@@ -270,6 +270,7 @@ struct target_symbol: public symbol
   bool addressof;
   std::string target_name;
   std::string cu_name;
+  std::string module;
   std::vector<component> components;
   semantic_error* saved_conversion_error; // hand-made linked list
   target_symbol(): addressof(false), saved_conversion_error (0) {}
@@ -288,7 +289,7 @@ std::ostream& operator << (std::ostream& o, const
target_symbol::component& c);
 struct cast_op: public target_symbol
 {
   expression *operand;
-  std::string type_name, module;
+  std::string type_name;
   void print (std::ostream& o) const;
   void visit (visitor* u);
 };
diff --git a/tapsets.cxx b/tapsets.cxx
index 6bede4c..a56b778 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -3953,6 +3953,7 @@ struct dwarf_cast_expanding_visitor: public
var_expanding_visitor
     s(s), db(db) {}
   void visit_cast_op (cast_op* e);
   void filter_special_modules(string& module);
+  void visit_target_symbol(target_symbol* e);
 };


@@ -4161,6 +4162,171 @@ void
dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
 }


+struct dwarf_var_query: public base_query
+{
+  target_symbol& e;
+  const bool userspace_p;
+  functioncall*& result;
+  vector<Dwarf_Die> *scopes;
+  unsigned& tick;
+
+  dwarf_var_query(dwflpp& dw, const string& module, target_symbol& e,
+                  const bool userspace_p, functioncall*& result,
+                  unsigned& tick):
+    base_query(dw, module), e(e),
+    userspace_p(userspace_p), result(result), scopes(NULL), tick(tick) {}
+
+  void handle_query_module();
+  void query_library(const char *) {}
+  void query_plt(const char *entry, size_t addr) {}
+  void getscopes(target_symbol *e);
+  ~dwarf_var_query() { if (scopes) delete scopes; }
+};
+
+
+void
+dwarf_var_query::handle_query_module()
+{
+  string fname = (string("_dwarf_tvar_get")
+                  + "_" + e.sym_name()
+                  + "_" + lex_cast(tick++));
+
+  getscopes(&e);
+
+  if (scopes->size() == 0)
+    return;
+
+  this->dw.focus_on_cu(&(scopes->at(0)));
+
+  exp_type type = pe_long;
+  string code = this->dw.literal_stmt_for_local(*scopes, 0, e.sym_name(),
+                                                &e, 0, type);
+
+  result = synthetic_embedded_deref_call(this->sess, fname, code, type,
+                                         userspace_p, 0, &e);
+}
+
+
+void
+dwarf_var_query::getscopes(target_symbol *e)
+{
+  Dwarf_Off cu_off = 0;
+  const char *cu_name = NULL;
+
+  string prefixed_srcfile = string("*/") + e->cu_name;
+
+  Dwarf_Off off = 0;
+  size_t cuhl;
+  Dwarf_Off noff;
+  Dwarf_Off module_bias;
+  Dwarf *dw = dwfl_module_getdwarf(this->dw.module, &module_bias);
+  while (dwarf_nextcu(dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+    {
+      Dwarf_Die die_mem;
+      Dwarf_Die *die;
+      die = dwarf_offdie(dw, off + cuhl, &die_mem);
+
+      /* We are not interested in partial units. */
+      if (dwarf_tag(die) == DW_TAG_compile_unit)
+ {
+  const char *die_name = dwarf_diename(die);
+  if (e->cu_name.empty()
+              || strcmp(die_name, e->cu_name.c_str()) == 0) // Perfect match.
+    {
+      cu_name = die_name;
+      cu_off = off + cuhl;
+      break;
+    }
+
+  if (fnmatch(prefixed_srcfile.c_str(), die_name, 0) == 0)
+    if (cu_name == NULL || strlen(die_name) < strlen (cu_name))
+      {
+ cu_name = die_name;
+ cu_off = off + cuhl;
+      }
+ }
+      off = noff;
+    }
+
+  if (cu_name == NULL)
+    throw semantic_error ("unable to find CU '" + e->cu_name + "'"
+  + " while searching for '" + e->target_name + "'",
+  e->tok);
+
+  //cerr << "Found CU name: " << cu_name << endl;
+
+  if (scopes)
+    delete scopes;
+
+  scopes = new vector<Dwarf_Die>;
+  Dwarf_Die cu_die;
+  dwarf_offdie(dw, cu_off, &cu_die);
+  scopes->push_back(cu_die);
+}
+
+
+void
+dwarf_cast_expanding_visitor::visit_target_symbol(target_symbol* e)
+{
+  //cerr << "accessing target_symbol " << e->sym_name() << endl;
+
+  if (is_active_lvalue(e)
+      || e->name != "@var"
+      || e->target_name.empty()
+      || e->module.empty()
+      || (!e->components.empty()
+          && e->components.back().type == target_symbol::comp_pretty_print))
+    {
+      provide(e);
+      return;
+    }
+
+  functioncall* result = NULL;
+
+  // split the module string by ':' for alternatives
+  vector<string> modules;
+  tokenize(e->module, modules, ":");
+  bool userspace_p = false;
+  for (unsigned i = 0; !result && i < modules.size(); ++i)
+    {
+      string& module = modules[i];
+      filter_special_modules(module);
+
+      dwflpp* dw;
+      try
+ {
+          userspace_p = is_user_module(module);
+  if (!userspace_p)
+    {
+      // kernel or kernel module target
+      dw = db.get_kern_dw(s, module);
+    }
+  else
+    {
+              module = find_executable(module, "", s.sysenv);
+      dw = db.get_user_dw(s, module);
+    }
+ }
+      catch (const semantic_error& er)
+ {
+  /* ignore and go to the next module */
+  continue;
+ }
+
+      dwarf_var_query q (*dw, module, *e, userspace_p, result, tick);
+      dw->iterate_over_modules(&query_module, &q);
+    }
+
+  if (!result)
+    {
+      provide(e);
+      return;
+    }
+
+  result->visit (this);
+}
+
+
 void
 dwarf_derived_probe::printsig (ostream& o) const
 {
--
1.7.11.7

Attachment: var_in_funcs_and_ctx_free_probes.patch
Description: Binary data


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