aboutsummaryrefslogtreecommitdiff
path: root/gdb/stap-probe.c
diff options
context:
space:
mode:
authorSergio Durigan Junior <sergiodj@redhat.com>2014-09-05 15:21:44 -0400
committerSergio Durigan Junior <sergiodj@redhat.com>2014-09-05 15:21:44 -0400
commit474ca4f6871d4addb7ce6a177245bce79c89550e (patch)
tree4b2dfcbe59886833ae57af8e009c0180f7c360d4 /gdb/stap-probe.c
parent514104634d0efd8955f7fd45cd509963e28212f6 (diff)
downloadgdb-474ca4f6871d4addb7ce6a177245bce79c89550e.zip
gdb-474ca4f6871d4addb7ce6a177245bce79c89550e.tar.gz
gdb-474ca4f6871d4addb7ce6a177245bce79c89550e.tar.bz2
Fix for PR gdb/17235: possible bug extracting systemtap probe operand
This patch is a fix to PR gdb/17235. The bug is about an unused variable that got declared and set during one of the parsing phases of an SDT probe's argument. I took the opportunity to rewrite some of the code to improve the parsing. The bug was actually a thinko, because what I wanted to do in the code was to discard the number on the string being parsed. During this portion, the code identifies that it is dealing with an expression that begins with a sign ('+', '-' or '~'). This means that the expression could be: - a numeric literal (e.g., '+5') - a register displacement (e.g., '-4(%rsp)') - a subexpression (e.g., '-(2*3)') So, after saving the sign and moving forward 1 char, now the code needs to know if there is a digit followed by a register displacement prefix operand (e.g., '(' on x86_64). If yes, then it is a register operation. If not, then it will be handled recursively, and the code will later apply the requested operation on the result (either a '+', a '-' or a '~'). With the bug, the code was correctly discarding the digit (though using strtol unnecessarily), but it wasn't properly dealing with subexpressions when the register indirection prefix was '(', like on x86_64. This patch also fixes this bug, and includes a testcase. It passes on x86_64 Fedora 20.
Diffstat (limited to 'gdb/stap-probe.c')
-rw-r--r--gdb/stap-probe.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index 84714b5..23202d7 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -753,9 +753,9 @@ stap_parse_single_operand (struct stap_parse_info *p)
if (*p->arg == '-' || *p->arg == '~' || *p->arg == '+')
{
char c = *p->arg;
- int number;
/* We use this variable to do a lookahead. */
const char *tmp = p->arg;
+ int has_digit = 0;
/* Skipping signal. */
++tmp;
@@ -772,26 +772,19 @@ stap_parse_single_operand (struct stap_parse_info *p)
if (p->inside_paren_p)
tmp = skip_spaces_const (tmp);
- if (isdigit (*tmp))
+ while (isdigit (*tmp))
{
- char *endp;
-
- number = strtol (tmp, &endp, 10);
- tmp = endp;
+ /* We skip the digit here because we are only interested in
+ knowing what kind of unary operation this is. The digit
+ will be handled by one of the functions that will be
+ called below ('stap_parse_argument_conditionally' or
+ 'stap_parse_register_operand'). */
+ ++tmp;
+ has_digit = 1;
}
- if (!stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
- {
- /* This is not a displacement. We skip the operator, and deal
- with it later. */
- ++p->arg;
- stap_parse_argument_conditionally (p);
- if (c == '-')
- write_exp_elt_opcode (&p->pstate, UNOP_NEG);
- else if (c == '~')
- write_exp_elt_opcode (&p->pstate, UNOP_COMPLEMENT);
- }
- else
+ if (has_digit && stap_is_register_indirection_prefix (gdbarch, tmp,
+ NULL))
{
/* If we are here, it means it is a displacement. The only
operations allowed here are `-' and `+'. */
@@ -801,6 +794,17 @@ stap_parse_single_operand (struct stap_parse_info *p)
stap_parse_register_operand (p);
}
+ else
+ {
+ /* This is not a displacement. We skip the operator, and
+ deal with it when the recursion returns. */
+ ++p->arg;
+ stap_parse_argument_conditionally (p);
+ if (c == '-')
+ write_exp_elt_opcode (&p->pstate, UNOP_NEG);
+ else if (c == '~')
+ write_exp_elt_opcode (&p->pstate, UNOP_COMPLEMENT);
+ }
}
else if (isdigit (*p->arg))
{