public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] archer-sergiodj-stap: Lots of comments, small fixes.
@ 2011-03-17 6:51 sergiodj
0 siblings, 0 replies; only message in thread
From: sergiodj @ 2011-03-17 6:51 UTC (permalink / raw)
To: archer-commits
The branch, archer-sergiodj-stap has been updated
via d909b1c3af91be2fe436ed45662a8301cbd6c86d (commit)
from 0d92265d7094189e7d0719f3bec48d6dd7697097 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit d909b1c3af91be2fe436ed45662a8301cbd6c86d
Author: Sergio Durigan Junior <sergiodj@redhat.com>
Date: Thu Mar 17 03:50:21 2011 -0300
Lots of comments, small fixes.
This commit adds lots of comments to the evaluation functions,
explaining how they work and why they do what they do. I also found an
issue with some specific expressions, and fixed it.
-----------------------------------------------------------------------
Summary of changes:
gdb/stap-probe.c | 212 +++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 170 insertions(+), 42 deletions(-)
First 500 lines of diff:
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index f3c4f33..dd86b62 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -646,11 +646,11 @@ stap_is_operator (char *s)
|| op == '|' || op == '&' || op == '%' || op == '=');
}
-/* Given **P, this function fetches the value of the register whose
- name starts in **P. It also applies any register displacements
- (e.g., `-4(%eax)'), and indirects the contents of the register
- (e.g., `(%eax)'). It returns RET if the operation has succeeded,
- or NULL otherwise. */
+/* This function fetches the value of the register whose
+ name starts in the expression buffer. It also applies any register
+ displacements (e.g., `-4(%eax)'), and indirects the contents of the
+ register (e.g., `(%eax)'). It returns RET if the operation has succeeded,
+ or calls `error' otherwise. */
static struct value *
stap_fetch_reg_value (struct stap_evaluation_info *eval_info,
@@ -667,8 +667,16 @@ stap_fetch_reg_value (struct stap_evaluation_info *eval_info,
struct value *ret;
if (!s || !*s)
- return NULL;
+ /* The function which called us did not check if the expression
+ buffer was empty. */
+ internal_error (__FILE__, __LINE__,
+ _("Invalid call to function."));
+
+ /* Valid register name on x86 platforms are:
+
+ [paren]%{a-z0-9}[paren]
+ Let's check for that here. */
if (*s == '(')
{
++s;
@@ -677,6 +685,8 @@ stap_fetch_reg_value (struct stap_evaluation_info *eval_info,
error (_("Invalid register name on expression `%s'."),
eval_info->saved_expr);
++s;
+ /* The presence of parenthesis means that we want to indirect
+ the register. */
indirect_p = 1;
}
else if (*s == '%')
@@ -695,6 +705,7 @@ stap_fetch_reg_value (struct stap_evaluation_info *eval_info,
error (_("Trying to apply displacement without indirecting register "
"on expression `%s'."), eval_info->saved_expr);
+ /* Ok, let's calculate the size of the register name. */
start = s;
while (isalnum (*s))
++s;
@@ -705,19 +716,31 @@ stap_fetch_reg_value (struct stap_evaluation_info *eval_info,
++s;
if (len >= REG_NAME_MAX_SIZE)
- return NULL;
+ error (_("The register name is greater than the supported size "
+ "on expression `%s'."), eval_info->saved_expr);
strncpy (regname, start, len);
regname[len] = '\0';
+ /* Translating the register name into the corresponding number. */
regnum = user_reg_map_name_to_regnum (gdbarch, regname, len);
+ if (regnum == -1)
+ error (_("Invalid register name `%s' on expression `%s'."),
+ regname, eval_info->saved_expr);
+
ret = value_of_register (regnum, frame);
if (indirect_p)
{
struct type *t = NULL;
+ /* If the user has specified that the register must be indirected,
+ we should know what's the correct type to cast it before making
+ the indirection. This type corresponds to the bitness specified
+ before the `@' sign on the argument string, or it defaults to
+ `unsigned long' if the `@' were not present. */
+
switch (bitness)
{
case STAP_ARG_BITNESS_UNDEFINED:
@@ -758,13 +781,23 @@ stap_fetch_reg_value (struct stap_evaluation_info *eval_info,
ret = value_ind (ret);
}
+ /* Updating the expression buffer pointer, because we have made
+ some modifications to it before. */
eval_info->exp_buf = s;
return ret;
}
+/* This function tries to evaluate a single operand of the expression.
+
+ Single operands can be:
+
+ - unary operators `-' and `~';
+ - integer constants (beginning with `$');
+ - register access, with/out displacement and indirection. */
+
static struct value *
-stap_parse_single_operand (struct stap_evaluation_info *eval_info)
+stap_evaluate_single_operand (struct stap_evaluation_info *eval_info)
{
struct gdbarch *gdbarch = eval_info->gdbarch;
struct frame_info *frame = eval_info->frame;
@@ -777,6 +810,21 @@ stap_parse_single_operand (struct stap_evaluation_info *eval_info)
{
char c = *eval_info->exp_buf;
+ /* This is a binary operator (either `-' or `~').
+
+ If it is followed by a parenthesis, and this parenthesis
+ is NOT followed by a `%', then we are dealing with an expression
+ like `-(2 + 3)' or `~(2 + 3)'. We just have to treat separately
+ and return the result after applying the operation (`-' or `~').
+
+ If it is followed by a digit, then we have only one choice: it
+ is a displacement argument for a register access, like
+ `-4(%eax)'. It also means that the operator can *only* be `-',
+ and the characters immediately after the number *must* be `(%'.
+
+ If it is followed by a `$', then it is an integer constant, and
+ we should apply the correct operation to it. */
+
++eval_info->exp_buf;
eval_info->exp_buf = skip_spaces (eval_info->exp_buf);
if (*eval_info->exp_buf
@@ -784,10 +832,12 @@ stap_parse_single_operand (struct stap_evaluation_info *eval_info)
&& eval_info->exp_buf[1] != '%')
{
struct value *tmp_res;
- /* We're not dealing with a register name, but with an
- expression like:
- `-(2)' */
+ /* We're not dealing with a register name, but with an
+ expression like `-(2 + 3)' or `~(2 + 3)'. We first have
+ to evaluate the right side of the expression (i.e., the
+ parenthesis), and then apply the specified operation
+ (either `-' or `~') to it. */
tmp_res = stap_evaluate_probe_argument_2 (eval_info,
/*lhs=*/NULL,
/*prec=*/0);
@@ -797,38 +847,59 @@ stap_parse_single_operand (struct stap_evaluation_info *eval_info)
else
res = value_complement (tmp_res);
}
- else
+ else if (isdigit (*eval_info->exp_buf))
{
- if (isdigit (*eval_info->exp_buf))
- {
- int number = strtol (eval_info->exp_buf,
- &eval_info->exp_buf, 0);
-
- eval_info->exp_buf = skip_spaces (eval_info->exp_buf);
+ int number;
+
+ /* This is a number, so it MUST be a register displacement.
+ The only operator allowed here is `-', it MUST be
+ followed by a number, and the number MUST be followed by
+ `(%'. */
+ if (c != '-')
+ error (_("Invalid operator `%c' for register displacement "
+ "on expression `%s'."), c, eval_info->saved_expr);
+
+ number = strtol (eval_info->exp_buf,
+ &eval_info->exp_buf, 0) * -1;
+
+ if (!*eval_info->exp_buf
+ || *eval_info->exp_buf != '('
+ || (*eval_info->exp_buf == '('
+ && eval_info->exp_buf[1] != '%'))
+ error (_("Invalid method of indirecting a register on "
+ "expression `%s'."), eval_info->saved_expr);
+
+ res
+ = value_from_longest (builtin_type (gdbarch)->builtin_int,
+ number);
+
+ res = stap_fetch_reg_value (eval_info, res);
+ }
+ else if (*eval_info->exp_buf == '$')
+ {
+ int number;
- res
- = value_from_longest (builtin_type (gdbarch)->builtin_int,
- number);
+ /* Last case. We are dealing with an integer constant, so
+ we must read it and then apply the necessary operation,
+ either `-' or `~'. */
+ ++eval_info->exp_buf;
+ number = strtol (eval_info->exp_buf,
+ &eval_info->exp_buf, 0);
- if (c == '-')
- res = value_neg (res);
- else
- res = value_complement (res);
+ res
+ = value_from_longest (builtin_type (gdbarch)->builtin_int,
+ number);
- if (!*eval_info->exp_buf
- || stap_is_operator (eval_info->exp_buf))
- break;
- else if (*eval_info->exp_buf == '('
- && eval_info->exp_buf[1] == '%')
- {
- if (c == '~')
- error (_("Invalid operator `%c' on expression `%s'."),
- c, eval_info->saved_expr);
+ eval_info->exp_buf = skip_spaces (eval_info->exp_buf);
- res = stap_fetch_reg_value (eval_info, res);
- }
- }
+ if (c == '-')
+ res = value_neg (res);
+ else
+ res = value_complement (res);
}
+ else
+ error (_("Invalid operand to unary operator `%c' on "
+ "expression `%s'."), c, eval_info->saved_expr);
}
break;
@@ -837,6 +908,8 @@ stap_parse_single_operand (struct stap_evaluation_info *eval_info)
{
int number = strtol (eval_info->exp_buf, &eval_info->exp_buf, 0);
+ /* This is a register displacement with a positive value. We read
+ the number, and then check for the mandatory `(%' part. */
if (!*eval_info->exp_buf
|| !(*eval_info->exp_buf == '('
&& eval_info->exp_buf[1] == '%'))
@@ -854,6 +927,8 @@ stap_parse_single_operand (struct stap_evaluation_info *eval_info)
{
int number;
+ /* This is an integer constant. We just have to read the number
+ and return it. */
++eval_info->exp_buf;
eval_info->exp_buf = skip_spaces (eval_info->exp_buf);
@@ -868,6 +943,7 @@ stap_parse_single_operand (struct stap_evaluation_info *eval_info)
case '(': case '%':
{
+ /* Register access, with or without indirection. */
res = stap_fetch_reg_value (eval_info, /*displacement=*/NULL);
}
break;
@@ -882,6 +958,14 @@ stap_parse_single_operand (struct stap_evaluation_info *eval_info)
return res;
}
+/* This function is responsible for checking the necessary type of evaluation
+ depending on what is the next "thing" in the buffer. Valid values are:
+
+ - Unary operators;
+ - Integer constants;
+ - Register displacement, indirection, and direct access;
+ - Parenthesized operand. */
+
static struct value *
stap_evaluate_conditionally (struct stap_evaluation_info *eval_info)
{
@@ -893,9 +977,13 @@ stap_evaluate_conditionally (struct stap_evaluation_info *eval_info)
|| (isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement. */
|| (*s == '(' && s[1] == '%') /* Register indirection. */
|| (*s == '%' && isalpha (s[1]))) /* Register value. */
- ret = stap_parse_single_operand (eval_info);
+ /* This is a single operand, so just evaluate it and return. */
+ ret = stap_evaluate_single_operand (eval_info);
else if (*s == '(')
{
+ /* We are dealing with a parenthesized operand. It means we
+ have to evaluate it as it was a separate expression, without
+ left-side or precedence. */
++eval_info->exp_buf;
eval_info->exp_buf = skip_spaces (eval_info->exp_buf);
@@ -921,16 +1009,32 @@ stap_evaluate_probe_argument_2 (struct stap_evaluation_info *eval_info,
{
struct value *rhs = NULL;
+ /* This is an operator-precedence parser and evaluator.
+
+ We work with left- and right-sides of expressions, and
+ evaluate them depending on the precedence of the operators
+ we find. */
+
eval_info->exp_buf = skip_spaces (eval_info->exp_buf);
if (!lhs)
- /* We have to evaluate the left side of this expression. */
+ /* We were called without a left-side, either because this is the
+ first call, or because we were called to evaluate a parenthesized
+ expression. It doesn't really matter; we have to evaluate the
+ left-side in order to continue the process. */
lhs = stap_evaluate_conditionally (eval_info);
+ /* Start to evaluate the right-side, and to "join" left and right sides
+ depending on the operation specified.
+
+ This loop shall continue until we run out of characters in the input,
+ or until we find a close-parenthesis, which means that we've reached
+ the end of a sub-expression. */
while (eval_info->exp_buf
&& *eval_info->exp_buf
&& *eval_info->exp_buf != ')')
{
+ char *tmp_exp_buf;
enum exp_opcode opcode;
int cur_prec;
@@ -938,38 +1042,61 @@ stap_evaluate_probe_argument_2 (struct stap_evaluation_info *eval_info,
error (_("Invalid operator `%c' on expression `%s'."),
*eval_info->exp_buf, eval_info->saved_expr);
- stap_get_opcode (&eval_info->exp_buf, &opcode);
+ /* We have to save the current value of the expression buffer because
+ the `stap_get_opcode' modifies it in order to get the current
+ operator. If this operator's precedence is lower than PREC, we
+ should return and not advance the expression buffer pointer. */
+ tmp_exp_buf = eval_info->exp_buf;
+ stap_get_opcode (&tmp_exp_buf, &opcode);
cur_prec = stap_get_operator_prec (opcode);
if (cur_prec < prec)
+ /* If the precedence of the operator that we are seeing now is
+ lower than the precedence of the first operator seen before
+ this evaluation process began, it means we should stop evaluating
+ and return. */
break;
+ eval_info->exp_buf = tmp_exp_buf;
eval_info->exp_buf = skip_spaces (eval_info->exp_buf);
+ /* Evaluate the right-side of the expression. */
rhs = stap_evaluate_conditionally (eval_info);
+ /* While we still have operators, try to evaluate another
+ right-side, but using the current right-side as a left-side. */
while (*eval_info->exp_buf
&& stap_is_operator (eval_info->exp_buf))
{
enum exp_opcode lookahead_opcode;
int lookahead_prec;
- stap_get_opcode (&eval_info->exp_buf, &lookahead_opcode);
+ /* Saving the current expression buffer position. The explanation
+ is the same as above. */
+ tmp_exp_buf = eval_info->exp_buf;
+ stap_get_opcode (&tmp_exp_buf, &lookahead_opcode);
lookahead_prec = stap_get_operator_prec (lookahead_opcode);
if (lookahead_prec <= prec)
+ /* If we are dealing with an operator whose precedence is lower
+ than the first one, just abandon the attempt. */
break;
rhs = stap_evaluate_probe_argument_2 (eval_info,
rhs, lookahead_prec);
}
+ /* Now, "join" both left and right sides into one left-side, using
+ the specified operator. */
lhs = value_binop (lhs, rhs, opcode);
}
return lhs;
}
+/* This function fills the necessary arguments for the evaluation function
+ to work. */
+
#define TEST 0
static struct value *
stap_evaluate_probe_argument_1 (struct objfile *objfile,
@@ -983,12 +1110,13 @@ stap_evaluate_probe_argument_1 (struct objfile *objfile,
struct value *res, *vs[4];
#if TEST /*TESTING*/
const char *args[4] = { "$2",
- "$2 + $3",
+ "$2 + $3 * $4 + $5",
"-($2 + $3)",
"(~($2) * $3) / ($1 + $1)" };
int i;
#endif
+ /* Filling necessary information for evaluation function. */
eval_info.saved_expr = s;
eval_info.exp_buf = s;
eval_info.gdbarch = get_objfile_arch (objfile);
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-03-17 6:51 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-17 6:51 [SCM] archer-sergiodj-stap: Lots of comments, small fixes 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).