]> sourceware.org Git - systemtap.git/commitdiff
PR11815: SDT_V2 asm operand parsing reorg
authorFrank Ch. Eigler <fche@elastic.org>
Tue, 20 Jul 2010 01:18:46 +0000 (21:18 -0400)
committerFrank Ch. Eigler <fche@elastic.org>
Tue, 20 Jul 2010 01:18:46 +0000 (21:18 -0400)
* tapsets.cxx (sdt_uprobe_var_expanding_visitor ctor): Use %-adorned
  register names.  Accept other architectures.
  (visit_target_symbol): Rewrite regexp matching / parsing.  Fall back to
  DWARF in case of parse failure.
* testsuite/systemtap.base/cxxclass.exp: Use -w to suppress dwarf warning.
* util.cxx (regexp_match): New function.
* util.h: Declare it.

tapsets.cxx
testsuite/systemtap.base/cxxclass.exp
util.cxx
util.h

index e52b702883a991e0668bf472542e7a4eb402399e..99840dc2f48d3c20b57e84fe33d04b794085b332 100644 (file)
@@ -4495,6 +4495,30 @@ dwarf_derived_probe_group::emit_module_exit (systemtap_session& s)
   s.op->newline(-1) << "}";
 }
 
+
+struct sdt_kprobe_var_expanding_visitor: public var_expanding_visitor
+{
+  sdt_kprobe_var_expanding_visitor(const string & process_name,
+                                  const string & provider_name,
+                                  const string & probe_name,
+                                  const string & arg_string,
+                                  int arg_count):
+    process_name (process_name), provider_name (provider_name), probe_name (probe_name),
+    arg_count (arg_count)
+  {
+    tokenize(arg_string, arg_tokens, " ");
+    assert(arg_count >= 0 && arg_count <= 10);
+  }
+  const string & process_name;
+  const string & provider_name;
+  const string & probe_name;
+  int arg_count;
+  vector<string> arg_tokens;
+
+  void visit_target_symbol (target_symbol* e);
+};
+
+
 struct sdt_uprobe_var_expanding_visitor: public var_expanding_visitor
 {
   sdt_uprobe_var_expanding_visitor(systemtap_session& s,
@@ -4503,100 +4527,85 @@ struct sdt_uprobe_var_expanding_visitor: public var_expanding_visitor
                                   const string & provider_name,
                                   const string & probe_name,
                                   const string & arg_string,
-                                  int arg_count):
+                                  int ac):
     session (s), process_name (process_name),
-    provider_name (provider_name), probe_name (probe_name), arg_count (arg_count)
+    provider_name (provider_name), probe_name (probe_name), arg_count ((unsigned) ac)
   {
     /* Register name mapping table depends on the elf machine of this particular
        probe target process/file, not upon the host.  So we can't just
        #ifdef _i686_ etc. */
     if (elf_machine == EM_X86_64) {
-      reg_prefix = "";
-      dwarf_regs["rax"] = dwarf_regs["eax"] = dwarf_regs["ax"] = dwarf_regs["al"] = 0;
-      dwarf_regs["rdx"] = dwarf_regs["edx"] = dwarf_regs["dx"] = dwarf_regs["dl"] = 1;
-      dwarf_regs["rcx"] = dwarf_regs["ecx"] = dwarf_regs["cx"] = dwarf_regs["cl"] = 2;
-      dwarf_regs["rbx"] = dwarf_regs["ebx"] = dwarf_regs["bx"] = dwarf_regs["bl"] = 3;
-      dwarf_regs["rsi"] = dwarf_regs["esi"] = dwarf_regs["si"] = dwarf_regs["sil"] = 4;
-      dwarf_regs["rdi"] = dwarf_regs["edi"] = dwarf_regs["di"] = dwarf_regs["dil"] = 5;
-      dwarf_regs["rbp"] = dwarf_regs["ebp"] = dwarf_regs["bp"] = 6;
-      dwarf_regs["rsp"] = dwarf_regs["esp"] = dwarf_regs["sp"] = 7;
-      dwarf_regs["r8"]  = dwarf_regs["r8d"]  = dwarf_regs["r8w"]       = dwarf_regs["r8b"]  = 8;
-      dwarf_regs["r9"]  = dwarf_regs["r9d"]  = dwarf_regs["r9w"]       = dwarf_regs["r9b"]  = 9;
-      dwarf_regs["r10"] = dwarf_regs["r10d"] = dwarf_regs["r10w"] = dwarf_regs["r10b"] = 10;
-      dwarf_regs["r11"] = dwarf_regs["r11d"] = dwarf_regs["r11w"] = dwarf_regs["r11b"] = 11;
-      dwarf_regs["r12"] = dwarf_regs["r12d"] = dwarf_regs["r12w"] = dwarf_regs["r12b"] = 12;
-      dwarf_regs["r13"] = dwarf_regs["r13d"] = dwarf_regs["r13w"] = dwarf_regs["r13b"] = 13;
-      dwarf_regs["r14"] = dwarf_regs["r14d"] = dwarf_regs["r14w"] = dwarf_regs["r14b"] = 14;
-      dwarf_regs["r15"] = dwarf_regs["r15d"] = dwarf_regs["r15w"] = dwarf_regs["r15b"] = 15;
+      dwarf_regs["%rax"] = dwarf_regs["%eax"] = dwarf_regs["%ax"] = dwarf_regs["%al"] = 0;
+      dwarf_regs["%rdx"] = dwarf_regs["%edx"] = dwarf_regs["%dx"] = dwarf_regs["%dl"] = 1;
+      dwarf_regs["%rcx"] = dwarf_regs["%ecx"] = dwarf_regs["%cx"] = dwarf_regs["%cl"] = 2;
+      dwarf_regs["%rbx"] = dwarf_regs["%ebx"] = dwarf_regs["%bx"] = dwarf_regs["%bl"] = 3;
+      dwarf_regs["%rsi"] = dwarf_regs["%esi"] = dwarf_regs["%si"] = dwarf_regs["%sil"] = 4;
+      dwarf_regs["%rdi"] = dwarf_regs["%edi"] = dwarf_regs["%di"] = dwarf_regs["%dil"] = 5;
+      dwarf_regs["%rbp"] = dwarf_regs["%ebp"] = dwarf_regs["%bp"] = 6;
+      dwarf_regs["%rsp"] = dwarf_regs["%esp"] = dwarf_regs["%sp"] = 7;
+      dwarf_regs["%r8"]  = dwarf_regs["%r8d"]  = dwarf_regs["%r8w"]    = dwarf_regs["%r8b"]  = 8;
+      dwarf_regs["%r9"]  = dwarf_regs["%r9d"]  = dwarf_regs["%r9w"]    = dwarf_regs["%r9b"]  = 9;
+      dwarf_regs["%r10"] = dwarf_regs["%r10d"] = dwarf_regs["%r10w"] = dwarf_regs["%r10b"] = 10;
+      dwarf_regs["%r11"] = dwarf_regs["%r11d"] = dwarf_regs["%r11w"] = dwarf_regs["%r11b"] = 11;
+      dwarf_regs["%r12"] = dwarf_regs["%r12d"] = dwarf_regs["%r12w"] = dwarf_regs["%r12b"] = 12;
+      dwarf_regs["%r13"] = dwarf_regs["%r13d"] = dwarf_regs["%r13w"] = dwarf_regs["%r13b"] = 13;
+      dwarf_regs["%r14"] = dwarf_regs["%r14d"] = dwarf_regs["%r14w"] = dwarf_regs["%r14b"] = 14;
+      dwarf_regs["%r15"] = dwarf_regs["%r15d"] = dwarf_regs["%r15w"] = dwarf_regs["%r15b"] = 15;
     } else if (elf_machine == EM_386) {
-      reg_prefix = "";
-      dwarf_regs["eax"] = dwarf_regs["ax"] = dwarf_regs["al"] = 0;
-      dwarf_regs["ecx"] = dwarf_regs["cx"] = dwarf_regs["cl"] = 1;
-      dwarf_regs["edx"] = dwarf_regs["dx"] = dwarf_regs["dl"] = 2;
-      dwarf_regs["ebx"] = dwarf_regs["bx"] = dwarf_regs["bl"] = 3;
-      dwarf_regs["esp"] = dwarf_regs["sp"] = 4;
-      dwarf_regs["ebp"] = dwarf_regs["bp"] = 5;
-      dwarf_regs["esi"] = dwarf_regs["si"] = dwarf_regs["sil"] = 6;
-      dwarf_regs["edi"] = dwarf_regs["di"] = dwarf_regs["dil"] = 7;
+      dwarf_regs["%eax"] = dwarf_regs["%ax"] = dwarf_regs["%al"] = 0;
+      dwarf_regs["%ecx"] = dwarf_regs["%cx"] = dwarf_regs["%cl"] = 1;
+      dwarf_regs["%edx"] = dwarf_regs["%dx"] = dwarf_regs["%dl"] = 2;
+      dwarf_regs["%ebx"] = dwarf_regs["%bx"] = dwarf_regs["%bl"] = 3;
+      dwarf_regs["%esp"] = dwarf_regs["%sp"] = 4;
+      dwarf_regs["%ebp"] = dwarf_regs["%bp"] = 5;
+      dwarf_regs["%esi"] = dwarf_regs["%si"] = dwarf_regs["%sil"] = 6;
+      dwarf_regs["%edi"] = dwarf_regs["%di"] = dwarf_regs["%dil"] = 7;
     } else if (elf_machine == EM_PPC || elf_machine == EM_PPC64) {
-      reg_prefix = "r";
-      dwarf_regs["r0"] = 0; dwarf_regs["r1"] = 1; dwarf_regs["r2"] = 2;
-      dwarf_regs["r3"] = 3; dwarf_regs["r4"] = 4; dwarf_regs["r5"] = 5;
-      dwarf_regs["r6"] = 6; dwarf_regs["r7"] = 7; dwarf_regs["r8"] = 8;
-      dwarf_regs["r9"] = 9; dwarf_regs["r10"] = 10; dwarf_regs["r11"] = 11;
-      dwarf_regs["r12"] = 12; dwarf_regs["r13"] = 13; dwarf_regs["r14"] = 14;
-      dwarf_regs["r15"] = 15; dwarf_regs["r16"] = 16; dwarf_regs["r17"] = 17;
-      dwarf_regs["r18"] = 18; dwarf_regs["r19"] = 19; dwarf_regs["r20"] = 20;
-      dwarf_regs["r21"] = 21; dwarf_regs["r22"] = 22; dwarf_regs["r23"] = 23;
-      dwarf_regs["r24"] = 24; dwarf_regs["r25"] = 25; dwarf_regs["r26"] = 26;
-      dwarf_regs["r27"] = 27; dwarf_regs["r28"] = 28; dwarf_regs["r29"] = 29;
-      dwarf_regs["r30"] = 30; dwarf_regs["r31"] = 31; 
+      dwarf_regs["%r0"] = 0; dwarf_regs["%r1"] = 1; dwarf_regs["%r2"] = 2;
+      dwarf_regs["%r3"] = 3; dwarf_regs["%r4"] = 4; dwarf_regs["%r5"] = 5;
+      dwarf_regs["%r6"] = 6; dwarf_regs["%r7"] = 7; dwarf_regs["%r8"] = 8;
+      dwarf_regs["%r9"] = 9; dwarf_regs["%r10"] = 10; dwarf_regs["%r11"] = 11;
+      dwarf_regs["%r12"] = 12; dwarf_regs["%r13"] = 13; dwarf_regs["%r14"] = 14;
+      dwarf_regs["%r15"] = 15; dwarf_regs["%r16"] = 16; dwarf_regs["%r17"] = 17;
+      dwarf_regs["%r18"] = 18; dwarf_regs["%r19"] = 19; dwarf_regs["%r20"] = 20;
+      dwarf_regs["%r21"] = 21; dwarf_regs["%r22"] = 22; dwarf_regs["%r23"] = 23;
+      dwarf_regs["%r24"] = 24; dwarf_regs["%r25"] = 25; dwarf_regs["%r26"] = 26;
+      dwarf_regs["%r27"] = 27; dwarf_regs["%r28"] = 28; dwarf_regs["%r29"] = 29;
+      dwarf_regs["%r30"] = 30; dwarf_regs["%r31"] = 31; 
+      // PR11821: unadorned register "names" without -mregnames
+      dwarf_regs["0"] = 0; dwarf_regs["1"] = 1; dwarf_regs["2"] = 2;
+      dwarf_regs["3"] = 3; dwarf_regs["4"] = 4; dwarf_regs["5"] = 5;
+      dwarf_regs["6"] = 6; dwarf_regs["7"] = 7; dwarf_regs["8"] = 8;
+      dwarf_regs["9"] = 9; dwarf_regs["10"] = 10; dwarf_regs["11"] = 11;
+      dwarf_regs["12"] = 12; dwarf_regs["13"] = 13; dwarf_regs["14"] = 14;
+      dwarf_regs["15"] = 15; dwarf_regs["16"] = 16; dwarf_regs["17"] = 17;
+      dwarf_regs["18"] = 18; dwarf_regs["19"] = 19; dwarf_regs["20"] = 20;
+      dwarf_regs["21"] = 21; dwarf_regs["22"] = 22; dwarf_regs["23"] = 23;
+      dwarf_regs["24"] = 24; dwarf_regs["25"] = 25; dwarf_regs["26"] = 26;
+      dwarf_regs["27"] = 27; dwarf_regs["28"] = 28; dwarf_regs["29"] = 29;
+      dwarf_regs["30"] = 30; dwarf_regs["31"] = 31; 
     }
     else if (arg_count) {
-      throw semantic_error (string("Unsupported architecture ")
-                            + "(" + process_name + " ELF code " + lex_cast(elf_machine) + ")"
-                            + "for dwarfless sdt probes.");
+      /* permit this case; just fall back to dwarf */
     }
 
-
     need_debug_info = false;
     tokenize(arg_string, arg_tokens, " ");
     assert(arg_count >= 0 && arg_count <= 10);
   }
+
   systemtap_session& session;
   const string & process_name;
   const string & provider_name;
   const string & probe_name;
-  int arg_count;
+  unsigned arg_count;
   vector<string> arg_tokens;
   map<string,int> dwarf_regs;
-  string reg_prefix;
   bool need_debug_info;
 
   void visit_target_symbol (target_symbol* e);
 };
 
-struct sdt_kprobe_var_expanding_visitor: public var_expanding_visitor
-{
-  sdt_kprobe_var_expanding_visitor(const string & process_name,
-                                  const string & provider_name,
-                                  const string & probe_name,
-                                  const string & arg_string,
-                                  int arg_count):
-    process_name (process_name), provider_name (provider_name), probe_name (probe_name),
-    arg_count (arg_count)
-  {
-    tokenize(arg_string, arg_tokens, " ");
-    assert(arg_count >= 0 && arg_count <= 10);
-  }
-  const string & process_name;
-  const string & provider_name;
-  const string & probe_name;
-  int arg_count;
-  vector<string> arg_tokens;
-
-  void visit_target_symbol (target_symbol* e);
-};
 
 void
 sdt_uprobe_var_expanding_visitor::visit_target_symbol (target_symbol *e)
@@ -4623,153 +4632,190 @@ sdt_uprobe_var_expanding_visitor::visit_target_symbol (target_symbol *e)
          provide(myname);
          return;
        }
-      if (arg_count == 0)
-       {
-         // NB: Either
-         // 1) uprobe1_type $argN or $FOO (we don't know the arg_count)
-         // 2) uprobe2_type $FOO (no probe args)
-         // both of which get resolved later.
-         need_debug_info = true;
-         provide(e);
-         return;
-       }
 
-      int argno = -1;
+      unsigned argno = 0; // the N in $argN
       try
        {
          if (startswith(e->name, "$arg"))
-           argno = lex_cast<int>(e->name.substr(4));
+           argno = lex_cast<unsigned>(e->name.substr(4));
        }
       catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF
        {
+          argno = 0;
        }
-      if (argno < 0)
-       throw semantic_error("invalid variable, must be of the form $argN", e->tok);
-      if (argno < 1 || argno > arg_count)
-       throw semantic_error("invalid argument number", e->tok);
 
-      enum arg_type
-      {
-       literal_arg,
-       register_arg,
-       memory_arg
-      } arg_type;
-      functioncall *fc = new functioncall;
-      binary_expression *be = new binary_expression;
-      literal_number* ln = NULL;
-      string reg;
-      string disp_str;
-      int disp = 0;
-      // NB: uprobes-based sdt.h; $argFOO gets resolved later.
-
-      string tok = arg_tokens[argno-1];
-
-      regex_t   preg;
-      // this pattern matches 0xD(%R) | (%R) | %R
-      const char *pattern = "\\([0x]*-*[0-9]*\\)\\([(]*\\)\\(%*[0-9a-z][0-9a-z]*\\)\\([)]*\\)";
-      int       rc;
-      size_t    nmatch = 5;
-      regmatch_t pmatch[5];
-
-      if (0 != (rc = regcomp(&preg, pattern, 0)))
-       throw semantic_error("Failed to parse probe operand");
-      if (0 != (rc = regexec(&preg, arg_tokens[argno-1].c_str(), nmatch, pmatch, 0)))
+      if (arg_count == 0 || // a sdt.h variant without .probe-stored arg_count
+          argno < 1 || argno > arg_count) // a $argN with out-of-range N
        {
-         // Do we have a numeric literal?
-         // Check this separately instead of complicating the above pattern.
-         if (0 != (rc = regcomp(&preg, "\\$[0-9][0-9]*", 0)))
-           throw semantic_error("Failed to parse probe operand");
-         if (0 != (rc = regexec(&preg, arg_tokens[argno-1].c_str(), nmatch, pmatch, 0)))
-           throw semantic_error("Unsupported assembler operand while accessing "
-                                + probe_name + " " + e->name + " " + arg_tokens[argno-1],
-                                e->tok);
-         arg_type = literal_arg;
-         ln = new literal_number(lex_cast<int>(arg_tokens[argno-1].substr(pmatch[0].rm_so+1)));
-         ln->tok = e->tok;
+         // NB: Either
+         // 1) uprobe1_type $argN or $FOO (we don't know the arg_count)
+         // 2) uprobe2_type $FOO (no probe args)
+         // both of which get resolved later.
+         need_debug_info = true;
+         provide(e);
+         return;
        }
-      else
-       {
-         // Is there a displacement?
-         if (pmatch[2].rm_so > pmatch[1].rm_so)
-           {
-             disp_str = arg_tokens[argno-1].substr(pmatch[1].rm_so);
-             disp = lex_cast<int>(disp_str.substr(0,pmatch[1].rm_eo - pmatch[1].rm_so));
-           }
-         // Is there an indirect register?
-         if ((arg_tokens[argno-1][pmatch[2].rm_so]) == '(')
-           arg_type = memory_arg;
-         else
-           arg_type = register_arg;
-         // Is there a register?
-         if (pmatch[3].rm_eo >= pmatch[3].rm_so)
-           {
-             reg = arg_tokens[argno-1].substr(pmatch[3].rm_so);
-             reg.erase(pmatch[3].rm_eo - pmatch[3].rm_so);
-             if (reg[0] == '%')
-               reg.erase(0,1);
-             else
-               {
-                 // Handle reg XY which is recognized as disp X reg Y
-                 if (arg_type == register_arg)
-                   {
-                     reg.insert (0, disp_str.substr(0,pmatch[1].rm_eo - pmatch[1].rm_so));
-                     disp = 0;
-                   }
-                 reg.insert (0, reg_prefix);
-               }
-           }
-         if (reg.length() == 0)
-           throw semantic_error("Unsupported assembler operand while accessing "
-                                + probe_name + " " + e->name, e->tok);
-         // synthesize user_long(%{fetch_register(R)%} + D)
-         fc->function = "user_long";
-         fc->tok = e->tok;
-         be->tok = e->tok;
-
-         embedded_expr *get_arg1 = new embedded_expr;
-         get_arg1->tok = e->tok;
-         get_arg1->code = string("/* unprivileged */ /* pure */")
-           + (is_user_module (process_name)
-              ? string("u_fetch_register(")
-              : string("k_fetch_register("))
-           + lex_cast(dwarf_regs[reg]) + string(")");
-         // XXX: may we ever need to cast that to a narrower type?
 
-         be->left = get_arg1;
-         be->op = "+";
-         literal_number* inc = new literal_number(disp);
-         inc->tok = e->tok;
-         be->right = inc;
-         fc->args.push_back(be);
-       }
+      assert (arg_tokens.size() >= argno);
+      string asmarg = arg_tokens[argno-1];   // $arg1 => arg_tokens[0]
+      
+      // Now we try to parse this thing, which is an assembler operand
+      // expression.  If we can't, we warn, back down to need_debug_info
+      // and hope for the best.
+      expression* argexpr = 0; // filled in in case of successful parse
+
+      string percent_regnames;
+      string regnames;
+      vector<string> matches;
+      int rc;
+
+      // test for a numeric literal.
+      // Only accept (signed) decimals throughout. XXX
+
+      // PR11821.  NB: on powerpc, literals are not prefixed with $,
+      // so this regex does not match.  But that's OK, since without
+      // -mregnames, we can't tell them apart from register numbers
+      // anyway.  With -mregnames, we could, if gcc somehow
+      // communicated to us the presence of that option, but alas it
+      // doesn't.  http://gcc.gnu.org/PR44995.
+      rc = regexp_match (asmarg, "^\\$[-]?[0-9][0-9]*$", matches);
+      if (! rc)
+        {
+         literal_number* ln = new literal_number(lex_cast<int>(matches[0].substr(1))); // assume decimal
+         ln->tok = e->tok;
+          argexpr = ln;
+          goto matched;
+        }
 
-      if (e->components.empty()) // We have a scalar
-       {
-         if (e->addressof)
-           throw semantic_error("cannot take address of sdt variable", e->tok);
+      // Build regex pieces out of the known dwarf_regs.  We keep two separate
+      // lists: ones with the % prefix (and thus unambigiuous even despite PR11821),
+      // and ones with no prefix (and thus only usable in unambiguous contexts).
+      for (map<string,int>::iterator ri = dwarf_regs.begin(); ri != dwarf_regs.end(); ri++)
+        {
+          string regname = ri->first;
+          assert (regname != "");
+          regnames += string("|")+regname;
+          if (regname[0]=='%')
+            percent_regnames += string("|")+regname;
+        }
+      // clip off leading |
+      regnames = regnames.substr(1);
+      percent_regnames = percent_regnames.substr(1);
+
+      // test for REGISTER
+      // NB: Because PR11821, we must use percent_regnames here.
+      rc = regexp_match (asmarg, string("^(")+percent_regnames+string(")$"), matches);
+      if (! rc)
+        {
+          string regname = matches[1];
+          if (dwarf_regs.find (regname) != dwarf_regs.end()) // known register
+            {
+              embedded_expr *get_arg1 = new embedded_expr;
+              get_arg1->tok = e->tok;
+              get_arg1->code = string("/* unprivileged */ /* pure */")
+                + (is_user_module (process_name)
+                   ? string("u_fetch_register(")
+                   : string("k_fetch_register("))
+                + lex_cast(dwarf_regs[regname]) + string(")");
+              // XXX: may we ever need to cast that to a narrower type?
+              argexpr = get_arg1;
+              goto matched;
+            }
+          // invalid register name, fall through
+        }
+      
+      // test for OFFSET(REGISTER)
+      // NB: Despire PR11821, we can use regnames here, since the parentheses 
+      // make things unambiguous.
+      rc = regexp_match (asmarg, string("^([-]?[0-9]*)[(](")+regnames+string(")[)]$"), matches);
+      if (! rc)
+        {
+          string dispstr = matches[1];
+          int64_t disp = 0;
+              if (dispstr == "")
+                disp = 0;
+              else
+                try
+                  {
+                    disp = lex_cast<int64_t>(dispstr); // should decode positive/negative hex/decimal
+                  }
+                catch (const runtime_error& f) // unparseable offset
+                  {
+                    goto not_matched; // can't just 'break' out of
+                                      // this case or use a sentinel
+                                      // value, unfortunately
+                  }
 
-         if (arg_type == memory_arg)
-           provide(fc);
-         else if (arg_type == register_arg)
-           provide(be);
-         else if (arg_type == literal_arg)
-           provide(ln);
-         return;
-       }
-      cast_op *cast = new cast_op;
-      cast->name = "@cast";
-      cast->tok = e->tok;
-      if (arg_type == memory_arg)
-       cast->operand = fc;
-      else if (arg_type == register_arg)
-       cast->operand = be;
-      else if (arg_type == literal_arg)
-       provide(ln);
-      cast->components = e->components;
-      cast->type_name = probe_name + "_arg" + lex_cast(argno);
-      cast->module = process_name;
+              string regname = matches[2];
+              if (dwarf_regs.find (regname) != dwarf_regs.end()) // known register
+                {
+                  // synthesize user_long(%{fetch_register(R)%} + D)
+                  
+                  embedded_expr *get_arg1 = new embedded_expr;
+                  get_arg1->tok = e->tok;
+                  get_arg1->code = string("/* unprivileged */ /* pure */")
+                    + (is_user_module (process_name)
+                       ? string("u_fetch_register(")
+                       : string("k_fetch_register("))
+                    + lex_cast(dwarf_regs[regname]) + string(")");
+                  // XXX: may we ever need to cast that to a narrower type?
+                  
+                  literal_number* inc = new literal_number(disp);
+                  inc->tok = e->tok;
+                  
+                  binary_expression *be = new binary_expression;
+                  be->tok = e->tok;
+                  be->left = get_arg1;
+                  be->op = "+";
+                  be->right = inc;
+                  
+                  functioncall *fc = new functioncall;
+                  fc->function = "user_long";
+                  fc->tok = e->tok;
+                  fc->args.push_back(be);
+                  
+                  argexpr = fc;
+                  goto matched;
+                }
+              // invalid register name, fall through
+        }
 
-      cast->visit(this);
+    not_matched:
+      // The asmarg operand was not recognized.  Back down to dwarf.
+      if (! session.suppress_warnings)
+        session.print_warning ("Downgrading SDT_V2 probe argument to dwarf, can't parse '"+asmarg+"'", e->tok);
+      assert (argexpr == 0);
+      need_debug_info = true;
+      provide (e);
+      return;
+      
+    matched:
+      assert (argexpr != 0);
+      
+      if (session.verbose > 2) 
+        clog << "mapped asm operand " << asmarg << " to " << *argexpr << endl;
+      
+      if (e->components.empty()) // We have a scalar
+        {
+          if (e->addressof)
+            throw semantic_error("cannot take address of sdt variable", e->tok);
+          provide (argexpr);
+          return;
+        }
+      else  // $var->foo
+        {
+          cast_op *cast = new cast_op;
+          cast->name = "@cast";
+          cast->tok = e->tok;
+          cast->operand = argexpr;
+          cast->components = e->components;
+          cast->type_name = probe_name + "_arg" + lex_cast(argno);
+          cast->module = process_name;
+          cast->visit(this);
+          return;
+        }
+      
+      /* NOTREACHED */
     }
   catch (const semantic_error &er)
     {
index c6c6c53be6f9b712bbc797ffdc4dda9331ff6bc8..ddc8d618a60c6d32834e91c87c3827602c0166a1 100644 (file)
@@ -26,7 +26,7 @@ if { $res != "" } {
 }
 
 if {[installtest_p] && [uprobes_p]} {
-  stap_run3 "$test" $srcdir/$subdir/$test.stp $test.exe -c ./$test.exe
+  stap_run3 "$test" -w $srcdir/$subdir/$test.stp $test.exe -c ./$test.exe
 } else {
   untested "$test"
 }
index 9370a8c42995e3fe80ba514759c64defaef35bf0..74e1ce13cc5ab888acde3fac85396258a7e021bc 100644 (file)
--- a/util.cxx
+++ b/util.cxx
@@ -443,6 +443,7 @@ kill_stap_spawn(int sig)
 }
 
 
+
 void assert_regexp_match (const string& name, const string& value, const string& re)
 {
   typedef map<string,regex_t*> cache;
@@ -473,4 +474,45 @@ void assert_regexp_match (const string& name, const string& value, const string&
 }
 
 
+int regexp_match (const string& value, const string& re, vector<string>& matches)
+{
+  typedef map<string,regex_t*> cache;  // separate cache because we use different regcomp options
+  static cache compiled;
+  cache::iterator it = compiled.find (re);
+  regex_t* r = 0;
+  if (it == compiled.end())
+    {
+      r = new regex_t;
+      int rc = regcomp (r, re.c_str(), REG_EXTENDED); /* REG_ICASE? */
+      if (rc) {
+        cerr << "regcomp " << re << " error rc=" << rc << endl;
+        exit(1);
+      }
+      compiled[re] = r;
+    }
+  else
+    r = it->second;
+
+
+  // run regexec
+#define maxmatches 10
+  regmatch_t rm[maxmatches];
+
+  int rc = regexec (r, value.c_str(), maxmatches, rm, 0);
+  if (rc) return rc;
+
+  matches.erase(matches.begin(), matches.end());
+  for (unsigned i=0; i<maxmatches; i++) // XXX: ideally, the number of actual subexpressions in re
+    {
+      if (rm[i].rm_so >= 0)
+        matches.push_back(value.substr (rm[i].rm_so, rm[i].rm_eo-rm[i].rm_so));
+      else
+        matches.push_back("");
+    }
+
+  return 0;
+}
+
+
+
 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/util.h b/util.h
index fecbfab6f6f86ecb66040c192ff495a6fa3f753d..5e7483879016cf7c9795ab76a646f381a0bb40c6 100644 (file)
--- a/util.h
+++ b/util.h
@@ -24,6 +24,7 @@ std::string git_revision(const std::string& path);
 int stap_system(int verbose, const std::string& command);
 int kill_stap_spawn(int sig);
 void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re);
+int regexp_match (const std::string& value, const std::string& re, std::vector<std::string>& matches);
 
 // stringification generics
 
This page took 0.052399 seconds and 5 git commands to generate.