[patch] Watchpoints: support for thread <thread_num> parameters

Luis Machado
2007-08-16T21:03:19Z

[-- Attachment #1: Type: text/plain, Size: 1131 bytes --]

Hi,

This is a first try on the implementation of the additional "thread
<thread_num>" parameter for the watchpoint command in order to make GDB
stop only on specific threads when a watchpoint is triggered.

Basically i started parsing the arguments backwards, trying to locate
tokens that identify a "thread <thread_num>" command. After that i hand
all the left parameters over to the default expression parser.

Differently than the breakpoint command, the "thread <thread_num>"
parameter for watchpoints is located at the end of the argument list due
to ambiguities that would arise when putting that parameter in between
expressions, since those could contain strings that would require a more
complex parser with context capabilities, thus being able to figure out
what is part of an expression and what is not.

What do you think? Looking forward to ideas and suggestions to improve
it. We could change the location of the "thread <thread_num>" parameter
for breakpoints as well, in order to keep it standard.

Best regards,

--
Luis Machado
Software Engineer
IBM Linux Technology Center
e-mail: luisgpm@linux.vnet.ibm.com

[-- Attachment #2: watch_thread_param.diff --]
[-- Type: text/x-patch, Size: 3022 bytes --]

2007-08-16 Luis Machado <luisgpm@linux.vnet.ibm.com>

* breakpoint.c: (watch_command_1): Parse additional optional
"thread" parameter to the watchpoint command and set the
"thread" member of the breakpoint struct.

Index: gdb/breakpoint.c
===================================================================
--- gdb.orig/breakpoint.c 2007-08-16 12:37:20.000000000 -0700
+++ gdb/breakpoint.c 2007-08-16 13:45:26.000000000 -0700
@@ -5834,10 +5834,70 @@
int i, other_type_used, target_resources_ok = 0;
enum bptype bp_type;
int mem_cnt = 0;
+ int thread = -1;

init_sal (&sal); /* initialize to zeroes */

- /* Parse arguments. */
+ /* Make sure that we actually have parameters to parse */
+ if (arg != NULL && strlen (arg) >= 1)
+ {
+ toklen = strlen (arg); /* Size of argument list */
+
+ /* Points tok to the end of the argument list */
+ tok = arg + toklen;
+
+ /* Go backwards in the parameters list. Skip the last parameter.
+ If we're expecting a 'thread <thread_num>' parameter, this should
+ be the thread identifier. */
+ while (strlen (tok) < toklen && (*tok == ' ' || *tok == '\t'))
+ tok--;
+ while (strlen (tok) < toklen && (*tok != ' ' && *tok != '\t'))
+ tok--;
+
+ /* Go backwards in the parameters list. Skip one more parameter.
+ If we're expecting a 'thread <thread_num>' parameter, we should
+ reach a "thread" token. */
+ while (strlen (tok) < toklen && (*tok == ' ' || *tok == '\t'))
+ tok--;
+
+ end_tok = tok;
+
+ while (strlen (tok) < toklen && (*tok != ' ' && *tok != '\t'))
+ tok--;
+
+ /* Move the pointer forward to skip the whitespace and
+ calculate the length of the token. */
+ tok++;
+ toklen = end_tok - tok;
+
+ if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
+ {
+ /* At this point we've found a "thread" token, which means
+ the user is trying to set a watchpoint that triggers
+ only in a specific thread. */
+ char *tmptok;
+ char *thread_token;
+
+ /* Extract the thread ID from the next token. */
+ thread_token = tok;
+ tok = end_tok + 1;
+ tmptok = tok;
+ thread = strtol (tok, &tok, 0);
+
+ if (tok == tmptok)
+ error (_("Incorrect parameter after thread keyword."));
+
+ if (!valid_thread_id (thread))
+ error (_("Unknown thread %d."), thread);
+
+ /* truncate the string and get rid of the thread <thread_num>
+ parameter before the parameter list is parsed by the
+ evaluate_expression() function. */
+ *thread_token = '\0';
+ }
+ }
+
+ /* Parse the rest of the arguments. */
innermost_block = NULL;
exp_start = arg;
exp = parse_exp_1 (&arg, 0, 0);
@@ -5921,6 +5981,7 @@
b = set_raw_breakpoint (sal, bp_type);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
+ b->thread = thread;
b->disposition = disp_donttouch;
b->exp = exp;
b->exp_valid_block = exp_valid_block;