public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* debuginfoless static user probes
@ 2010-04-12  3:41 Stan Cox
  2010-04-12 16:11 ` Frank Ch. Eigler
  0 siblings, 1 reply; 10+ messages in thread
From: Stan Cox @ 2010-04-12  3:41 UTC (permalink / raw)
  To: SystemTap List

[-- Attachment #1: Type: text/plain, Size: 427 bytes --]

This patch implements adding info to the .probes section to access probe 
arguments and since the probe address is also in the .probes section this 
means no debuginfo is required for a process("proc").mark("mark") probe.  So 
here is a patch to implement that and also to implement not needing debuginfo 
for .mark probes.  The diffs are large but some of this is mechanical.  I put 
'#####' comments in the patch.  Comments?

[-- Attachment #2: stap.diff --]
[-- Type: text/plain, Size: 25097 bytes --]

The .probes section format is now:
%rcx %rsi %rdi 
seven__test
UPB1
pointer to seven__test
count of probe arguments
probe address
pointer to argument asm string

diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h
index 7490678..e2700b1 100644
--- a/includes/sys/sdt.h
+++ b/includes/sys/sdt.h
@@ -25,23 +25,6 @@
    on having a writable .probes section to put the enabled variables in. */
 #define ALLOCSEC "\"aw\""
 
-/* An allocated section .probes that holds the probe names and addrs. */
-#define STAP_PROBE_DATA_(probe,guard,arg)		\
-  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
-		    "\t.balign 8\n"			\
-		    "1:\n\t.asciz " #probe "\n"         \
-		    "\t.balign 4\n"                     \
-		    "\t.int " #guard "\n"		\
-		    "\t.balign 8\n"			\
-		    STAP_PROBE_ADDR("1b\n")             \
-		    "\t.balign 8\n"                     \
-		    STAP_PROBE_ADDR(#arg "\n")		\
-		    "\t.int 0\n"			\
-		    "\t.previous\n")
-
-#define STAP_PROBE_DATA(probe, guard, arg)	\
-  STAP_PROBE_DATA_(#probe,guard,arg)
-
 #if defined STAP_HAS_SEMAPHORES
 #define STAP_SEMAPHORE(probe)	\
   if (__builtin_expect ( probe ## _semaphore , 0))
@@ -51,6 +34,25 @@
 
 #if ! defined EXPERIMENTAL_KPROBE_SDT
 
+/* An allocated section .probes that holds the probe names and addrs. */
+#define STAP_PROBE_DATA_(probe,guard,argc)	\
+  __asm__ volatile ("\t.balign 8\n"			\
+		    "1:\n\t.asciz " #probe "\n"		\
+  		    "\t.balign 8\n"			\
+		    "\t.int " #guard "\n"		\
+		    "\t.balign 8\n"			\
+  		    STAP_PROBE_ADDR ("1b\n")		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR (#argc "\n")	\
+                    "\t.balign 8\n"                     \
+                    STAP_PROBE_ADDR("2f\n")          	\
+                    "\t.balign 8\n"                     \
+                    STAP_PROBE_ADDR("3b\n")		\
+		    "\t.int 0\n"			\
+		    "\t.previous\n")
+#define STAP_PROBE_DATA(probe, guard, argc)	\
+  STAP_PROBE_DATA_(#probe,guard,argc)
+
 /* These baroque macros are used to create a unique label. */
 #define STAP_CONCAT(a,b) a ## b
 #define STAP_LABEL_PREFIX(p) _stapprobe1_ ## p
@@ -78,7 +80,7 @@
 #define STAP_NOP "\tnop 0 "
 #endif
 
-#define STAP_UPROBE_GUARD 0x31425250
+#define STAP_UPROBE_GUARD 0x31425055
 
 #ifndef STAP_SDT_VOLATILE /* allow users to override */
 #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 5 \
@@ -90,18 +92,22 @@
 #define STAP_SDT_VOLATILE volatile
 #endif
 #endif
+
 #define STAP_PROBE_(probe)			\
 do {						\
-  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,2f);	\
-  __asm__ volatile ("2:\n"			\
-		    STAP_NOP);			\
+  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
+		    "\t.balign 8\n");			\
+  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,0);	\
+  __asm__ volatile ("2:\n" STAP_NOP);			\
 } while (0)
 
 #define STAP_PROBE1_(probe,label,parm1)			\
 do STAP_SEMAPHORE(probe) {				\
-  STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;	\
+  STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;		\
   STAP_UNINLINE;					\
-  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,2f);		\
-  __asm__ volatile ("2:\n"				\
-		    STAP_NOP "/* %0 */" :: "g"(arg1));	\
+  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
+		    "\t.balign 8\n"			\
+		    "3:\n\t.asciz \"%0\"" :: "g" (arg1));	\
+  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,1);	\
+  __asm__ volatile ("2:\n" STAP_NOP);	\
  } while (0)

...
 
 #else /* ! defined EXPERIMENTAL_KPROBE_SDT */
@@ -240,11 +264,32 @@ extern long int syscall (long int __sysno, ...) __THROW;
 # endif
 # if defined EXPERIMENTAL_KPROBE_SDT
 # define STAP_SYSCALL __NR_getegid
-# define STAP_GUARD 0x32425250
+# define STAP_GUARD 0x3142504b
 # endif
 
 #include <sys/syscall.h>
 
+/* An allocated section .probes that holds the probe names and addrs. */
+#define STAP_PROBE_DATA_(probe,guard,argc)	\
+  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
+		    "\t.balign 8\n"			\
+		    "1:\n\t.asciz " #probe "\n"		\
+		    "\t.balign 8\n"			\
+		    "\t.int " #guard "\n"		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR ("1b\n")		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR (#argc "\n")	\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR ("0\n")		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR ("0\n")		\
+		    "\t.int 0\n"			\
+		    "\t.previous\n")
+
+#define STAP_PROBE_DATA(probe, guard, argc)	\
+  STAP_PROBE_DATA_(#probe,guard,argc)
+
 #define STAP_PROBE_(probe)			\
 do STAP_SEMAPHORE(probe) {			\
   STAP_PROBE_DATA(probe,STAP_GUARD,0);		\

##### Add byte register variants

diff --git a/tapset/i386/registers.stp b/tapset/i386/registers.stp
index c1e98ac..1a118bc 100644
--- a/tapset/i386/registers.stp
+++ b/tapset/i386/registers.stp
@@ -12,12 +12,16 @@ function _stp_register_regs() {
 
 	/* Same order as pt_regs */
 	_reg_offsets["ebx"] =  0		_reg_offsets["bx"] =  0
+			      			_reg_offsets["bl"] =  0
 	_reg_offsets["ecx"] =  4		_reg_offsets["cx"] =  4
+			      			_reg_offsets["cl"] =  4
 	_reg_offsets["edx"] =  8		_reg_offsets["dx"] =  8
+			      			_reg_offsets["dl"] =  8
 	_reg_offsets["esi"] = 12		_reg_offsets["si"] = 12
 	_reg_offsets["edi"] = 16		_reg_offsets["di"] = 16
 	_reg_offsets["ebp"] = 20		_reg_offsets["bp"] = 20
 	_reg_offsets["eax"] = 24		_reg_offsets["ax"] = 24
+			      			_reg_offsets["al"] = 24
 	_reg_offsets["xds"] = 28		_reg_offsets["ds"] = 28
 	_reg_offsets["xes"] = 32		_reg_offsets["es"] = 32
 	_reg_offsets["xfs"] = 36		_reg_offsets["fs"] = 36

##### Add byte register variants

diff --git a/tapset/x86_64/registers.stp b/tapset/x86_64/registers.stp
index e7abb18..ae5a639 100644
--- a/tapset/x86_64/registers.stp
+++ b/tapset/x86_64/registers.stp
@@ -2,21 +2,35 @@ global _reg_offsets, _r32_offsets, _stp_regs_registered
 
 function _stp_register_regs() {
 	/* Same order as pt_regs */
-	_reg_offsets["r15"] = 0
-	_reg_offsets["r14"] = 8
-	_reg_offsets["r13"] = 16
-	_reg_offsets["r12"] = 24
+	_reg_offsets["r15"] = 0		_reg_offsets["r15d"] = 0
+	_reg_offsets["r15w"] = 0	_reg_offsets["r15b"] = 0
+	_reg_offsets["r14"] = 8		_reg_offsets["r14d"] = 8
+	_reg_offsets["r14w"] = 8	_reg_offsets["r14b"] = 8
+	_reg_offsets["r13"] = 16	_reg_offsets["r13d"] = 16
+	_reg_offsets["r13w"] = 16	_reg_offsets["r13b"] = 16
+	_reg_offsets["r12"] = 24	_reg_offsets["r12d"] = 24
+	_reg_offsets["r12w"] = 24	_reg_offsets["r12b"] = 24
 	_reg_offsets["rbp"] = 32	_reg_offsets["bp"] = 32
 	_reg_offsets["rbx"] = 40	_reg_offsets["bx"] = 40
-	_reg_offsets["r11"] = 48
-	_reg_offsets["r10"] = 56
-	_reg_offsets["r9"]  = 64
-	_reg_offsets["r8"]  = 72
+			      		_reg_offsets["bl"] = 40
+	_reg_offsets["r11"] = 48	_reg_offsets["r11d"] = 48
+	_reg_offsets["r11w"] = 48	_reg_offsets["r11b"] = 48
+	_reg_offsets["r10"] = 56	_reg_offsets["r10d"] = 56
+	_reg_offsets["r10w"] = 56	_reg_offsets["r10b"] = 56
+	_reg_offsets["r9"]  = 64	_reg_offsets["r9d"]  = 64
+	_reg_offsets["r9w"]  = 64	_reg_offsets["r9b"]  = 64
+	_reg_offsets["r8"]  = 72	_reg_offsets["r8d"]  = 72
+	_reg_offsets["r8w"]  = 72	_reg_offsets["r8b"]  = 72
 	_reg_offsets["rax"] = 80	_reg_offsets["ax"] = 80
+			      		_reg_offsets["al"] = 80
 	_reg_offsets["rcx"] = 88	_reg_offsets["cx"] = 88
+			      		_reg_offsets["cl"] = 88
 	_reg_offsets["rdx"] = 96	_reg_offsets["dx"] = 96
+			      		_reg_offsets["dl"] = 96
 	_reg_offsets["rsi"] = 104	_reg_offsets["si"] = 104
+			      		_reg_offsets["sil"] = 104
 	_reg_offsets["rdi"] = 112	_reg_offsets["di"] = 112
+			      		_reg_offsets["dil"] = 112
 	_reg_offsets["orig_rax"] = 120	_reg_offsets["orig_ax"] = 120
 	_reg_offsets["rip"] = 128	_reg_offsets["ip"] = 128
 	_reg_offsets["xcs"] = 136	_reg_offsets["cs"] = 136

diff --git a/tapsets.cxx b/tapsets.cxx
index 7b04f79..fb78f34 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx

##### rename have_reg_args to have_kprobe

@@ -3914,17 +3914,21 @@ dwarf_derived_probe_group::emit_module_exit (systemtap_session& s)
 struct sdt_var_expanding_visitor: public var_expanding_visitor
 {
   sdt_var_expanding_visitor(string & process_name, string & probe_name,
-			    int arg_count, bool have_reg_args):
+			    string & arg_string,
+			    int arg_count, bool have_kprobe):
     process_name (process_name), probe_name (probe_name),
-    have_reg_args (have_reg_args),
+    have_kprobe (have_kprobe),
     arg_count (arg_count)
   {
-    assert(!have_reg_args || (arg_count >= 0 && arg_count <= 10));
+    tokenize(arg_string, arg_tokens, " ");
+
+    assert(!have_kprobe || (arg_count >= 0 && arg_count <= 10));
   }
   string & process_name;
   string & probe_name;
-  bool have_reg_args;
+  bool have_kprobe;
   int arg_count;
+  vector<string> arg_tokens;
 
   void visit_target_symbol (target_symbol* e);
   void visit_defined_op (defined_op* e);

##### we now handle uprobe $arg case

@@ -3946,14 +3950,6 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
           return;
         }
 
-      if (!startswith(e->base_name, "$arg") || ! have_reg_args)
-        {
-          // NB: uprobes-based sdt.h; $argFOO gets resolved later.
-          // XXX: We don't even know the arg_count in this case.
-          provide(e);
-          return;
-        }
-
       int argno = 0;
       try
         {

##### parse the asm arg string then create stap ops to access either RX or D(RX)

@@ -3965,56 +3961,123 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
         }
       if (argno < 1 || argno > arg_count)
         throw semantic_error("invalid argument number", e->tok);
-
       bool lvalue = is_active_lvalue(e);
+      bool arg_in_memory = false;
       functioncall *fc = new functioncall;
+      binary_expression *be = new binary_expression;
 
-      // First two args are hidden: 1. pointer to probe name 2. task id
-      if (arg_count < 2)
+      if (!startswith(e->base_name, "$arg") || ! have_kprobe)
         {
-          fc->function = "ulong_arg";
-          fc->type = pe_long;
-          fc->tok = e->tok;
-          literal_number* num = new literal_number(argno + 2);
-          num->tok = e->tok;
-          fc->args.push_back(num);
-        }
-      else				// args passed as a struct
-        {
-          fc->function = "user_long";
-          fc->tok = e->tok;
-          binary_expression *be = new binary_expression;
-          be->tok = e->tok;
-          functioncall *get_arg1 = new functioncall;
-          get_arg1->function = "pointer_arg";
-          get_arg1->tok = e->tok;
-          literal_number* num = new literal_number(3);
-          num->tok = e->tok;
-          get_arg1->args.push_back(num);
-
-          be->left = get_arg1;
-          be->op = "+";
-          literal_number* inc = new literal_number((argno - 1) * 8);
-          inc->tok = e->tok;
-          be->right = inc;
-          fc->args.push_back(be);
-        }
+	  string reg;
+	  string disp_str;
+	  int disp = 0;
+          // NB: uprobes-based sdt.h; $argFOO gets resolved later.
 
-      if (lvalue)
-        *(target_symbol_setter_functioncalls.top()) = fc;
+	  string tok = arg_tokens[argno-1];
+	  bool bad_asm_op = false;
+
+	  for (unsigned i = 0; i < tok.length(); i++)
+	    // Recognize: %R | (%R) | N(%R)
+	    switch (tok[i])
+	      {
+	      case '-':
+	      case '1' ... '9':
+		{
+		  disp_str = tok.substr(i,tok.find('(',i)-i);
+		  i += disp_str.length();
+		  disp = lex_cast<int>(disp_str);
+		  arg_in_memory = true;
+		  break;
+		}
+	      case '(':
+		arg_in_memory = true;
+		break;
+	      case ')':
+		break;
+	      case '%':
+		{
+		  reg = tok.substr(i+1,tok.find(')',i)-i-1);
+		  i += reg.length();
+		  break;
+		}
+	      default:
+		bad_asm_op = true;
+	      }
+          if (reg.length() == 0 || bad_asm_op)
+            throw semantic_error("Unsupported assembler operand while accessing " + probe_name + " " + e->base_name, e->tok);
+
+	  fc->function = "user_long";
+	  fc->tok = e->tok;
+	  be->tok = e->tok;
+	  functioncall *get_arg1 = new functioncall;
+	  get_arg1->function = "register";
+	  get_arg1->tok = e->tok;
+	  literal_string* reg_arg = new literal_string(reg);
+	  reg_arg->tok = e->tok;
+	  get_arg1->args.push_back(reg_arg);
+
+	  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);
+        }
 
-      if (e->components.empty())
+      else if (have_kprobe)
+	{
+	  // First two args are hidden: 1. pointer to probe name 2. task id
+	  if (arg_count < 2)
+	    {
+	      fc->function = "ulong_arg";
+	      fc->type = pe_long;
+	      fc->tok = e->tok;
+	      literal_number* num = new literal_number(argno + 2);
+	      num->tok = e->tok;
+	      fc->args.push_back(num);
+	    }
+	  else				// args passed as a struct
+	    {
+	      fc->function = "user_long";
+	      fc->tok = e->tok;
+	      binary_expression *be = new binary_expression;
+	      be->tok = e->tok;
+	      functioncall *get_arg1 = new functioncall;
+	      get_arg1->function = "pointer_arg";
+	      get_arg1->tok = e->tok;
+	      literal_number* num = new literal_number(3);
+	      num->tok = e->tok;
+	      get_arg1->args.push_back(num);
+
+	      be->left = get_arg1;
+	      be->op = "+";
+	      literal_number* inc = new literal_number((argno - 1) * 8);
+	      inc->tok = e->tok;
+	      be->right = inc;
+	      fc->args.push_back(be);
+	    }
+	  if (lvalue)
+	    *(target_symbol_setter_functioncalls.top()) = fc;
+	}
+      
+      if (e->components.empty()) // We have a scalar
         {
           if (e->addressof)
             throw semantic_error("cannot take address of sdt variable", e->tok);
 
-          provide(fc);
+	  if (have_kprobe || arg_in_memory)
+	    provide(fc);
+	  else
+	    provide(be);
           return;
         }
       cast_op *cast = new cast_op;
       cast->base_name = "@cast";
       cast->tok = e->tok;
-      cast->operand = fc;
+      if (have_kprobe || arg_in_memory)
+	cast->operand = fc;
+      else
+	cast->operand = be;
       cast->components = e->components;
       cast->type = probe_name + "_arg" + lex_cast(argno);
       cast->module = process_name;
@@ -4034,7 +4097,7 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
 void
 sdt_var_expanding_visitor::visit_defined_op (defined_op *e)
 {
-  if (! have_reg_args) // for uprobes, pass @defined through to dwarf synthetic probe's own var-expansion
+  if (! have_kprobe) // for uprobes, pass @defined through to dwarf synthetic probe's own var-expansion
     provide (e);
   else
     var_expanding_visitor::visit_defined_op (e);

##### most of this is just supporting both old and new probes sections

@@ -4052,8 +4115,10 @@ struct sdt_query : public base_query
 private:
   enum probe_types
     {
-      uprobe_type = 0x31425250, // "PRB1"
-      kprobe_type = 0x32425250, // "PRB2"
+      uprobe1_type = 0x31425250, // "PRB1"
+      uprobe2_type = 0x31425055, // "UPB1"
+      kprobe1_type = 0x32425250, // "PRB2"
+      kprobe2_type = 0x3142504b  // "KPB1"
     } probe_type;
 
   probe * base_probe;
@@ -4067,7 +4132,9 @@ private:
   Elf_Data *pdata;
   size_t probe_scn_offset;
   size_t probe_scn_addr;
-  uint64_t probe_arg;
+  uint64_t arg_count;
+  uint64_t pc;
+  string arg_string;
   string probe_name;
 
   bool init_probe_scn();
@@ -4076,6 +4143,8 @@ private:
   void convert_probe(probe *base);
   void record_semaphore(vector<derived_probe *> & results, unsigned start);
   probe* convert_location();
+  bool have_uprobe() {return probe_type == uprobe1_type || probe_type == uprobe2_type;}
+  bool have_kprobe() {return probe_type == kprobe1_type || probe_type == kprobe2_type;}
 };
 
 
@@ -4100,7 +4169,7 @@ sdt_query::handle_query_module()
 
   while (get_next_probe())
     {
-      if (probe_type != uprobe_type
+      if (! have_uprobe()
 	  && !probes_handled.insert(probe_name).second)
         continue;
 
@@ -4109,10 +4178,12 @@ sdt_query::handle_query_module()
 	  clog << "matched probe_name " << probe_name << " probe_type ";
 	  switch (probe_type)
 	    {
-	    case uprobe_type:
-	      clog << "uprobe at 0x" << hex << probe_arg << dec << endl;
+	    case uprobe1_type:
+	    case uprobe2_type:
+	      clog << "uprobe at 0x" << hex << pc << dec << endl;
 	      break;
-	    case kprobe_type:
+	    case kprobe1_type:
+	    case kprobe2_type:
 	      clog << "kprobe" << endl;
 	      break;
 	    }
@@ -4122,22 +4193,23 @@ sdt_query::handle_query_module()
       probe *new_base = convert_location();
       probe_point *new_location = new_base->locations[0];
 
-      bool have_reg_args = false;
-      if (probe_type == kprobe_type)
+      bool kprobe_found = false;
+      if (have_kprobe())
         {
           convert_probe(new_base);
-          have_reg_args = true;
+          kprobe_found = true;
         }
 
       // Expand the local variables in the probe body
       sdt_var_expanding_visitor svv (module_val, probe_name,
-                                     probe_arg, // XXX: whoa, isn't this 'arg_count'?
-                                     have_reg_args);
+				     arg_string,
+                                     arg_count,
+                                     kprobe_found);
       svv.replace (new_base->body);
 
       unsigned i = results.size();
 
-      if (probe_type == kprobe_type)
+      if (have_kprobe())
         derive_probes(sess, new_base, results);
 
       else

##### just wire in a uprobe_derived_probe "by hand" to avoid needeing debuginfo
##### TODO the old iterate_over_modules method is still needed for version I

@@ -4149,9 +4221,30 @@ sdt_query::handle_query_module()
               params[c->functor] = c->arg;
             }
 
-          dwarf_query q(new_base, new_location, dw, params, results, "", "");
-          q.has_mark = true; // enables mid-statement probing
-          dw.iterate_over_modules(&query_module, &q);
+	  dwarf_query q(new_base, new_location, dw, params, results, "", "");
+	  q.has_mark = true; // enables mid-statement probing
+#if 0
+	  dw.iterate_over_modules(&query_module, &q);
+#else
+
+	  Dwarf_Addr bias;
+	  Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (q.dw.mod_info->mod, &bias))
+		      ?: dwfl_module_getelf (q.dw.mod_info->mod, &bias));
+
+	  GElf_Ehdr ehdr_mem;
+	  GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
+	  string section;
+	  if ((em->e_type == ET_EXEC))
+	    section = ".absolute";
+	  else if (em->e_type == ET_DYN)
+	    section = ".dynamic";
+	  uprobe_derived_probe* p =
+	    new uprobe_derived_probe ("", "", 0, q.module_val, section /*".absolute"*/,
+				     q.statement_num_val, q.statement_num_val,
+				     q, 0);
+	  results.push_back (p);
+	  sess.unwindsym_modules.insert ("kernel");
+#endif
         }
 
       record_semaphore(results, i);
@@ -4204,7 +4297,7 @@ sdt_query::init_probe_scn()
 	  if (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name),
 		      ".probes") == 0)
 	    have_probes = true;
-	    break;
+	  break;
 	}
     }
 
##### get next probe from either v1 or v2

@@ -4234,17 +4327,12 @@ sdt_query::get_next_probe()
 
   while (probe_scn_offset < pdata->d_size)
     {
-      struct probe_entry
-      {
-	__uint64_t name;
-	__uint64_t arg;
-      }  *pbe;
       __uint32_t *type = (__uint32_t*) ((char*)pdata->d_buf + probe_scn_offset);
       probe_type = (enum probe_types)*type;
-      if (probe_type != uprobe_type && probe_type != kprobe_type)
+      if (! have_uprobe() && ! have_kprobe())
 	{
 	  // Unless this is a mangled .probes section, this happens
-	  // because the name of the probe comes first, followed by
+	  // because the name of the probe comes first, followed by	
 	  // the sentinel.
 	  if (sess.verbose > 5)
 	    clog << "got unknown probe_type: 0x" << hex << probe_type
@@ -4252,18 +4340,51 @@ sdt_query::get_next_probe()
 	  probe_scn_offset += sizeof(__uint32_t);
 	  continue;
 	}
-      probe_scn_offset += sizeof(__uint32_t);
-      probe_scn_offset += probe_scn_offset % sizeof(__uint64_t);
-      pbe = (struct probe_entry*) ((char*)pdata->d_buf + probe_scn_offset);
-      if (pbe->name == 0)
-	return false;
-      probe_name = (char*)((char*)pdata->d_buf + pbe->name - (char*)probe_scn_addr);
-      probe_arg = pbe->arg;
+      if (probe_type == uprobe1_type || probe_type == kprobe1_type)
+	{
+	  struct probe_entry
+	  {
+	    __uint64_t name;
+	    __uint64_t arg;
+	  }  *pbe;
+
+	  probe_scn_offset += sizeof(__uint32_t);
+	  probe_scn_offset += probe_scn_offset % sizeof(__uint64_t);
+	  pbe = (struct probe_entry*) ((char*)pdata->d_buf + probe_scn_offset);
+	  if (pbe->name == 0)
+	    return false;
+	  probe_name = (char*)((char*)pdata->d_buf + pbe->name - (char*)probe_scn_addr);
+	  if (probe_type == uprobe1_type)
+	    {
+	      pc = pbe->arg;
+	      arg_count = 0;
+	    }
+	  else if (probe_type == kprobe1_type)
+	    arg_count = pbe->arg;
+	  probe_scn_offset += sizeof (struct probe_entry);
+	}
+      else if (probe_type == uprobe2_type || probe_type == kprobe2_type)
+	{
+	  struct probe_entry
+	  {
+	    __uint64_t type;
+	    __uint64_t name;
+	    __uint64_t arg_count;
+	    __uint64_t pc;
+	    __uint64_t arg_string;
+	  }  *pbe;
+	  pbe = (struct probe_entry*) ((char*)pdata->d_buf + probe_scn_offset);
+	  probe_name = (char*)((char*)pdata->d_buf + pbe->name - (char*)probe_scn_addr);
+	  arg_count = pbe->arg_count;
+	  pc = pbe->pc;
+	  if (pbe->arg_string)
+	    arg_string = (char*)((char*)pdata->d_buf + pbe->arg_string - (char*)probe_scn_addr);
+	  probe_scn_offset += sizeof (struct probe_entry);
+	}
       if (sess.verbose > 4)
 	clog << "saw .probes " << probe_name
-	     << "@0x" << hex << probe_arg << dec << endl;
+	     << "@0x" << hex << pc << dec << endl;
 
-      probe_scn_offset += sizeof (struct probe_entry);
       if ((mark_name == probe_name)
 	  || (dw.name_has_wildcard (mark_name)
 	      && dw.function_name_matches_pattern (probe_name, mark_name)))
@@ -4298,7 +4419,7 @@ sdt_query::convert_probe (probe *base)
 
   // XXX: Does this also need to happen for i386 under x86_64 stap?
 #ifdef __i386__
-  if (probe_type == kprobe_type)
+  if (have_kprobe())
     {
       functioncall *rp = new functioncall;
       rp->function = "regparm";
@@ -4313,9 +4434,9 @@ sdt_query::convert_probe (probe *base)
     }
 #endif
 
-  if (probe_type == kprobe_type)
+  if (have_kprobe())
     {
-      // Generate: if (arg2 != kprobe_type) next;
+      // Generate: if (arg2 != kprobe2_type) next;
       if_statement *istid = new if_statement;
       istid->thenblock = new next_statement;
       istid->elseblock = NULL;
@@ -4333,7 +4454,7 @@ sdt_query::convert_probe (probe *base)
       arg2->args.push_back(num);
 
       betid->left = arg2;
-      literal_number* littid = new literal_number(kprobe_type);
+      literal_number* littid = new literal_number(probe_type);
       littid->tok = b->tok;
       betid->right = littid;
       istid->condition = betid;
@@ -4389,17 +4510,19 @@ sdt_query::convert_location ()
 
         switch (probe_type)
           {
-          case uprobe_type:
+          case uprobe1_type:
+          case uprobe2_type:
             if (sess.verbose > 3)
               clog << "probe_type == uprobe_type, use statement addr: 0x"
-                << hex << probe_arg << dec << endl;
+		   << hex << pc << dec << endl;
             // process("executable").statement(probe_arg)
             derived_loc->components[i] =
               new probe_point::component(TOK_STATEMENT,
-                                         new literal_number(probe_arg, true));
+                                         new literal_number(pc, true));
             break;
 
-	  case kprobe_type:
+	  case kprobe1_type:
+	  case kprobe2_type:
 	    if (sess.verbose > 3)
 	      clog << "probe_type == kprobe_type" << endl;
 	    // kernel.function("*getegid*")
@@ -4412,7 +4535,7 @@ sdt_query::convert_location ()
           default:
             if (sess.verbose > 3)
               clog << "probe_type == use_uprobe_no_dwarf, use label name: "
-                << "_stapprobe1_" << mark_name << endl;
+		   << "_stapprobe1_" << mark_name << endl;
             // process("executable").function("*").label("_stapprobe1_MARK_NAME")
             derived_loc->components[i] =
               new probe_point::component(TOK_FUNCTION, new literal_string("*"));
@@ -4423,7 +4546,7 @@ sdt_query::convert_location ()
           }
       }
     else if (derived_loc->components[i]->functor == TOK_PROCESS
-             && probe_type == kprobe_type)
+             && have_kprobe())
       {
         derived_loc->components[i] = new probe_point::component(TOK_KERNEL);
       }
@@ -4998,7 +5121,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
               s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ",";
               s.op->line() << " .callback=&stap_uprobe_process_found,";
             }
-          if (p->section != ".absolute") // ET_DYN 
+          else if (p->section != ".absolute") // ET_DYN 
             {
 	      if (p->has_library && p->sdt_semaphore_addr != 0)
 		s.op->line() << " .procname=\"" << p->path << "\", ";

##### not shown is sdt_misc.exp  which uses an old format
##### sdt.h that is squirrelled away in /testsuite to build and test with.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-04-12  3:41 debuginfoless static user probes Stan Cox
@ 2010-04-12 16:11 ` Frank Ch. Eigler
  2010-04-22 13:41   ` Stan Cox
  0 siblings, 1 reply; 10+ messages in thread
From: Frank Ch. Eigler @ 2010-04-12 16:11 UTC (permalink / raw)
  To: Stan Cox; +Cc: SystemTap List

Stan Cox <scox@redhat.com> writes:

> This patch implements adding info to the .probes section to access
> probe arguments and since the probe address is also in the .probes
> section this means no debuginfo is required for a
> process("proc").mark("mark") probe.

Thanks.

> The .probes section format is now:
> %rcx %rsi %rdi 
> seven__test
> UPB1
> pointer to seven__test
> count of probe arguments
> probe address
> pointer to argument asm string

You will earn reap manifold benefits if each and every permutation of
the .probes struct is available in sys/sdt.h as a full fledged struct
declaration.  It may be helpful to also include the capability to
generate all corresponding STAP_PROBE_DATA() variants, e.g. for use by
the testsuite.

It would also be good to document clearly the run-time interface ABI
at the probe invocation moment, for each of these probes.  i.e.,
kprobe1 style assumes kprobe in sys_geteuid, arg1 being blah, arg2
being blah2, blah blah blah.

It's nice to have the arg-count in there finally; this should improve
translation-time error handling.


> --- a/tapset/i386/registers.stp
> +++ b/tapset/i386/registers.stp
> @@ -12,12 +12,16 @@ function _stp_register_regs() {
>  
>  	/* Same order as pt_regs */
>  	_reg_offsets["ebx"] =  0		_reg_offsets["bx"] =  0
> +			      			_reg_offsets["bl"] =  0
>  	_reg_offsets["ecx"] =  4		_reg_offsets["cx"] =  4
> +			      			_reg_offsets["cl"] =  4
> [...]

Ah an interesting solution: map the register names in the assembly
code to strings supplied to the tapset function.  This would make
these tapset functions more heavily used than usual.  Some
complications: more testing re. valid and unexpected inputs, treatment
of kernel-space vs user-space register sets (see the PR10601 stuff for
uprobes).  Consider that the expressions / register names would
henceforth arrive from untrustworthy user-space binaries!


>    sdt_var_expanding_visitor(string & process_name, string & probe_name,
> -			    int arg_count, bool have_reg_args):
> +			    string & arg_string,
> +			    int arg_count, bool have_kprobe):

(Do those string& args need to be string& as opposed to const string& ?
Are those additional outputs?)


> [...]
> +	  for (unsigned i = 0; i < tok.length(); i++)
> +	    // Recognize: %R | (%R) | N(%R)
> +	    switch (tok[i])
> +	      {
> +	      case '-':
> +	      case '1' ... '9':
> +		{
> +		  disp_str = tok.substr(i,tok.find('(',i)-i);
> +		  i += disp_str.length();
> +		  disp = lex_cast<int>(disp_str);
> +		  arg_in_memory = true;
> +		  break;
> +		}
> +	      case '(':
> +		arg_in_memory = true;
> +		break;
> +	      case ')':
> +		break;
> +	      case '%':
> +		{
> +		  reg = tok.substr(i+1,tok.find(')',i)-i-1);
> +		  i += reg.length();
> +		  break;
> +		}
> +	      default:
> +		bad_asm_op = true;
> +	      }

It would seem less fragile to use a mechanism such as regular
expressions to parse the thing.  (Remember, they are not trustworthy
from a security point of view.)


> [...]
> +	      literal_number* num = new literal_number(3);
> [...]
> +	      literal_number* inc = new literal_number((argno - 1) * 8);

There are a couple of similar magic numbers (3, -1, 8) in there that
should be better explained.


> +	  if (have_kprobe || arg_in_memory)
> +	    provide(fc);
> +	  else
> +	    provide(be);

Just confirming, you are not removing the translator's compatibility
with the old style probes, right?  It may make the code best if all
the alternatives are handled in completely separate code paths in the
translator, without intermingling the code with flags like
"have_kprobe || arg_in_memory".  If there are too many conditionals,
the code probably could be improved.  This is C++, we can subtype etc.
if needed.

> @@ -4109,10 +4178,12 @@ sdt_query::handle_query_module()
>  	  clog << "matched probe_name " << probe_name << " probe_type ";
>  	  switch (probe_type)
>  	    {
> -	    case uprobe_type:
> -	      clog << "uprobe at 0x" << hex << probe_arg << dec << endl;
> +	    case uprobe1_type:
> +	    case uprobe2_type:
> +	      clog << "uprobe at 0x" << hex << pc << dec << endl;
>  	      break;
> -	    case kprobe_type:
> +	    case kprobe1_type:
> +	    case kprobe2_type:
>  	      clog << "kprobe" << endl;
>  	      break;
>  	    }

We lose diagnostic capabilities if uprobe1/uprobe2 are shown
indistinguisably here.


> +	  Dwarf_Addr bias;
> +	  Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (q.dw.mod_info->mod, &bias))
> +		      ?: dwfl_module_getelf (q.dw.mod_info->mod, &bias));
> +
> +	  GElf_Ehdr ehdr_mem;
> +	  GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
> +	  string section;
> +	  if ((em->e_type == ET_EXEC))
> +	    section = ".absolute";
> +	  else if (em->e_type == ET_DYN)
> +	    section = ".dynamic";
> +	  uprobe_derived_probe* p =
> +	    new uprobe_derived_probe ("", "", 0, q.module_val, section /*".absolute"*/,
> +				     q.statement_num_val, q.statement_num_val,
> +				     q, 0);
> +	  results.push_back (p);

This looks OK, but will need the sdt.exp style permutation testing
with various flavours of executables / shared libraries (pie/prelink).

> +	  sess.unwindsym_modules.insert ("kernel");

(Why?)


> +      if (probe_type == uprobe1_type || probe_type == kprobe1_type)
> +	{
> +	  struct probe_entry
> +	  {
> +	    __uint64_t name;
> +	    __uint64_t arg;
> +	  }  *pbe;
> +
> +	  probe_scn_offset += sizeof(__uint32_t);
> +	  probe_scn_offset += probe_scn_offset % sizeof(__uint64_t);
> +	  pbe = (struct probe_entry*) ((char*)pdata->d_buf + probe_scn_offset);
> +	  if (pbe->name == 0)
> +	    return false;
> +	  probe_name = (char*)((char*)pdata->d_buf + pbe->name - (char*)probe_scn_addr);

All this pointer goo could go away if sdt.h contained usable
declarations for the .probe structs.


Thanks, good progress.


- FChE

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-04-12 16:11 ` Frank Ch. Eigler
@ 2010-04-22 13:41   ` Stan Cox
  2010-05-04 17:45     ` Stan Cox
  0 siblings, 1 reply; 10+ messages in thread
From: Stan Cox @ 2010-04-22 13:41 UTC (permalink / raw)
  To: systemtap

[-- Attachment #1: Type: text/plain, Size: 48 bytes --]

This addresses everything but register mapping.

[-- Attachment #2: stap-111.diff --]
[-- Type: text/plain, Size: 30758 bytes --]

--- a/includes/sys/sdt.h
+++ b/includes/sys/sdt.h
@@ -10,6 +10,25 @@
 #include <sys/types.h>
 #include <errno.h>
#####  
##### Added probe entry descriptions for both v1 and v2
##### 
+typedef struct 
+{
+  struct
+  {
+    int type_a;
+    int type_b;
+  };
+  __uint64_t name;
+  __uint64_t arg;
+}  stap_sdt_probe_entry_v1;
+
+typedef struct
+{
+  __uint64_t type;
+  __uint64_t name;
+  __uint64_t arg_count;
+  __uint64_t pc;
+  __uint64_t arg_string;
+}   stap_sdt_probe_entry_v2;
 
 #ifdef __LP64__
 #define STAP_PROBE_ADDR(arg) "\t.quad " arg
@@ -25,7 +44,18 @@
    on having a writable .probes section to put the enabled variables in. */
 #define ALLOCSEC "\"aw\""
 
+#if defined STAP_HAS_SEMAPHORES
+#define STAP_SEMAPHORE(probe)	\
+  if (__builtin_expect ( probe ## _semaphore , 0))
+#else
+#define STAP_SEMAPHORE(probe)
+#endif
+
+#if ! defined EXPERIMENTAL_KPROBE_SDT
+
 /* An allocated section .probes that holds the probe names and addrs. */
##### 
##### Both v1 and v2 probe entries can be generated
##### 
+#ifdef STAP_SDT_V1 /* allow users to override */
+#define STAP_UPROBE_GUARD 0x31425250
 #define STAP_PROBE_DATA_(probe,guard,arg)		\
   __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
 		    "\t.balign 8\n"			\
@@ -38,18 +68,26 @@
 		    STAP_PROBE_ADDR(#arg "\n")		\
 		    "\t.int 0\n"			\
 		    "\t.previous\n")
-
-#define STAP_PROBE_DATA(probe, guard, arg)	\
-  STAP_PROBE_DATA_(#probe,guard,arg)
-
-#if defined STAP_HAS_SEMAPHORES
-#define STAP_SEMAPHORE(probe)	\
-  if (__builtin_expect ( probe ## _semaphore , 0))
 #else
-#define STAP_SEMAPHORE(probe)
+#define STAP_UPROBE_GUARD 0x31425055
+#define STAP_PROBE_DATA_(probe,guard,argc)		\
+  __asm__ volatile ("\t.balign 8\n"			\
+		    "1:\n\t.asciz " #probe "\n"		\
+  		    "\t.balign 8\n"			\
+		    "\t.int " #guard "\n"		\
+		    "\t.balign 8\n"			\
+  		    STAP_PROBE_ADDR ("1b\n")		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR (#argc "\n")	\
+                    "\t.balign 8\n"                     \
+                    STAP_PROBE_ADDR("2f\n")          	\
+                    "\t.balign 8\n"                     \
+                    STAP_PROBE_ADDR("3b\n")		\
+		    "\t.int 0\n"			\
+		    "\t.previous\n")
 #endif
-
-#if ! defined EXPERIMENTAL_KPROBE_SDT
+#define STAP_PROBE_DATA(probe, guard, argc)	\
+  STAP_PROBE_DATA_(#probe,guard,argc)
 
 /* These baroque macros are used to create a unique label. */
 #define STAP_CONCAT(a,b) a ## b
@@ -78,8 +116,6 @@
 #define STAP_NOP "\tnop 0 "
 #endif
 
-#define STAP_UPROBE_GUARD 0x31425250
-
 #ifndef STAP_SDT_VOLATILE /* allow users to override */
 #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 5 \
      || (defined __GNUC_RH_RELEASE__ \
@@ -90,146 +126,149 @@
 #define STAP_SDT_VOLATILE volatile
 #endif
 #endif
##### 
##### Common probe entry generator for both v1 and v2
##### 
+
+#ifdef STAP_SDT_V1
+#define STAP_PROBE_POINT(probe,argc,arg_format,args...)	\
+  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,2f);		\
+  __asm__ volatile ("2:\n" STAP_NOP "/* " arg_format " */" :: args);
+#else
+#define STAP_PROBE_POINT(probe,argc,arg_format,args...)	\
+  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
+		    "\t.balign 8\n"			\
+		    "3:\n\t.asciz " #arg_format :: args);	\
+  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,argc);	\
+  __asm__ volatile ("2:\n" STAP_NOP);	
+#endif
+
+#ifdef STAP_SDT_V1
 #define STAP_PROBE_(probe)			\
 do {						\
   STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,2f);	\
-  __asm__ volatile ("2:\n"			\
-		    STAP_NOP);			\
+  __asm__ volatile ("2:\n" STAP_NOP);			\
 } while (0)
+#else
+#define STAP_PROBE_(probe)			\
+do {						\
+  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
+		    "\t.balign 8\n");			\
+  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,0);	\
+  __asm__ volatile ("2:\n" STAP_NOP);			\
+} while (0)
+#endif
 
##### 
##### Probe point generation
##### 
 #define STAP_PROBE1_(probe,label,parm1)			\
 do STAP_SEMAPHORE(probe) {				\
-  STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;	\
+  STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;		\
   STAP_UNINLINE;					\
-  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,2f);		\
-  __asm__ volatile ("2:\n"				\
-		    STAP_NOP "/* %0 */" :: "g"(arg1));	\
+  STAP_PROBE_POINT(probe, 1, "%0", "g"(arg1))		\
  } while (0)
 
 #define STAP_PROBE2_(probe,label,parm1,parm2)				\
 do STAP_SEMAPHORE(probe) {						\
-  STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;			\
-  STAP_SDT_VOLATILE __typeof__((parm2)) arg2 = parm2;			\
-  STAP_UNINLINE;							\
-  STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,2f);				\
-  __asm__ volatile ("2:\n"						\
-		    STAP_NOP "/* %0 %1 */" :: "g"(arg1), "g"(arg2));	\
+  STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;				\
+  STAP_SDT_VOLATILE __typeof__((parm2)) arg2 = parm2;				\
+  STAP_UNINLINE;					\
+  STAP_PROBE_POINT(probe, 2, "%0 %1", "g"(arg1), "g"(arg2));	\
 } while (0)
##### 
##### etc for ... STAP_PROBE10
##### 
@@ -238,12 +277,47 @@ do STAP_SEMAPHORE(probe) {						\
 # if defined (__USE_ANSI)
 extern long int syscall (long int __sysno, ...) __THROW;
 # endif
-# if defined EXPERIMENTAL_KPROBE_SDT
+
+#include <sys/syscall.h>
+
+/* An allocated section .probes that holds the probe names and addrs. */
 # define STAP_SYSCALL __NR_getegid
+#ifdef STAP_SDT_V1 /* allow users to override */
 # define STAP_GUARD 0x32425250
-# endif
+#define STAP_PROBE_DATA_(probe,guard,arg)		\
+  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
+		    "\t.balign 8\n"			\
+		    "1:\n\t.asciz " #probe "\n"         \
+		    "\t.balign 4\n"                     \
+		    "\t.int " #guard "\n"		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR("1b\n")             \
+		    "\t.balign 8\n"                     \
+		    STAP_PROBE_ADDR(#arg "\n")		\
+		    "\t.int 0\n"			\
+		    "\t.previous\n")
+#else
+# define STAP_GUARD 0x3142504b
+#define STAP_PROBE_DATA_(probe,guard,argc)	\
+  __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
+		    "\t.balign 8\n"			\
+		    "1:\n\t.asciz " #probe "\n"		\
+		    "\t.balign 8\n"			\
+		    "\t.int " #guard "\n"		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR ("1b\n")		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR (#argc "\n")	\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR ("0\n")		\
+		    "\t.balign 8\n"			\
+		    STAP_PROBE_ADDR ("0\n")		\
+		    "\t.int 0\n"			\
+		    "\t.previous\n")
+#endif
 
-#include <sys/syscall.h>
+#define STAP_PROBE_DATA(probe, guard, argc)	\
+  STAP_PROBE_DATA_(#probe,guard,argc)
 
 #define STAP_PROBE_(probe)			\
 do STAP_SEMAPHORE(probe) {			\
##### 
##### No change to the register mechanism
##### 
--- a/tapset/i386/registers.stp
+++ b/tapset/i386/registers.stp
@@ -12,12 +12,16 @@ function _stp_register_regs() {
 
 	/* Same order as pt_regs */
 	_reg_offsets["ebx"] =  0		_reg_offsets["bx"] =  0
+			      			_reg_offsets["bl"] =  0
 	_reg_offsets["ecx"] =  4		_reg_offsets["cx"] =  4
+			      			_reg_offsets["cl"] =  4
 	_reg_offsets["edx"] =  8		_reg_offsets["dx"] =  8
+			      			_reg_offsets["dl"] =  8
 	_reg_offsets["esi"] = 12		_reg_offsets["si"] = 12
 	_reg_offsets["edi"] = 16		_reg_offsets["di"] = 16
 	_reg_offsets["ebp"] = 20		_reg_offsets["bp"] = 20
 	_reg_offsets["eax"] = 24		_reg_offsets["ax"] = 24
+			      			_reg_offsets["al"] = 24
 	_reg_offsets["xds"] = 28		_reg_offsets["ds"] = 28
 	_reg_offsets["xes"] = 32		_reg_offsets["es"] = 32
 	_reg_offsets["xfs"] = 36		_reg_offsets["fs"] = 36

--- a/tapset/x86_64/registers.stp
+++ b/tapset/x86_64/registers.stp
@@ -2,21 +2,35 @@ global _reg_offsets, _r32_offsets, _stp_regs_registered
 
 function _stp_register_regs() {
 	/* Same order as pt_regs */
-	_reg_offsets["r15"] = 0
-	_reg_offsets["r14"] = 8
-	_reg_offsets["r13"] = 16
-	_reg_offsets["r12"] = 24
+	_reg_offsets["r15"] = 0		_reg_offsets["r15d"] = 0
+	_reg_offsets["r15w"] = 0	_reg_offsets["r15b"] = 0
+	_reg_offsets["r14"] = 8		_reg_offsets["r14d"] = 8
+	_reg_offsets["r14w"] = 8	_reg_offsets["r14b"] = 8
+	_reg_offsets["r13"] = 16	_reg_offsets["r13d"] = 16
+	_reg_offsets["r13w"] = 16	_reg_offsets["r13b"] = 16
+	_reg_offsets["r12"] = 24	_reg_offsets["r12d"] = 24
+	_reg_offsets["r12w"] = 24	_reg_offsets["r12b"] = 24
 	_reg_offsets["rbp"] = 32	_reg_offsets["bp"] = 32
 	_reg_offsets["rbx"] = 40	_reg_offsets["bx"] = 40
-	_reg_offsets["r11"] = 48
-	_reg_offsets["r10"] = 56
-	_reg_offsets["r9"]  = 64
-	_reg_offsets["r8"]  = 72
+			      		_reg_offsets["bl"] = 40
+	_reg_offsets["r11"] = 48	_reg_offsets["r11d"] = 48
+	_reg_offsets["r11w"] = 48	_reg_offsets["r11b"] = 48
+	_reg_offsets["r10"] = 56	_reg_offsets["r10d"] = 56
+	_reg_offsets["r10w"] = 56	_reg_offsets["r10b"] = 56
+	_reg_offsets["r9"]  = 64	_reg_offsets["r9d"]  = 64
+	_reg_offsets["r9w"]  = 64	_reg_offsets["r9b"]  = 64
+	_reg_offsets["r8"]  = 72	_reg_offsets["r8d"]  = 72
+	_reg_offsets["r8w"]  = 72	_reg_offsets["r8b"]  = 72
 	_reg_offsets["rax"] = 80	_reg_offsets["ax"] = 80
+			      		_reg_offsets["al"] = 80
 	_reg_offsets["rcx"] = 88	_reg_offsets["cx"] = 88
+			      		_reg_offsets["cl"] = 88
 	_reg_offsets["rdx"] = 96	_reg_offsets["dx"] = 96
+			      		_reg_offsets["dl"] = 96
 	_reg_offsets["rsi"] = 104	_reg_offsets["si"] = 104
+			      		_reg_offsets["sil"] = 104
 	_reg_offsets["rdi"] = 112	_reg_offsets["di"] = 112
+			      		_reg_offsets["dil"] = 112
 	_reg_offsets["orig_rax"] = 120	_reg_offsets["orig_ax"] = 120
 	_reg_offsets["rip"] = 128	_reg_offsets["ip"] = 128
 	_reg_offsets["xcs"] = 136	_reg_offsets["cs"] = 136

--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -22,6 +22,7 @@
 #include "hash.h"
 #include "dwflpp.h"
 #include "setupdwfl.h"
+#include "sys/sdt.h"
 
 #include <cstdlib>
 #include <algorithm>
@@ -49,6 +50,7 @@ extern "C" {
 #include <stdio.h>
 #include <sys/types.h>
 #include <math.h>
+#include <regex.h>
 
 #define __STDC_FORMAT_MACROS
 #include <inttypes.h>
@@ -3881,27 +3883,51 @@ dwarf_derived_probe_group::emit_module_exit (systemtap_session& s)
   s.op->newline(-1) << "}";
 }
 
##### 
##### distinct codepaths for uprobe/kprobe variable expansion
##### 
-struct sdt_var_expanding_visitor: public var_expanding_visitor
+
+struct sdt_uprobe_var_expanding_visitor: public var_expanding_visitor
 {
-  sdt_var_expanding_visitor(string & process_name, string & probe_name,
-			    int arg_count, bool have_reg_args):
+  sdt_uprobe_var_expanding_visitor(const string & process_name,
+				   const string & probe_name,
+				   const string & arg_string,
+				   int arg_count):
     process_name (process_name), probe_name (probe_name),
-    have_reg_args (have_reg_args),
     arg_count (arg_count)
   {
-    assert(!have_reg_args || (arg_count >= 0 && arg_count <= 10));
+    tokenize(arg_string, arg_tokens, " ");
+    assert(arg_count >= 0 && arg_count <= 10);
   }
-  string & process_name;
-  string & probe_name;
-  bool have_reg_args;
+  const string & process_name;
+  const string & probe_name;
   int arg_count;
+  vector<string> arg_tokens;
+
+  void visit_target_symbol (target_symbol* e);
+  void visit_defined_op (defined_op* e);
+};
+
+struct sdt_kprobe_var_expanding_visitor: public var_expanding_visitor
+{
+  sdt_kprobe_var_expanding_visitor(const string & process_name,
+				   const string & probe_name,
+				   const string & arg_string,
+				   int arg_count):
+    process_name (process_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 & probe_name;
+  int arg_count;
+  vector<string> arg_tokens;
 
   void visit_target_symbol (target_symbol* e);
   void visit_defined_op (defined_op* e);
 };
 
 void
-sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
+sdt_uprobe_var_expanding_visitor::visit_target_symbol (target_symbol *e)
 {
   try
     {
@@ -3916,11 +3942,120 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
##### 
##### Use regex to parse argument  string
##### 
           return;
         }
 
-      if (!startswith(e->base_name, "$arg") || ! have_reg_args)
+      int argno = 0;
+      try
+        {
+          argno = lex_cast<int>(e->base_name.substr(4));
+        }
+      catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF
+        {
+          throw semantic_error("invalid argument number", e->tok);
+        }
+      if (argno < 1 || argno > arg_count)
+        throw semantic_error("invalid argument number", e->tok);
+      bool arg_in_memory = false;
+      functioncall *fc = new functioncall;
+      binary_expression *be = new binary_expression;
+      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][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)))
+	throw semantic_error("Unsupported assembler operand while accessing " + probe_name + " " + e->base_name + " " + arg_tokens[argno-1], e->tok);
+      // Is there a displacement?
+      if (pmatch[2].rm_so > pmatch[1].rm_so)
+	{
+	  string disp_str =	(char*)&arg_tokens[argno-1][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]) == '(')
+	//      if (pmatch[2].rm_eo == (pmatch[2].rm_so + 1))
+	arg_in_memory = true;
+      // Is there a register?
+      if (pmatch[3].rm_eo >= pmatch[3].rm_so)
+	{
+	  reg = (char*)&arg_tokens[argno-1][pmatch[3].rm_so+1];
+	  reg.erase(pmatch[3].rm_eo - pmatch[3].rm_so - 1);
+	}
+	  
+      if (reg.length() == 0)
+	throw semantic_error("Unsupported assembler operand while accessing " + probe_name + " " + e->base_name, e->tok);
+
+      fc->function = "user_long";
+      fc->tok = e->tok;
+      be->tok = e->tok;
+      functioncall *get_arg1 = new functioncall;
+      get_arg1->function = "register";
+      get_arg1->tok = e->tok;
+      literal_string* reg_arg = new literal_string(reg);
+      reg_arg->tok = e->tok;
+      get_arg1->args.push_back(reg_arg);
+
+      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);
+
+      if (e->components.empty()) // We have a scalar
         {
-          // NB: uprobes-based sdt.h; $argFOO gets resolved later.
-          // XXX: We don't even know the arg_count in this case.
-          provide(e);
+          if (e->addressof)
+            throw semantic_error("cannot take address of sdt variable", e->tok);
+
+	  if (arg_in_memory)
+	    provide(fc);
+	  else
+	    provide(be);
+          return;
+        }
+      cast_op *cast = new cast_op;
+      cast->base_name = "@cast";
+      cast->tok = e->tok;
+      if (arg_in_memory)
+	cast->operand = fc;
+      else
+	cast->operand = be;
+      cast->components = e->components;
+      cast->type = probe_name + "_arg" + lex_cast(argno);
+      cast->module = process_name;
+
+      cast->visit(this);
+    }
+  catch (const semantic_error &er)
+    {
+      e->chain (er);
+      provide (e);
+    }
+}
+
+
+void
+sdt_kprobe_var_expanding_visitor::visit_target_symbol (target_symbol *e)
+{
+  try
+    {
+      if (e->base_name == "$$name")
+        {
+          if (e->addressof)
+            throw semantic_error("cannot take address of sdt context variable", e->tok);
+
+          literal_string *myname = new literal_string (probe_name);
+          myname->tok = e->tok;
+          provide(myname);
           return;
         }
 
@@ -3935,50 +4070,51 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
         }
       if (argno < 1 || argno > arg_count)
         throw semantic_error("invalid argument number", e->tok);
-
       bool lvalue = is_active_lvalue(e);
       functioncall *fc = new functioncall;
 
       // First two args are hidden: 1. pointer to probe name 2. task id
       if (arg_count < 2)
-        {
-          fc->function = "ulong_arg";
-          fc->type = pe_long;
-          fc->tok = e->tok;
-          literal_number* num = new literal_number(argno + 2);
-          num->tok = e->tok;
-          fc->args.push_back(num);
-        }
-      else				// args passed as a struct
-        {
-          fc->function = "user_long";
-          fc->tok = e->tok;
-          binary_expression *be = new binary_expression;
-          be->tok = e->tok;
-          functioncall *get_arg1 = new functioncall;
-          get_arg1->function = "pointer_arg";
-          get_arg1->tok = e->tok;
-          literal_number* num = new literal_number(3);
-          num->tok = e->tok;
-          get_arg1->args.push_back(num);
-
-          be->left = get_arg1;
-          be->op = "+";
-          literal_number* inc = new literal_number((argno - 1) * 8);
-          inc->tok = e->tok;
-          be->right = inc;
-          fc->args.push_back(be);
-        }
-
+	{
+	  fc->function = "ulong_arg";
+	  fc->type = pe_long;
+	  fc->tok = e->tok;
+	  // skip hidden args
+	  literal_number* num = new literal_number(argno + 2);
+	  num->tok = e->tok;
+	  fc->args.push_back(num);
+	}
+      else
+	{
+	  // args are passed in arg3 as members of a struct
+	  fc->function = "user_long";
+	  fc->tok = e->tok;
+	  binary_expression *be = new binary_expression;
+	  be->tok = e->tok;
+	  functioncall *get_arg1 = new functioncall;
+	  get_arg1->function = "pointer_arg";
+	  get_arg1->tok = e->tok;
+	  literal_number* num = new literal_number(3); // struct in arg3
+	  num->tok = e->tok;
+	  get_arg1->args.push_back(num);
+
+	  be->left = get_arg1;
+	  be->op = "+";
+	  // offset in struct to the desired arg
+	  literal_number* inc = new literal_number((argno - 1) * 8);
+	  inc->tok = e->tok;
+	  be->right = inc;
+	  fc->args.push_back(be);
+	}
       if (lvalue)
-        *(target_symbol_setter_functioncalls.top()) = fc;
+	*(target_symbol_setter_functioncalls.top()) = fc;
 
-      if (e->components.empty())
+      if (e->components.empty()) // We have a scalar
         {
           if (e->addressof)
             throw semantic_error("cannot take address of sdt variable", e->tok);
 
-          provide(fc);
+	  provide(fc);
           return;
         }
       cast_op *cast = new cast_op;
@@ -3998,16 +4134,19 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
     }
 }
 
-
+  
 // See var_expanding_visitor::visit_defined_op for a background on
-// this callback, 
+// this callback,
 void
-sdt_var_expanding_visitor::visit_defined_op (defined_op *e)
+sdt_uprobe_var_expanding_visitor::visit_defined_op (defined_op *e)
 {
-  if (! have_reg_args) // for uprobes, pass @defined through to dwarf synthetic probe's own var-expansion
-    provide (e);
-  else
-    var_expanding_visitor::visit_defined_op (e);
+  provide (e);
+}
+
+void
+sdt_kprobe_var_expanding_visitor::visit_defined_op (defined_op *e)
+{
+  var_expanding_visitor::visit_defined_op (e);
 }
 
 
@@ -4022,8 +4161,10 @@ struct sdt_query : public base_query
 private:
   enum probe_types
     {
-      uprobe_type = 0x31425250, // "PRB1"
-      kprobe_type = 0x32425250, // "PRB2"
+      uprobe1_type = 0x31425250, // "PRB1"
+      uprobe2_type = 0x31425055, // "UPB1"
+      kprobe1_type = 0x32425250, // "PRB2"
+      kprobe2_type = 0x3142504b  // "KPB1"
     } probe_type;
 
   probe * base_probe;
@@ -4037,7 +4178,9 @@ private:
   Elf_Data *pdata;
   size_t probe_scn_offset;
   size_t probe_scn_addr;
-  uint64_t probe_arg;
+  uint64_t arg_count;
+  uint64_t pc;
+  string arg_string;
   string probe_name;
 
   bool init_probe_scn();
@@ -4046,6 +4189,8 @@ private:
   void convert_probe(probe *base);
   void record_semaphore(vector<derived_probe *> & results, unsigned start);
   probe* convert_location();
+  bool have_uprobe() {return probe_type == uprobe1_type || probe_type == uprobe2_type;}
+  bool have_kprobe() {return probe_type == kprobe1_type || probe_type == kprobe2_type;}
 };
 
 
@@ -4070,7 +4215,7 @@ sdt_query::handle_query_module()
 
   while (get_next_probe())
     {
-      if (probe_type != uprobe_type
+      if (! have_uprobe()
 	  && !probes_handled.insert(probe_name).second)
         continue;
 
@@ -4079,11 +4224,17 @@ sdt_query::handle_query_module()
##### 
##### Tailor log message to probe type
##### 
 	  clog << "matched probe_name " << probe_name << " probe_type ";
 	  switch (probe_type)
 	    {
-	    case uprobe_type:
-	      clog << "uprobe at 0x" << hex << probe_arg << dec << endl;
+	    case uprobe1_type:
+	      clog << "uprobe1 at 0x" << hex << pc << dec << endl;
+	      break;
+	    case uprobe2_type:
+	      clog << "uprobe2 at 0x" << hex << pc << dec << endl;
 	      break;
-	    case kprobe_type:
-	      clog << "kprobe" << endl;
+	    case kprobe1_type:
+	      clog << "kprobe1" << endl;
+	      break;
+	    case kprobe2_type:
+	      clog << "kprobe2" << endl;
 	      break;
 	    }
 	}
@@ -4092,22 +4243,30 @@ sdt_query::handle_query_module()
       probe *new_base = convert_location();
       probe_point *new_location = new_base->locations[0];
 
-      bool have_reg_args = false;
-      if (probe_type == kprobe_type)
+      bool kprobe_found = false;
+      if (have_kprobe())
         {
           convert_probe(new_base);
-          have_reg_args = true;
+          kprobe_found = true;
+	  // Expand the local variables in the probe body
+	  sdt_kprobe_var_expanding_visitor svv (module_val,
+						probe_name,
+						arg_string,
+						arg_count);
+	  svv.replace (new_base->body);
         }
-
-      // Expand the local variables in the probe body
-      sdt_var_expanding_visitor svv (module_val, probe_name,
-                                     probe_arg, // XXX: whoa, isn't this 'arg_count'?
-                                     have_reg_args);
-      svv.replace (new_base->body);
-
+      else
+	{
+	  sdt_uprobe_var_expanding_visitor svv (module_val,
+						probe_name,
+						arg_string,
+						arg_count);
+	  svv.replace (new_base->body);
+	}
+      
       unsigned i = results.size();
 
-      if (probe_type == kprobe_type)
+      if (have_kprobe())
         derive_probes(sess, new_base, results);
 
       else
@@ -4119,11 +4278,30 @@ sdt_query::handle_query_module()
##### 
##### Do not require debuginfo for v2, just wireup a uprobe_derived_probe
##### 
               params[c->functor] = c->arg;
             }
 
-          dwarf_query q(new_base, new_location, dw, params, results, "", "");
-          q.has_mark = true; // enables mid-statement probing
-          dw.iterate_over_modules(&query_module, &q);
-        }
+	  dwarf_query q(new_base, new_location, dw, params, results, "", "");
+	  q.has_mark = true; // enables mid-statement probing
 
+	  if (probe_type == uprobe1_type)
+	      dw.iterate_over_modules(&query_module, &q);
+	  else if (probe_type == uprobe2_type)
+	    {
+	      Dwarf_Addr bias;
+	      Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (q.dw.mod_info->mod, &bias))
+			  ?: dwfl_module_getelf (q.dw.mod_info->mod, &bias));
+	      GElf_Ehdr ehdr_mem;
+	      GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
+	      string section;
+	      if ((em->e_type == ET_EXEC))
+		section = ".absolute";
+	      else if (em->e_type == ET_DYN)
+		section = ".dynamic";
+	      uprobe_derived_probe* p =
+		new uprobe_derived_probe ("", "", 0, q.module_val, section,
+					  q.statement_num_val, q.statement_num_val,
+					  q, 0);
+	      results.push_back (p);
+	    }
+        }
       record_semaphore(results, i);
     }
 }
@@ -4204,14 +4382,10 @@ sdt_query::get_next_probe()
##### 
##### Simplify using probe entry structs now in sdt.h
##### 
 
   while (probe_scn_offset < pdata->d_size)
     {
-      struct probe_entry
-      {
-	__uint64_t name;
-	__uint64_t arg;
-      }  *pbe;
-      __uint32_t *type = (__uint32_t*) ((char*)pdata->d_buf + probe_scn_offset);
-      probe_type = (enum probe_types)*type;
-      if (probe_type != uprobe_type && probe_type != kprobe_type)
+      stap_sdt_probe_entry_v1 *pbe_v1 = (stap_sdt_probe_entry_v1 *) ((char*)pdata->d_buf + probe_scn_offset);
+      stap_sdt_probe_entry_v2 *pbe_v2 = (stap_sdt_probe_entry_v2 *) ((char*)pdata->d_buf + probe_scn_offset);
+      probe_type = (enum probe_types)(pbe_v1->type_a);
+      if (! have_uprobe() && ! have_kprobe())
 	{
 	  // Unless this is a mangled .probes section, this happens
 	  // because the name of the probe comes first, followed by
@@ -4222,18 +4396,38 @@ sdt_query::get_next_probe()
 	  probe_scn_offset += sizeof(__uint32_t);
 	  continue;
 	}
-      probe_scn_offset += sizeof(__uint32_t);
-      probe_scn_offset += probe_scn_offset % sizeof(__uint64_t);
-      pbe = (struct probe_entry*) ((char*)pdata->d_buf + probe_scn_offset);
-      if (pbe->name == 0)
-	return false;
-      probe_name = (char*)((char*)pdata->d_buf + pbe->name - (char*)probe_scn_addr);
-      probe_arg = pbe->arg;
+      if ((long)pbe_v1 % sizeof(__uint64_t)) // we have stap_sdt_probe_entry_v1.type_b
+	{
+	  pbe_v1 = (stap_sdt_probe_entry_v1*)((char*)pbe_v1 - sizeof(__uint32_t));
+	  if (pbe_v1->type_b != uprobe1_type && pbe_v1->type_b != kprobe1_type)
+	    continue;
+	}
+
+      if (probe_type == uprobe1_type || probe_type == kprobe1_type)
+	{
+	  probe_name = (char*)((char*)pdata->d_buf + pbe_v1->name - (char*)probe_scn_addr);
+	  if (probe_type == uprobe1_type)
+	    {
+	      pc = pbe_v1->arg;
+	      arg_count = 0;
+	    }
+	  else if (probe_type == kprobe1_type)
+	    arg_count = pbe_v1->arg;
+	  probe_scn_offset += sizeof (stap_sdt_probe_entry_v1);
+	}
+      else if (probe_type == uprobe2_type || probe_type == kprobe2_type)
+	{
+	  probe_name = (char*)((char*)pdata->d_buf + pbe_v2->name - (char*)probe_scn_addr);
+	  arg_count = pbe_v2->arg_count;
+	  pc = pbe_v2->pc;
+	  if (pbe_v2->arg_string)
+	    arg_string = (char*)((char*)pdata->d_buf + pbe_v2->arg_string - (char*)probe_scn_addr);
+	  probe_scn_offset += sizeof (stap_sdt_probe_entry_v2);
+	}
       if (sess.verbose > 4)
 	clog << "saw .probes " << probe_name
-	     << "@0x" << hex << probe_arg << dec << endl;
+	     << "@0x" << hex << pc << dec << endl;
 
-      probe_scn_offset += sizeof (struct probe_entry);
       if ((mark_name == probe_name)
 	  || (dw.name_has_wildcard (mark_name)
 	      && dw.function_name_matches_pattern (probe_name, mark_name)))
@@ -4268,7 +4462,7 @@ sdt_query::convert_probe (probe *base)
 
   // XXX: Does this also need to happen for i386 under x86_64 stap?
 #ifdef __i386__
-  if (probe_type == kprobe_type)
+  if (have_kprobe())
     {
       functioncall *rp = new functioncall;
       rp->function = "regparm";
@@ -4283,9 +4477,9 @@ sdt_query::convert_probe (probe *base)
     }
 #endif
 
-  if (probe_type == kprobe_type)
+  if (have_kprobe())
     {
-      // Generate: if (arg2 != kprobe_type) next;
+      // Generate: if (arg2 != kprobe2_type) next;
       if_statement *istid = new if_statement;
       istid->thenblock = new next_statement;
       istid->elseblock = NULL;
@@ -4303,7 +4497,7 @@ sdt_query::convert_probe (probe *base)
       arg2->args.push_back(num);
 
       betid->left = arg2;
-      literal_number* littid = new literal_number(kprobe_type);
+      literal_number* littid = new literal_number(probe_type);
       littid->tok = b->tok;
       betid->right = littid;
       istid->condition = betid;
@@ -4357,21 +4551,41 @@ sdt_query::convert_location ()
##### 
##### Tailor log message to probe type
##### 
         specific_loc->components[i] =
           new probe_point::component(TOK_MARK, new literal_string(probe_name));
 
+	if (sess.verbose > 3)
+	  switch (probe_type)
+	    {
+	    case uprobe1_type:
+              clog << "probe_type == uprobe1, use statement addr: 0x"
+		   << hex << pc << dec << endl;
+	      break;
+	    case uprobe2_type:
+              clog << "probe_type == uprobe2, use statement addr: 0x"
+		   << hex << pc << dec << endl;
+            break;
+
+	  case kprobe1_type:
+	    clog << "probe_type == kprobe1" << endl;
+	    break;
+	  case kprobe2_type:
+	    clog << "probe_type == kprobe2" << endl;
+	    break;
+	    default:
+              clog << "probe_type == use_uprobe_no_dwarf, use label name: "
+		   << "_stapprobe1_" << mark_name << endl;
+          }
+
         switch (probe_type)
           {
-          case uprobe_type:
-            if (sess.verbose > 3)
-              clog << "probe_type == uprobe_type, use statement addr: 0x"
-                << hex << probe_arg << dec << endl;
+          case uprobe1_type:
+          case uprobe2_type:
             // process("executable").statement(probe_arg)
             derived_loc->components[i] =
               new probe_point::component(TOK_STATEMENT,
-                                         new literal_number(probe_arg, true));
+                                         new literal_number(pc, true));
             break;
 
-	  case kprobe_type:
-	    if (sess.verbose > 3)
-	      clog << "probe_type == kprobe_type" << endl;
+	  case kprobe1_type:
+	  case kprobe2_type:
 	    // kernel.function("*getegid*")
 	    derived_loc->components[i] =
 	      new probe_point::component(TOK_FUNCTION, new literal_string("*getegid*"));
@@ -4380,9 +4594,6 @@ sdt_query::convert_location ()
 	    break;
 
           default:
-            if (sess.verbose > 3)
-              clog << "probe_type == use_uprobe_no_dwarf, use label name: "
-                << "_stapprobe1_" << mark_name << endl;
             // process("executable").function("*").label("_stapprobe1_MARK_NAME")
             derived_loc->components[i] =
               new probe_point::component(TOK_FUNCTION, new literal_string("*"));
@@ -4393,7 +4604,7 @@ sdt_query::convert_location ()
           }
       }
     else if (derived_loc->components[i]->functor == TOK_PROCESS
-             && probe_type == kprobe_type)
+             && have_kprobe())
       {
         derived_loc->components[i] = new probe_point::component(TOK_KERNEL);
       }
@@ -4968,7 +5179,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
               s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ",";
               s.op->line() << " .callback=&stap_uprobe_process_found,";
             }
-          if (p->section != ".absolute") // ET_DYN 
+          else if (p->section != ".absolute") // ET_DYN
             {
 	      if (p->has_library && p->sdt_semaphore_addr != 0)
 		s.op->line() << " .procname=\"" << p->path << "\", ";

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-04-22 13:41   ` Stan Cox
@ 2010-05-04 17:45     ` Stan Cox
  2010-05-04 19:09       ` Frank Ch. Eigler
  0 siblings, 1 reply; 10+ messages in thread
From: Stan Cox @ 2010-05-04 17:45 UTC (permalink / raw)
  To: systemtap

[-- Attachment #1: Type: text/plain, Size: 455 bytes --]

On 04/21/2010 04:11 PM, Stan Cox wrote:
> This addresses everything but register mapping.

This replaces the previous change to registers.stp.  Instead of using the 
"register" stapfunc via changing _stp_register_regs to add entries to 
_reg_offsets this takes a different parallel approach.  A new dwarf ordered 
list _dwarf_register_regs is added (parallels _stp_register_regs) which is 
accessed via new stapfunc "fetch_register" (parallels register).

[-- Attachment #2: registers.patch --]
[-- Type: text/plain, Size: 4366 bytes --]

--- /work/scox/virginsystemtap/src/tapset/x86_64/registers.stp	2009-08-27 14:46:44.000000000 -0400
+++ /work/scox/systemtap/src/tapset/x86_64/registers.stp	2010-05-03 15:35:50.000000000 -0400
@@ -1,4 +1,5 @@
 global _reg_offsets, _r32_offsets, _stp_regs_registered
+global _x8664_dwarf_regs, _x8664_dwarf_regs_registered
 
 function _stp_register_regs() {
 	/* Same order as pt_regs */
@@ -94,6 +95,96 @@ function register:long (name:string) {
 	return _stp_register(name, 1)
 }
 
+function _dwarf_register_regs() {
+   _x8664_dwarf_regs["rax"] = 0 _x8664_dwarf_regs["eax"] = 0
+   _x8664_dwarf_regs["ax"] = 0 _x8664_dwarf_regs["al"] = 0
+   _x8664_dwarf_regs["rdx"] = 1 _x8664_dwarf_regs["edx"] = 1
+   _x8664_dwarf_regs["dx"] = 1 _x8664_dwarf_regs["dl"] = 1
+   _x8664_dwarf_regs["rcx"] = 2 _x8664_dwarf_regs["ecx"] = 2
+   _x8664_dwarf_regs["cx"] = 2 _x8664_dwarf_regs["cl"] = 2
+   _x8664_dwarf_regs["rbx"] = 3 _x8664_dwarf_regs["ebx"] = 3
+   _x8664_dwarf_regs["bx"] = 3 _x8664_dwarf_regs["bl"] = 3
+   _x8664_dwarf_regs["rsi"] = 4 _x8664_dwarf_regs["esi"] = 4
+   _x8664_dwarf_regs["si"] = 4 _x8664_dwarf_regs["sil"] = 4
+   _x8664_dwarf_regs["rdi"] = 5 _x8664_dwarf_regs["edi"] = 5
+   _x8664_dwarf_regs["di"] = 5 _x8664_dwarf_regs["dil"] = 5
+   _x8664_dwarf_regs["rbp"] = 6 _x8664_dwarf_regs["ebp"] = 6
+   _x8664_dwarf_regs["bp"] = 6
+   _x8664_dwarf_regs["rsp"] = 7	_x8664_dwarf_regs["esp"] = 7
+   _x8664_dwarf_regs["sp"] = 7
+   _x8664_dwarf_regs["r8"]  = 8 _x8664_dwarf_regs["r8d"]  = 8
+   _x8664_dwarf_regs["r8w"]  = 8 _x8664_dwarf_regs["r8b"]  = 8
+   _x8664_dwarf_regs["r9"]  = 9 _x8664_dwarf_regs["r9d"]  = 9
+   _x8664_dwarf_regs["r9w"]  = 9 _x8664_dwarf_regs["r9b"]  = 9
+   _x8664_dwarf_regs["r10"] = 10 _x8664_dwarf_regs["r10d"] = 10
+   _x8664_dwarf_regs["r10w"] = 10 _x8664_dwarf_regs["r10b"] = 10
+   _x8664_dwarf_regs["r11"] = 11 _x8664_dwarf_regs["r11d"] = 11
+   _x8664_dwarf_regs["r11w"] = 11 _x8664_dwarf_regs["r11b"] = 11
+   _x8664_dwarf_regs["r12"] = 12 _x8664_dwarf_regs["r12d"] = 24
+   _x8664_dwarf_regs["r12w"] = 12 _x8664_dwarf_regs["r12b"] = 24
+   _x8664_dwarf_regs["r13"] = 13 _x8664_dwarf_regs["r13d"] = 16
+   _x8664_dwarf_regs["r13w"] = 13 _x8664_dwarf_regs["r13b"] = 16
+   _x8664_dwarf_regs["r14"] = 14 	_x8664_dwarf_regs["r14d"] = 14
+   _x8664_dwarf_regs["r14w"] = 14 _x8664_dwarf_regs["r14b"] = 14
+   _x8664_dwarf_regs["r15"] = 15 	_x8664_dwarf_regs["r15d"] = 15
+   _x8664_dwarf_regs["r15w"] = 15 _x8664_dwarf_regs["r15b"] = 15
+   _x8664_dwarf_regs_registered = 1
+}
+
+
+/* Return the named register value as a signed value. */
+
+function _stp_u_fetch_register:long (dwarf_regno:long) %{ /* pure */
+
+   uintptr_t value;
+   long dwarf_regno = THIS->dwarf_regno;
+   value = u_fetch_register(dwarf_regno);
+   THIS->__retvalue = value;
+%}
+
+function _stp_k_fetch_register:long (dwarf_regno:long) %{ /* pure */
+   uintptr_t value;
+   long dwarf_regno = THIS->dwarf_regno;
+   switch (dwarf_regno) {
+   case 0: value = k_fetch_register(0);break;
+   case 1: value = k_fetch_register(1);break;
+   case 2: value = k_fetch_register(2);break;
+   case 3: value = k_fetch_register(3);break;
+   case 4: value = k_fetch_register(4);break;
+   case 5: value = k_fetch_register(5);break;
+   case 6: value = k_fetch_register(6);break;
+   case 7: value = k_fetch_register(7);break;
+   case 8: value = k_fetch_register(8);break;
+   case 9: value = k_fetch_register(9);break;
+   case 10: value = k_fetch_register(10);break;
+   case 11: value = k_fetch_register(11);break;
+   case 12: value = k_fetch_register(12);break;
+   case 13: value = k_fetch_register(13);break;
+   case 14: value = k_fetch_register(14);break;
+   case 15: value = k_fetch_register(15);break;
+   }
+   THIS->__retvalue = value;
+%}
+
+
+/* Return the named register value as a signed value. */
+function fetch_register:long (name:string) {
+  if (!_x8664_dwarf_regs_registered)
+     _dwarf_register_regs()
+
+   if (!(name in _x8664_dwarf_regs)) {
+      error("Unknown register: " . name)
+      return 0
+   }
+
+   if (user_mode()) {
+      return _stp_u_fetch_register(_x8664_dwarf_regs[name])
+   }
+   else {
+      return _stp_k_fetch_register(_x8664_dwarf_regs[name])
+   }
+}
+
 /*
  * Return the named register value as an unsigned value.  Specifically,
  * don't sign-extend the register value when promoting it to 64 bits.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-05-04 17:45     ` Stan Cox
@ 2010-05-04 19:09       ` Frank Ch. Eigler
  2010-05-04 21:07         ` David Smith
                           ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Frank Ch. Eigler @ 2010-05-04 19:09 UTC (permalink / raw)
  To: Stan Cox; +Cc: systemtap

Stan Cox <scox@redhat.com> writes:

> [...]
> +function _dwarf_register_regs() {
> +   _x8664_dwarf_regs["rax"] = 0 _x8664_dwarf_regs["eax"] = 0
> +   _x8664_dwarf_regs["ax"] = 0 _x8664_dwarf_regs["al"] = 0
> [...]

Can we hard-code this kind of lookup table inside the translator?
It's just as fixed as the loc2c mappings.


> +function _stp_u_fetch_register:long (dwarf_regno:long) %{ /* pure */
> +
> +   uintptr_t value;
> +   long dwarf_regno = THIS->dwarf_regno;
> +   value = u_fetch_register(dwarf_regno);
> +   THIS->__retvalue = value;
> +%}
> +
> +function _stp_k_fetch_register:long (dwarf_regno:long) %{ /* pure */
> +   uintptr_t value;
> +   long dwarf_regno = THIS->dwarf_regno;
> +   switch (dwarf_regno) {
> +   case 0: value = k_fetch_register(0);break;
> [...]
> +   case 15: value = k_fetch_register(15);break;
> +   }
> +   THIS->__retvalue = value;
> +%}

I see why you're doing this, but I'm ambivalent whether this sort of
extension of the tapset proper is the best way.

Another one would be to synthesize such embedded-C functions
on-demand, just like we do for loc2c content.

Another one would be to introduce the possibility of embedded-C
*expressions* in the parse tree, so that the tapset-mark.cxx code
could emit the equivalent of

     val = %{ (int64_t) k_fetch_register(0) %}

(assumed to be an int64_t valued C expression)
instead of 

     function __foo0 () %{ THIS->__retvalue = k_fetch_register(0); %}
     val = __foo0 ()


Such a construct need not necessarily be parsed, thus available to
end-user scripts.  Though it would make some things easier.  It could
constitute a way to access kernel value macros.


- FChE

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-05-04 19:09       ` Frank Ch. Eigler
@ 2010-05-04 21:07         ` David Smith
  2010-05-06  0:24         ` Roland McGrath
  2010-05-10 17:48         ` Stan Cox
  2 siblings, 0 replies; 10+ messages in thread
From: David Smith @ 2010-05-04 21:07 UTC (permalink / raw)
  To: Frank Ch. Eigler; +Cc: Stan Cox, systemtap

On 05/04/2010 11:57 AM, Frank Ch. Eigler wrote:

...

> Another one would be to introduce the possibility of embedded-C
> *expressions* in the parse tree, so that the tapset-mark.cxx code
> could emit the equivalent of
> 
>      val = %{ (int64_t) k_fetch_register(0) %}
> 
> (assumed to be an int64_t valued C expression)
> instead of 
> 
>      function __foo0 () %{ THIS->__retvalue = k_fetch_register(0); %}
>      val = __foo0 ()
> 
> 
> Such a construct need not necessarily be parsed, thus available to
> end-user scripts.  Though it would make some things easier.  It could
> constitute a way to access kernel value macros.

Oooh - shiny.  So if this was implemented I could do something like this?

if ($var == %{ SOME_KERNEL_DEFINE %}) {
  ...
}

That would be great.

-- 
David Smith
dsmith@redhat.com
Red Hat
http://www.redhat.com
256.217.0141 (direct)
256.837.0057 (fax)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-05-04 19:09       ` Frank Ch. Eigler
  2010-05-04 21:07         ` David Smith
@ 2010-05-06  0:24         ` Roland McGrath
  2010-05-10 17:48         ` Stan Cox
  2 siblings, 0 replies; 10+ messages in thread
From: Roland McGrath @ 2010-05-06  0:24 UTC (permalink / raw)
  To: Frank Ch. Eigler; +Cc: Stan Cox, systemtap

> Stan Cox <scox@redhat.com> writes:
> 
> > [...]
> > +function _dwarf_register_regs() {
> > +   _x8664_dwarf_regs["rax"] = 0 _x8664_dwarf_regs["eax"] = 0
> > +   _x8664_dwarf_regs["ax"] = 0 _x8664_dwarf_regs["al"] = 0
> > [...]
> 
> Can we hard-code this kind of lookup table inside the translator?
> It's just as fixed as the loc2c mappings.

For the primary names, libdwfl can tell you these mappings.  It doesn't
know about the variant names like "eax" (on 64-bit) and "a[xhl]".
We could find a way to add those if it's worthwhile.


Thanks,
Roland

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-05-04 19:09       ` Frank Ch. Eigler
  2010-05-04 21:07         ` David Smith
  2010-05-06  0:24         ` Roland McGrath
@ 2010-05-10 17:48         ` Stan Cox
  2010-05-21 18:37           ` Stan Cox
  2 siblings, 1 reply; 10+ messages in thread
From: Stan Cox @ 2010-05-10 17:48 UTC (permalink / raw)
  To: Frank Ch. Eigler, systemtap

[-- Attachment #1: Type: text/plain, Size: 651 bytes --]

On 05/04/2010 12:57 PM, Frank Ch. Eigler wrote:

> Can we hard-code this kind of lookup table inside the translator?


> embedded-C *expressions* in the parse tree, so that the tapset-mark.cxx code
> could emit the equivalent of
>       val = %{ (int64_t) k_fetch_register(0) %}


tapsets.cxx (sdt_uprobe_var_expanding_visitor): Moved register lookup table 
into the translator.
(sdt_uprobe_var_expanding_visitor::visit_target_symbol): Properly handle v1 
uprobes.  Use fetch_register to fetch arguments

sdt.h (STAP_SDT_V1):  Define if host isn't x86.
(args1, ..., args10):  Variadic macro is cleaner, but unfortunately gets -ansi 
-pedantic warning

[-- Attachment #2: ,stap.diff --]
[-- Type: text/plain, Size: 6489 bytes --]

--- stap-sv/tapsets.cxx	2010-04-25 19:40:11.000000000 -0400
+++ /work/scox/systemtap/src/tapsets.cxx	2010-05-07 10:44:47.000000000 -0400
@@ -3895,11 +3893,28 @@ struct sdt_uprobe_var_expanding_visitor:
   {
     tokenize(arg_string, arg_tokens, " ");
     assert(arg_count >= 0 && arg_count <= 10);
+    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;
   }
   const string & process_name;
   const string & probe_name;
   int arg_count;
   vector<string> arg_tokens;
+  map<string,int> dwarf_regs;
 
   void visit_target_symbol (target_symbol* e);
   void visit_defined_op (defined_op* e);
@@ -3941,6 +3956,18 @@ sdt_uprobe_var_expanding_visitor::visit_
           provide(myname);
           return;
         }
+      if (arg_count == 0)
+	{
+	  if (startswith(e->base_name, "$arg"))
+	    {
+	      // NB: uprobes-based sdt.h; $argFOO gets resolved later.
+	      // XXX: We don't know the arg_count for this uprobe1_type.
+	      provide(e);
+	      return;
+	    }
+	  else			// uprobe2_type with no args
+	    return;
+	}
 
       int argno = 0;
       try
@@ -3994,15 +4020,18 @@ sdt_uprobe_var_expanding_visitor::visit_
       if (reg.length() == 0)
 	throw semantic_error("Unsupported assembler operand while accessing " + probe_name + " " + e->base_name, e->tok);
 
+      // synthesize user_long(%{fetch_register(R)%} + D)
       fc->function = "user_long";
       fc->tok = e->tok;
       be->tok = e->tok;
-      functioncall *get_arg1 = new functioncall;
-      get_arg1->function = "register";
+
+      embedded_expr *get_arg1 = new embedded_expr;
       get_arg1->tok = e->tok;
-      literal_string* reg_arg = new literal_string(reg);
-      reg_arg->tok = e->tok;
-      get_arg1->args.push_back(reg_arg);
+      get_arg1->code = string("/* unpriviledged */ ")
+	+ (is_user_module (process_name)
+	   ? string("u_fetch_register(")
+	   : string("k_fetch_register("))
+	+ lex_cast(dwarf_regs[reg]) + string(")");
 
       be->left = get_arg1;
       be->op = "+";

--- stap-sv/sdt.h	2010-04-25 19:40:11.000000000 -0400
+++ /work/scox/systemtap/src/includes/sys/sdt.h	2010-05-07 16:07:21.000000000 -0400
@@ -12,7 +12,7 @@
 
 typedef struct 
 {
-  struct
+  __extension__ struct
   {
     int type_a;
     int type_b;
@@ -110,6 +110,13 @@ typedef struct
 #define STAP_UNINLINE
 #endif
 
+
+/* The asm operand string stap_sdt_probe_entry_v2.arg_string
+   is currently only supported for x86 */
+#if ! defined __x86_64__ || ! defined __i386__
+#define STAP_SDT_V1 1
+#endif
+
 #if defined __x86_64__ || defined __i386__  || defined __powerpc__ || defined __arm__ || defined __sparc__
 #define STAP_NOP "\tnop "
 #else
@@ -127,12 +134,24 @@ typedef struct
 #endif
 #endif
 
+/* variadic macro args not allowed by -ansi -pedantic so... */
+#define args1 "g"(arg1)
+#define args2 "g"(arg1), "g"(arg2)
+#define args3 "g"(arg1), "g"(arg2), "g"(arg3)
+#define args4 "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4)
+#define args5 "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5)
+#define args6 "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6)
+#define args7 "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7)
+#define args8 "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8)
+#define args9 "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9)
+#define args10 "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9), "g"(arg10)
+
 #ifdef STAP_SDT_V1
-#define STAP_PROBE_POINT(probe,argc,arg_format,args...)	\
+#define STAP_PROBE_POINT(probe,argc,arg_format,args)	\
   STAP_PROBE_DATA(probe,STAP_UPROBE_GUARD,2f);		\
   __asm__ volatile ("2:\n" STAP_NOP "/* " arg_format " */" :: args);
 #else
-#define STAP_PROBE_POINT(probe,argc,arg_format,args...)	\
+#define STAP_PROBE_POINT(probe,argc,arg_format,args)	\
   __asm__ volatile (".section .probes," ALLOCSEC "\n"	\
 		    "\t.balign 8\n"			\
 		    "3:\n\t.asciz " #arg_format :: args);	\
@@ -160,7 +179,7 @@ do {						\
 do STAP_SEMAPHORE(probe) {				\
   STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;		\
   STAP_UNINLINE;					\
-  STAP_PROBE_POINT(probe, 1, "%0", "g"(arg1))		\
+  STAP_PROBE_POINT(probe, 1, "%0", args1)		\
  } while (0)
 
 #define STAP_PROBE2_(probe,label,parm1,parm2)				\
@@ -168,7 +187,7 @@ do STAP_SEMAPHORE(probe) {						\
   STAP_SDT_VOLATILE __typeof__((parm1)) arg1 = parm1;				\
   STAP_SDT_VOLATILE __typeof__((parm2)) arg2 = parm2;				\
   STAP_UNINLINE;					\
-  STAP_PROBE_POINT(probe, 2, "%0 %1", "g"(arg1), "g"(arg2));	\
+  STAP_PROBE_POINT(probe, 2, "%0 %1", args2);	\
 } while (0)
 
 #define STAP_PROBE3_(probe,label,parm1,parm2,parm3)			\
@@ -177,7 +196,7 @@ do STAP_SEMAPHORE(probe) {						\
   STAP_SDT_VOLATILE __typeof__((parm2)) arg2 = parm2;				\
   STAP_SDT_VOLATILE __typeof__((parm3)) arg3 = parm3;				\
   STAP_UNINLINE;							\
-  STAP_PROBE_POINT(probe, 3, "%0 %1 %2", "g"(arg1), "g"(arg2), "g"(arg3)); \
+  STAP_PROBE_POINT(probe, 3, "%0 %1 %2", args3); \
 } while (0)
 
 #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4)		\

### likewise for STAP_PROBE4_ - STAP_PROBE10_

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-05-10 17:48         ` Stan Cox
@ 2010-05-21 18:37           ` Stan Cox
  2010-05-25 20:10             ` Stan Cox
  0 siblings, 1 reply; 10+ messages in thread
From: Stan Cox @ 2010-05-21 18:37 UTC (permalink / raw)
  To: Frank Ch. Eigler, systemtap

Just checking before committing.  The current default is to use debuginfoless 
static user probes and fall back on the version 1 debuginfo probes if the 
application is built with -DSTAP_SDT_V1.  Does that seem a reasonable default?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: debuginfoless static user probes
  2010-05-21 18:37           ` Stan Cox
@ 2010-05-25 20:10             ` Stan Cox
  0 siblings, 0 replies; 10+ messages in thread
From: Stan Cox @ 2010-05-25 20:10 UTC (permalink / raw)
  To: systemtap

On 05/20/2010 05:03 PM, Stan Cox wrote:
> Just checking before committing.  The current default is to use
> debuginfoless static user probes and fall back on the version 1
> debuginfo probes if the application is built with -DSTAP_SDT_V1. Does
> that seem a reasonable default?

Now committed.  Here is a short blurb about it.

- process().mark() static user space markers no longer require the
   application to have debugging information.  The application must be
   built with -DSTAP_SDT_V2 on an x86 architecture, which will create a
   version 2 .probes section that contains probe argument access information.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-05-25 13:37 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-12  3:41 debuginfoless static user probes Stan Cox
2010-04-12 16:11 ` Frank Ch. Eigler
2010-04-22 13:41   ` Stan Cox
2010-05-04 17:45     ` Stan Cox
2010-05-04 19:09       ` Frank Ch. Eigler
2010-05-04 21:07         ` David Smith
2010-05-06  0:24         ` Roland McGrath
2010-05-10 17:48         ` Stan Cox
2010-05-21 18:37           ` Stan Cox
2010-05-25 20:10             ` Stan Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).