public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-sergiodj-stap: Initial implementation of the argument evaluation for probes.
@ 2011-03-14  5:26 sergiodj
  0 siblings, 0 replies; only message in thread
From: sergiodj @ 2011-03-14  5:26 UTC (permalink / raw)
  To: archer-commits

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 11928 bytes --]

The branch, archer-sergiodj-stap has been updated
       via  fe14f2b3be3b8360e7aa4a566f764c84747021b4 (commit)
      from  a62f1cbf34669576a356a7559cc33a4479483255 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit fe14f2b3be3b8360e7aa4a566f764c84747021b4
Author: Sergio Durigan Junior <sergiodj@redhat.com>
Date:   Mon Mar 14 02:23:40 2011 -0300

    Initial implementation of the argument evaluation for probes.
    
    This is *not* the final implementation, and this commit contains a lot
    of trash that will be cleaned ASAP.  It already works for simple
    expressions like `%eax', or simple integer expressions.  I will
    certainly have to work more in order to make it work as desired, but
    this commit already implements lots of features.

-----------------------------------------------------------------------

Summary of changes:
 gdb/elfread.c    |   13 +-
 gdb/stap-probe.c |  802 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gdb/stap-probe.h |    6 +
 3 files changed, 813 insertions(+), 8 deletions(-)

First 500 lines of diff:
diff --git a/gdb/elfread.c b/gdb/elfread.c
index b86073a..ec4ba9f 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1085,7 +1085,7 @@ handle_probe (struct objfile *objfile, struct sdt_note *el,
 {
   bfd *abfd = objfile->obfd;
   int size = bfd_get_arch_size (abfd) / 8;
-  struct gdbarch *gdbarch = get_current_arch ();
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
   CORE_ADDR base_ref;
 
@@ -1240,6 +1240,15 @@ elf_get_probe_argument_count (struct objfile *objfile,
   return stap_get_probe_argument_count (probe);
 }
 
+static struct value *
+elf_evaluate_probe_argument (struct objfile *objfile,
+			     const struct stap_probe *probe,
+			     struct frame_info *frame,
+			     int n)
+{
+  return stap_evaluate_probe_argument (objfile, probe, frame, n);
+}
+
 static void
 elf_symfile_relocate_probe (struct objfile *objfile,
 			    struct section_offsets *new_offsets,
@@ -1279,7 +1288,7 @@ static const struct sym_probe_fns elf_probe_fns =
 {
   elf_get_probes,		/* sym_get_probes */
   elf_get_probe_argument_count,	/* sym_get_probe_argument_count */
-  NULL,				/* sym_evaluate_probe_argument */
+  elf_evaluate_probe_argument,	/* sym_evaluate_probe_argument */
   NULL,				/* sym_compile_to_ax */
   elf_symfile_relocate_probe,	/* sym_relocate_probe */
 };
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index c23cb96..2e54d79 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -30,6 +30,7 @@
 #include "exceptions.h"
 #include "ax.h"
 #include "ax-gdb.h"
+#include "user-regs.h"
 
 #include <ctype.h>
 
@@ -49,6 +50,9 @@ struct stap_probe_arg
 
   /* The string representing this argument.  */
   char *arg_str;
+
+  /* The evaluated value of this argument.  */
+  struct value *val;
 };
 
 #define STAP_MAX_ARGS 10
@@ -124,7 +128,7 @@ stap_parse_arg (const char **p)
 
 	case '+': case '-':
 //	  break;
-	
+
 	case '*': case '/':
 	case '>': case '<': case '|': case '&':
 	case '^': case '!':
@@ -183,8 +187,7 @@ stap_parse_arg (const char **p)
 	      if (*cur >= 'a' && *cur <= 'z')
 		{
 		  /* We're dealing with a register name.  */
-		  while ((*cur >= 'a' && *cur <= 'z')
-			 || (*cur >= '0' && *cur <= '9'))
+		  while (isalnum (*cur))
 		    ++cur;
 
 		  stap_skip_whitespace_cond (&cur, paren_open);
@@ -199,7 +202,7 @@ stap_parse_arg (const char **p)
 		    {
 		      ++cur;
 		      stap_skip_whitespace_cond (&cur, paren_open);
-		      if (*cur < '0' || *cur > '9')
+		      if (!isdigit (*cur))
 			/* This is an error, since we only expect numbers
 			   inside this parenthesis.  */
 			return 0;
@@ -223,18 +226,52 @@ stap_parse_arg (const char **p)
 
 	      while (isdigit (*cur))
 		++cur;
+
+	      stap_skip_whitespace_cond (&cur, paren_open);
 	    }
 	  break;
 
 	case '0': case '1': case '2': case '3': case '4':
 	case '5': case '6': case '7': case '8': case '9':
 	    {
+	      char *old = cur;
+
 	      /* Number.  */
 	      while (isdigit (*cur))
 		++cur;
 
-	      stap_skip_whitespace_cond (&cur, paren_open);
+	      /* We have to do a lookahead here, because the user may
+		 input `2 + 2' (with spaces), and this is not an error.  */
+	      ep_skip_leading_whitespace (&cur);
+
+	      switch (*cur)
+		{
+		case '+': case '-':
+		  /* We may find the `@' sign, and it means that the
+		     argument has finished, so we shouldn't advance the
+		     pointer.  */
+		  if (cur[1] && (cur[1] == '4' || cur[1] == '8')
+		      && cur[2] && cur[2] == '@')
+		    {
+		      cur = old;
+		      goto fin;
+		    }
+		  break;
+
+		case '*': case '/': case '>': case '<':
+		case '|': case '&': case '^': case '!':
+		  /* This is a binary operation, which means we'll
+		     have to find another number after the operator.  */
+		  break;
+
+		case '(':
+		  /* We may also have sentences in the form:
+
+		     `4 (%rax)'  */
+		  break;
+		}
 	    }
+fin:
 	  break;
 	}
     }
@@ -251,8 +288,10 @@ stap_free_args_info (void *args_info_ptr)
   int i;
 
   for (i = 0; i < STAP_MAX_ARGS; i++)
-    if (a->arg->arg_str)
+    {
       xfree (a->arg->arg_str);
+      xfree (a->arg->val);
+    }
 
   xfree (a->arg);
   xfree (a);
@@ -406,6 +445,757 @@ stap_get_probe_argument_count (const struct stap_probe *probe)
   return probe->parsed_args->n_args;
 }
 
+#define REG_NAME_MAX_SIZE 20
+
+#if 0
+
+static struct value *
+stap_get_register_value (char **s)
+{
+}
+
+static struct value *
+stap_evaluate_unary_op (char **unary_ptr)
+{
+  struct value *tmp_res = NULL;
+  char *s = *unary_ptr;
+  char sign = *s;
+
+  gdb_assert (*s == '+' || *s == '-');
+  ++s;
+  ep_skip_leading_whitespace (&s);
+
+  if (isdigit (*s))
+    {
+      int number = (int) strtol (s, &s, 0);
+
+      tmp_res
+	= value_from_longest (builtin_type (gdbarch)->builtin_int,
+			      number);
+    }
+  else if (*s == '%')
+    tmp_res = stap_get_register_value (&s);
+
+  if (tmp_res && sign == '-')
+    tmp_res = value_neg (tmp_res);
+
+  ep_skip_leading_whitespace (&s);
+
+  *unary_ptr = s;
+
+  return tmp_res;
+}
+
+static enum exp_opcode
+stap_binary_expr_opcode (char **s)
+{
+  switch (**s)
+    {
+    case '+':
+      *s += 1;
+      return BINOP_ADD;
+
+    case '-':
+      *s += 1;
+      return BINOP_SUB;
+
+    case '*':
+      *s += 1;
+      return BINOP_MUL;
+
+    case '/':
+      *s += 1;
+      return BINOP_DIV;
+
+    case '%':
+      *s += 1;
+      return BINOP_REM;
+
+    case '&':
+      *s += 1;
+      if (**s == '&')
+	return BINOP_LOGICAL_AND;
+      return BINOP_BITWISE_AND;
+
+    case '|':
+      *s += 1;
+      if (**s == '|')
+	return BINOP_LOGICAL_OR;
+      return BINOP_BITWISE_IOR;
+
+    default:
+      /*ERROR*/
+      return 0;
+    }
+}
+
+static void
+stap_evaluate_probe_argument_1 (struct objfile *objfile,
+				const struct stap_probe *probe,
+				struct frame_info *frame,
+				int n)
+{
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  char *s = (char *) probe->parsed_args->arg[n].arg_str;
+  struct value *final_res = NULL;
+  enum
+    {
+      EVAL_INIT,
+      EVAL_INDIRECT_REG,
+      EVAL_REGISTER,
+      EVAL_PAREN,
+      EVAL_UNOP,
+      EVAL_BINOP,
+    } eval_arg_state;
+
+  eval_arg_state = EVAL_INIT;
+
+  probe->parsed_args->arg[n].val = NULL;
+
+  while (*s)
+    {
+      switch (eval_arg_state)
+	{
+	  /* Ideia: Fazer um parser que dê conta de exprs.
+
+	     Por ex: -2+(4-(23+3))
+
+	     a ideia eh pegar primeiro o -, ver que eh unario,
+	     criar um value pro -2, depois ver o + (sem consumir),
+	     chamar uma fcao pra avaliar a segunda parte do binario,
+	     depois chamar uma fcao pra avaliar
+	     parenteses, depois pegar o 4, ver que eh binario e salvar
+	     esse value, chamar fcao pra avaliar parent, ver que eh bin, avaliar
+	     e retornar o value, e ir retornando em cascata.  */
+
+	case EVAL_INIT:
+	  {
+	    switch (*s)
+	      {
+	      case '+': case '-':
+		eval_arg_state = EVAL_UNOP;
+		break;
+
+	      case '(':
+		if (s[1] == '%')
+		  eval_arg_state = EVAL_REGISTER;
+		else
+		  eval_arg_state = EVAL_PAREN;
+		break;
+
+	      case '0': case '1': case '2': case '3': case '4':
+	      case '5': case '6': case '7': case '8': case '9':
+		eval_arg_state = EVAL_BINOP;
+		break;
+	      }
+	  }
+	break;
+
+	case EVAL_UNOP:
+	  {
+	    final_res = stap_evaluate_unary_op (&s);
+
+	    if (!final_res)
+	      ; /* ERROR */
+
+	    if (stap_is_binary_op (*s))
+	      eval_arg_state = EVAL_BINOP;
+//	    else if (*s == '(')
+//	      eval_arg_state = EVAL_PAREN;
+	    else if (*s)
+	      ; /* ERROR */
+	  }
+	break;
+
+	case EVAL_BINOP:
+	  {
+	    struct value *tmp_res = NULL;
+	    enum exp_opcode opcode;
+
+	    gdb_assert (stap_is_binary_op (s));
+
+	    opcode = stap_binary_expr_opcode (&s);
+
+	    ++s;
+	    ep_skip_leading_whitespace (&s);
+
+	    switch (*s)
+	      {
+	      case '+': case '-':
+		{
+		  tmp_res = stap_evaluate_unary_op (&s);
+
+		  if (!tmp_res)
+		    ; /*ERROR*/
+		}
+	      break;
+
+	      case '(':
+		{
+		  tmp_res = stap_evaluate_paren (&s);
+
+		  if (!tmp_res)
+		    ; /*ERROR*/
+		}
+	      break;
+	      }
+
+	    final_res = value_binop (final_res, tmp_res, opcode);
+
+	    ep_skip_leading_whitespace (&s);
+	  }
+	break;
+#if 0
+	case '+': case '-':
+	  {
+	    /* This is the beginning of an unary operator.  */
+	    struct value *unary_res;
+	    char c = *s;
+
+	    ++s;
+	    ep_skip_leading_whitespace (&s);
+	    if (isdigit (*s))
+	      {
+		int number = (int) strtol (s, &s, 0);
+		struct value *tmp_res;
+
+		if (c == '-')
+		  number *= -1;
+
+		tmp_res
+		  = value_from_longest (builtin_type (gdbarch)->builtin_int,
+					number);
+
+		ep_skip_leading_whitespace (&s);
+
+		if (*s == '(' && s[1] == '%')
+		  {
+		    struct value *regval;
+
+		    ++s;
+		    regval = stap_get_register_value (&s);
+
+		    /* Now indirect the register's value.  */
+		  }
+	      }
+	    else if (*s == '(')
+	      {
+		char *start = s;
+
+		ep_skip_leading_whitespace (&s);
+
+		if (*s == '%')
+		  stap_get_register_value (s);
+	      }
+	  }
+	break;
+
+	case '(':
+	  {
+	    ++s;
+
+	    if (*s == '%')
+	      {
+		char regname[REG_NAME_MAX_SIZE + 1];
+		const char *start;
+		int len, regnum;
+
+		/* This is a register name.  */
+		++s;
+		start = s;
+		while (isalnum (*s))
+		  ++s;
+
+		if (*s != ')')
+		  return;
+
+		len = s - start;
+
+		if (len >= REG_NAME_MAX_SIZE)
+		  return;
+
+		strncpy (regname, start, len);
+		regname[len] = '\0';
+
+		regnum = user_reg_map_name_to_regnum (gdbarch, regname, len);
+	      }
+	  }
+	break;
+#endif
+	}
+    }
+}
+#endif
+
+static int
+stap_get_operator_prec (enum exp_opcode op)
+{
+  switch (op)
+    {
+    case BINOP_LOGICAL_OR:
+      return 1;
+
+    case BINOP_LOGICAL_AND:
+      return 2;
+
+    case BINOP_ADD: case BINOP_SUB:
+    case BINOP_EQUAL: case BINOP_NOTEQUAL:
+    case BINOP_LESS: case BINOP_LEQ:
+    case BINOP_GTR: case BINOP_GEQ:
+      return 3;
+
+    case BINOP_BITWISE_IOR: case BINOP_BITWISE_AND:
+    case BINOP_BITWISE_XOR: case UNOP_LOGICAL_NOT:
+      return 4;
+
+    case BINOP_MUL: case BINOP_DIV: case BINOP_REM:
+    case BINOP_LSH: case BINOP_RSH:
+      return 5;
+
+    default:
+      return 0;
+    }
+}
+
+static int
+stap_get_opcode (char **s, enum exp_opcode *op)
+{
+  char c = **s;
+
+  *s += 1;
+
+  switch (c)
+    {
+    case '*':
+      *op = BINOP_MUL;
+      break;
+
+    case '/':
+      *op = BINOP_DIV;
+      break;
+
+    case '%':
+      {
+	if (isalpha (**s))
+	  /* Dealing with a register name.  */
+	  break;
+
+	*op = BINOP_REM;
+      }
+    break;
+
+    case '<':
+      *op = BINOP_LESS;
+      if (**s == '<')


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-03-14  5:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-14  5:26 [SCM] archer-sergiodj-stap: Initial implementation of the argument evaluation for probes sergiodj

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).