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