public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-sergiodj-stap: Initial commit for the argument parsing stuff.
@ 2011-02-25  6:21 sergiodj
  0 siblings, 0 replies; only message in thread
From: sergiodj @ 2011-02-25  6:21 UTC (permalink / raw)
  To: archer-commits

The branch, archer-sergiodj-stap has been updated
       via  87b36e08466e835177114be74445d7ca94d3072c (commit)
      from  4b5b3ba9b4c57886aefdade01ffc39dead67c761 (commit)

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

- Log -----------------------------------------------------------------
commit 87b36e08466e835177114be74445d7ca94d3072c
Author: Sergio Durigan Junior <sergiodj@redhat.com>
Date:   Fri Feb 25 03:19:36 2011 -0300

    Initial commit for the argument parsing stuff.
    
    This commit still doesn't parse anything, but it has some code to deal
    with tokenization, and some support code for the parser.  It also has
    some "debug" statements that I obviously plan to remove soon.

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

Summary of changes:
 gdb/elfread.c    |   27 ++++-
 gdb/stap-probe.c |  405 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/stap-probe.h |    6 +
 3 files changed, 435 insertions(+), 3 deletions(-)

First 500 lines of diff:
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 674fac5..fdd69ff 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1157,6 +1157,11 @@ get_base_address (bfd *obfd)
   return base;
 }
 
+/* FIXME JUST FOR TESTING **/
+static int
+elf_get_probe_argument_count (struct objfile *objfile,
+			      const struct stap_probe *probe);
+
 static const struct stap_probe *
 elf_get_probes (struct objfile *objfile, int *num_probes)
 {
@@ -1214,17 +1219,33 @@ elf_get_probes (struct objfile *objfile, int *num_probes)
 
   *num_probes = probes_per_objfile->stap_num_probes;
 
+  /* FIXME : THIS IS JUST FOR TESTING */
+  elf_get_probe_argument_count (objfile, probes_per_objfile->probes);
+
   return ret;
 }
 
-#if 0
 static int
 elf_get_probe_argument_count (struct objfile *objfile,
 			      const struct stap_probe *probe)
 {
+  const char *pargs = probe->args;
+  int count = 0;
+
+  if (!pargs)
+    /* No arguments.  */
+    return 0;
+
+  /* Counting the arguments.  */
+  if (!stap_parse_probe_arguments (pargs, &count))
+    {
+      complaint (&symfile_complaints,
+		 _("Invalid arguments for probe `%s'."), probe->name);
+      return 0;
+    }
 
+  return count;
 }
-#endif
 
 static void
 elf_symfile_relocate_probe (struct objfile *objfile,
@@ -1261,7 +1282,7 @@ stap_probe_key_free (struct objfile *objfile, void *d)
 static const struct sym_probe_fns elf_probe_fns =
 {
   elf_get_probes,		/* sym_get_probes */
-  NULL,				/* sym_get_probe_argument_count */
+  elf_get_probe_argument_count,	/* sym_get_probe_argument_count */
   NULL,				/* 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 bef49c1..f05d859 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -33,6 +33,408 @@
 
 #include <ctype.h>
 
+
+/* Beginning of the parser code.
+
+   Systemtap probes can have argument string (in the form of assembly
+   code) "attached" to them.  In order to parser this string, we created
+   a recursive-descent parser based on GCC's parser.  */
+
+/* Lexer token table.
+   OP(name, string description): operator tokens
+   TK(name, string description): parser tokens.  */
+#define TOKEN_TABLE		    \
+  OP(EQ,		"=")	    \
+  OP(NOT,		"!")	    \
+  OP(GREATER,		">")	    \
+  OP(LESS,		"<")	    \
+  OP(GREATER_EQ,	">=")	    \
+  OP(LESS_EQ,		"<=")	    \
+  OP(EQ_EQ,		"==")	    \
+  OP(NOT_EQ,		"!=")	    \
+  OP(NOT_EQ2,		"<>")	    \
+  OP(OR,		"|")	    \
+  OP(AND,		"&")	    \
+  OP(OR_OR,		"||")	    \
+  OP(AND_AND,		"&&")	    \
+  OP(RSHIFT,		">>")	    \
+  OP(LSHIFT,		"<<")	    \
+  OP(PLUS,		"+")	    \
+  OP(MINUS,		"-")	    \
+  OP(MULT,		"*")	    \
+  OP(DIV,		"/")	    \
+  OP(MOD,		"%")	    \
+  OP(OPEN_PAREN,	"(")	    \
+  OP(CLOSE_PAREN,	")")	    \
+  OP(OPEN_SQUARE,	"[")	    \
+  OP(CLOSE_SQUARE,	"]")	    \
+  OP(AT_SIGN,		"@")	    \
+    TK(EOF,		NONE)
+
+#define OP(e, s) TTYPE_ ## e,
+#define TK(e, s) TTYPE_ ## e,
+
+typedef enum
+{
+  TOKEN_TABLE
+  N_TOKEN_TYPES
+} token_type;
+
+#undef OP
+#undef TK
+
+#define OP(e, s) "TTYPE_" # e,
+#define TK(e, s) "TTYPE_" # e,
+
+static const char *token_table_strings[(int) N_TOKEN_TYPES] =
+  {
+    TOKEN_TABLE
+  };
+
+#undef OP
+#undef TK
+
+static struct stap_token *EOF_token;
+
+typedef unsigned char token_value;
+
+struct stap_token
+{
+  token_type type;
+  token_value *value;
+};
+
+struct stap_token_list
+{
+  struct stap_token *token;
+  struct stap_token_list *next;
+};
+
+struct stap_parser_buffer
+{
+  /* The actual buffer holding the input.  */
+  const char *buf;
+
+  /* A pointer to the current lexer location.  */
+  const char *cur;
+};
+
+struct stap_lexer
+{
+  /* Buffer used for lexing.  */
+  struct stap_parser_buffer buffer;
+
+  /* The token stream.  */
+  struct stap_token_list *tokens;
+  struct stap_token_list *head;
+};
+
+struct stap_parser
+{
+  /* The lexer.  */
+  struct stap_lexer *lexer;
+};
+
+static struct stap_token *
+new_stap_token (void)
+{
+  struct stap_token *t
+    = (struct stap_token *) xcalloc (1, sizeof (struct stap_token));
+
+  return t;
+}
+
+static void
+stap_lexer_push_token (struct stap_lexer *lexer, struct stap_token *token)
+{
+  struct stap_token_list *new
+    = (struct stap_token_list *) xmalloc (sizeof (struct stap_token_list));
+
+  new->token = token;
+  new->next = NULL;
+
+  if (lexer->tokens == NULL)
+    {
+      lexer->tokens = new;
+      lexer->head = new;
+    }
+  else
+    {
+      struct stap_token_list *l;
+
+      for (l = lexer->tokens; l->next != NULL; l = l->next);
+
+      l->next = new;
+    }
+}
+
+static struct stap_token *
+stap_lexer_peek_token (const struct stap_lexer *lexer)
+{
+  if (lexer->tokens == NULL)
+    return EOF_token;
+
+  return lexer->tokens->token;
+}
+
+#if 0
+static struct stap_token *
+stap_lexer_consume_token (struct stap_lexer *lexer)
+{
+  struct stap_token_list *h = lexer->tokens;
+
+  lexer->tokens = h->next;
+
+  return h->token;
+}
+
+static int
+stap_lexer_next_token_is (struct stap_lexer *lexer, token_type type)
+{
+  return stap_lexer_peek_token (lexer)->type == type;
+}
+#endif
+
+static int
+stap_is_eof_token (struct stap_token *token)
+{
+  return token == EOF_token;
+}
+
+#define IF_NEXT_IS(CHAR, THEN_TYPE, ELSE_TYPE)	\
+  do {						\
+      result->type = ELSE_TYPE;			\
+      if (*lexer->buffer.cur == CHAR)		\
+	{					\
+	  ++lexer->buffer.cur;			\
+	  result->type = ELSE_TYPE;		\
+	}					\
+  } while (0)
+
+#define IF_NEXT_IS_ELSE_IF(CHAR_THEN, THEN_TYPE,	\
+			   CHAR_ELSE_IF, ELSE_IF_TYPE,	\
+			   ELSE_TYPE)			\
+  do {							\
+      result->type = ELSE_TYPE;				\
+      if (*lexer->buffer.cur == CHAR_THEN)		\
+	{						\
+	  ++lexer->buffer.cur;				\
+	  result->type = THEN_TYPE;			\
+	}						\
+      else if (*lexer->buffer.cur == CHAR_ELSE_IF)	\
+	{						\
+	  ++lexer->buffer.cur;				\
+	  result->type = ELSE_IF_TYPE;			\
+	}						\
+  } while (0)
+
+static struct stap_token *
+stap_lex_one_token (struct stap_lexer *lexer)
+{
+  char c;
+  struct stap_token *result = new_stap_token ();
+
+retry:
+  c = *lexer->buffer.cur++;
+
+  switch (c)
+    {
+    case ' ':
+    case '\t':
+    case '\n':
+      goto retry;
+
+    case '=':
+      IF_NEXT_IS ('=', TTYPE_EQ_EQ, TTYPE_EQ);
+      break;
+
+    case '!':
+      IF_NEXT_IS ('=', TTYPE_NOT_EQ, TTYPE_NOT);
+      break;
+
+    case '>':
+      IF_NEXT_IS_ELSE_IF ('=', TTYPE_GREATER_EQ,
+			  '>', TTYPE_RSHIFT,
+			  TTYPE_GREATER);
+      break;
+
+    case '<':
+      if (*lexer->buffer.cur == '=')
+	{
+	  ++lexer->buffer.cur;
+	  result->type = TTYPE_LESS_EQ;
+	}
+      else if (*lexer->buffer.cur == '>')
+	{
+	  ++lexer->buffer.cur;
+	  result->type = TTYPE_NOT_EQ2;
+	}
+      else if (*lexer->buffer.cur == '<')
+	{
+	  ++lexer->buffer.cur;
+	  result->type = TTYPE_LSHIFT;
+	}
+      else
+	result->type = TTYPE_LESS;
+      break;
+
+    case '|':
+      IF_NEXT_IS ('|', TTYPE_OR_OR, TTYPE_OR);
+      break;
+
+    case '&':
+      IF_NEXT_IS ('&', TTYPE_AND_AND, TTYPE_AND);
+      break;
+
+    case '+':
+      result->type = TTYPE_PLUS;
+      break;
+
+    case '-':
+      result->type = TTYPE_MINUS;
+      break;
+
+    case '*':
+      result->type = TTYPE_MULT;
+      break;
+
+    case '/':
+      result->type = TTYPE_DIV;
+      break;
+
+    case '(':
+      result->type = TTYPE_OPEN_PAREN;
+      break;
+
+    case ')':
+      result->type = TTYPE_CLOSE_PAREN;
+      break;
+
+    case '[':
+      result->type = TTYPE_OPEN_SQUARE;
+      break;
+
+    case ']':
+      result->type = TTYPE_CLOSE_SQUARE;
+      break;
+
+    case '@':
+      result->type = TTYPE_AT_SIGN;
+      break;
+
+    case 0:
+      --lexer->buffer.cur;
+      xfree (result);
+      result = EOF_token;
+      break;
+
+    default:
+      xfree (result);
+      return NULL;
+    }
+
+  return result;
+}
+
+static void
+stap_lex (struct stap_lexer *lexer)
+{
+  struct stap_token *token;
+
+  do
+    {
+      token = stap_lex_one_token (lexer);
+      stap_lexer_push_token (lexer, token);
+    }
+  while (!stap_is_eof_token (token));
+}
+
+static struct stap_parser *
+new_stap_parser (const char *start)
+{
+  struct stap_parser *parser
+    = (struct stap_parser *) xcalloc (1, sizeof (struct stap_parser));
+
+  parser->lexer
+    = (struct stap_lexer *) xcalloc (1, sizeof (struct stap_lexer));
+
+  parser->lexer->buffer.buf = start;
+  parser->lexer->buffer.cur = parser->lexer->buffer.buf;
+
+  return parser;
+}
+
+static void
+free_stap_parser (void *parser_ptr)
+{
+  struct stap_parser *p = (struct stap_parser *) parser_ptr;
+
+  /* FIXME: Free tokens.  */
+
+  xfree (p->lexer);
+  xfree (p);
+}
+
+static void
+stap_dump_token_stream (const struct stap_lexer *lexer)
+{
+  if (!lexer->tokens)
+    printf ("EMPTY!!!!!\n");
+  else
+    {
+      int i;
+      struct stap_token_list *l;
+
+      for (i = 0, l = lexer->tokens; l; l = l->next)
+	{
+	  struct stap_token *t = l->token;
+
+	  printf ("\t[%d] token = %s, value = \"%s\"\n", i++,
+		  token_table_strings[(int) t->type], t->value);
+	}
+    }
+}
+
+int
+stap_parse_probe_arguments (const char *args, int *n_args)
+{
+  struct stap_parser *parser;
+  struct cleanup *c;
+
+  *n_args = 0;
+
+  /* No arguments.  */
+  if (!args || !*args)
+    /* The parsing has not failed, so there is no need to return
+       zero here.  */
+    return 1;
+
+  parser = new_stap_parser (args);
+  c = make_cleanup (free_stap_parser, parser);
+
+  stap_lex (parser->lexer);
+
+  stap_dump_token_stream (parser->lexer);
+
+  /* FIXME: This will probably return an struct expression.  */
+//  stap_parse_expression (parser);
+
+  if (!stap_is_eof_token (stap_lexer_peek_token (parser->lexer)))
+    {
+      /* Error.  */
+      /* FIXME: Maybe we should be more verbose at reporting error
+	 situations.  Printing a message would be good.  complaint()??  */
+      do_cleanups (c);
+      return 0;
+    }
+
+  return 1;
+}
+
+
+/* End of the parser code.  */
+
+
 static void
 ep_skip_leading_whitespace (char **s)
 {
@@ -524,6 +926,9 @@ static const struct internalvar_funcs probe_funcs =
 void
 _initialize_stap_probe (void)
 {
+  EOF_token = new_stap_token ();
+  EOF_token->type = TTYPE_EOF;
+
   add_info ("probes", info_probes_command, _("\
 Show available static probes.\n\
 Usage: info probes [PROVIDER [NAME [OBJECT]]]\n\
diff --git a/gdb/stap-probe.h b/gdb/stap-probe.h
index 1213d8e..dfbe786 100644
--- a/gdb/stap-probe.h
+++ b/gdb/stap-probe.h
@@ -62,4 +62,10 @@ extern const struct stap_probe *find_probe_in_objfile (struct objfile *objfile,
 extern const struct stap_probe *find_probe_by_pc (CORE_ADDR pc,
 						  struct objfile **objfile_out);
 
+/* Give the string ARG, which represents a probe's arguments, this
+   function will parse it and return the number of arguments found
+   in *N_ARGS.  It returns 1 if the parsing was completed successfully,
+   or 0 if there is an error.  */
+extern int stap_parse_probe_arguments (const char *args, int *n_args);
+
 #endif /* !defined (STAP_PROBE_H) */


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


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

only message in thread, other threads:[~2011-02-25  6:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-25  6:21 [SCM] archer-sergiodj-stap: Initial commit for the argument parsing stuff 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).