diff options
author | Pedro Alves <palves@redhat.com> | 2016-01-15 21:46:23 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2016-01-15 21:46:23 +0000 |
commit | 71ef29a86b252a4780517fc9b2bf9f7d3dd2d991 (patch) | |
tree | 6906fc0e6297b079fa951857e19f15aefd7143cc | |
parent | 3f5b7598805c8253c43c989a540a2408c8b685ad (diff) | |
download | gdb-71ef29a86b252a4780517fc9b2bf9f7d3dd2d991.zip gdb-71ef29a86b252a4780517fc9b2bf9f7d3dd2d991.tar.gz gdb-71ef29a86b252a4780517fc9b2bf9f7d3dd2d991.tar.bz2 |
Star wildcard ranges (e.g., "info thread 2.*")
Add support for specifying "all threads of inferior N", by writing "*"
as thread number/range in thread ID lists.
E.g., "info threads 2.*" or "thread apply 2.* bt".
gdb/ChangeLog:
2016-01-15 Pedro Alves <palves@redhat.com>
* NEWS: Mention star wildcard ranges.
* cli/cli-utils.c (get_number_or_range): Check state->in_range first.
(number_range_setup_range): New function.
* cli/cli-utils.h (number_range_setup_range): New declaration.
* thread.c (thread_apply_command): Support star TID ranges.
* tid-parse.c (tid_range_parser_finished)
(tid_range_parser_string, tid_range_parser_skip)
(get_tid_or_range, get_tid_or_range): Handle
TID_RANGE_STATE_STAR_RANGE.
(tid_range_parser_star_range): New function.
* tid-parse.h (enum tid_range_state) <TID_RANGE_STATE_STAR_RANGE>:
New value.
(tid_range_parser_star_range): New declaration.
gdb/doc/ChangeLog:
2016-01-15 Pedro Alves <palves@redhat.com>
* gdb.texinfo (Threads) <thread ID lists>: Document star ranges.
gdb/testsuite/ChangeLog:
2016-01-15 Pedro Alves <palves@redhat.com>
* gdb.multi/tids.exp: Test star wildcard ranges.
-rw-r--r-- | gdb/ChangeLog | 16 | ||||
-rw-r--r-- | gdb/NEWS | 6 | ||||
-rw-r--r-- | gdb/cli/cli-utils.c | 47 | ||||
-rw-r--r-- | gdb/cli/cli-utils.h | 8 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 39 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.multi/tids.exp | 36 | ||||
-rw-r--r-- | gdb/thread.c | 20 | ||||
-rw-r--r-- | gdb/tid-parse.c | 28 | ||||
-rw-r--r-- | gdb/tid-parse.h | 7 |
11 files changed, 185 insertions, 30 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 99245d7..034e4f9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,21 @@ 2016-01-15 Pedro Alves <palves@redhat.com> + * NEWS: Mention star wildcard ranges. + * cli/cli-utils.c (get_number_or_range): Check state->in_range first. + (number_range_setup_range): New function. + * cli/cli-utils.h (number_range_setup_range): New declaration. + * thread.c (thread_apply_command): Support star TID ranges. + * tid-parse.c (tid_range_parser_finished) + (tid_range_parser_string, tid_range_parser_skip) + (get_tid_or_range, get_tid_or_range): Handle + TID_RANGE_STATE_STAR_RANGE. + (tid_range_parser_star_range): New function. + * tid-parse.h (enum tid_range_state) <TID_RANGE_STATE_STAR_RANGE>: + New value. + (tid_range_parser_star_range): New declaration. + +2016-01-15 Pedro Alves <palves@redhat.com> + * thread.c (thread_apply_command): Use the tid range parser to advance past the thread ID list. * tid-parse.c (get_positive_number_trailer): New function. @@ -34,6 +34,12 @@ [Switching to thread 2.1 (Thread 0x7ffff7fc2740 (LWP 8157))] (running) (gdb) +* In commands that accept a list of thread IDs, you can now refer to + all threads of an inferior using a star wildcard. GDB accepts + "INF_NUM.*", to refer to all threads of inferior INF_NUM, and "*" to + refer to all threads of the current inferior. For example, "info + threads 2.*". + * You can use "info threads -gid" to display the global thread ID of all threads. diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c index a68b67d..0946db0 100644 --- a/gdb/cli/cli-utils.c +++ b/gdb/cli/cli-utils.c @@ -134,7 +134,21 @@ init_number_or_range (struct get_number_or_range_state *state, int get_number_or_range (struct get_number_or_range_state *state) { - if (*state->string != '-') + if (state->in_range) + { + /* All number-parsing has already been done. Return the next + integer value (one greater than the saved previous value). + Do not advance the token pointer until the end of range is + reached. */ + + if (++state->last_retval == state->end_value) + { + /* End of range reached; advance token pointer. */ + state->string = state->end_ptr; + state->in_range = 0; + } + } + else if (*state->string != '-') { /* Default case: state->string is pointing either to a solo number, or to the first number of a range. */ @@ -165,27 +179,26 @@ get_number_or_range (struct get_number_or_range_state *state) state->in_range = 1; } } - else if (! state->in_range) - error (_("negative value")); else - { - /* state->string points to the '-' that betokens a range. All - number-parsing has already been done. Return the next - integer value (one greater than the saved previous value). - Do not advance the token pointer until the end of range - is reached. */ - - if (++state->last_retval == state->end_value) - { - /* End of range reached; advance token pointer. */ - state->string = state->end_ptr; - state->in_range = 0; - } - } + error (_("negative value")); state->finished = *state->string == '\0'; return state->last_retval; } +/* See documentation in cli-utils.h. */ + +void +number_range_setup_range (struct get_number_or_range_state *state, + int start_value, int end_value, const char *end_ptr) +{ + gdb_assert (start_value > 0); + + state->in_range = 1; + state->end_ptr = end_ptr; + state->last_retval = start_value - 1; + state->end_value = end_value; +} + /* Accept a number and a string-form list of numbers such as is accepted by get_number_or_range. Return TRUE if the number is in the list. diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h index ebf11f2..a31fff5 100644 --- a/gdb/cli/cli-utils.h +++ b/gdb/cli/cli-utils.h @@ -90,6 +90,14 @@ extern void init_number_or_range (struct get_number_or_range_state *state, extern int get_number_or_range (struct get_number_or_range_state *state); +/* Setups STATE such that get_number_or_range returns numbers in range + START_VALUE to END_VALUE. When get_number_or_range returns + END_VALUE, the STATE string is advanced to END_PTR. */ + +extern void number_range_setup_range (struct get_number_or_range_state *state, + int start_value, int end_value, + const char *end_ptr); + /* Accept a number and a string-form list of numbers such as is accepted by get_number_or_range. Return TRUE if the number is in the list. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 4b59057..db280b9 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2016-01-15 Pedro Alves <palves@redhat.com> + + * gdb.texinfo (Threads) <thread ID lists>: Document star ranges. + 2016-01-13 Pedro Alves <palves@redhat.com> * gdb.texinfo (Threads): Document the $_gthread convenience diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 7da31c8..a08a196 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -2912,16 +2912,35 @@ of inferior 1, the initial inferior. @anchor{thread ID lists} @cindex thread ID lists Some commands accept a space-separated @dfn{thread ID list} as -argument. A list element can be a thread ID as shown in the first -field of the @samp{info threads} display, with or without an inferior -qualifier (e.g., @samp{2.1} or @samp{1}); or can be a range of thread -numbers, again with or without an inferior qualifier, as in -@var{inf1}.@var{thr1}-@var{thr2} or @var{thr1}-@var{thr2} (e.g., -@samp{1.2-4} or @samp{2-4}). For example, if the current inferior is -1, the thread list @samp{1 2-3 4.5 6.7-9} includes threads 1 to 3 of -inferior 1, thread 5 of inferior 4 and threads 7 to 9 of inferior 6. -That is, in expanded qualified form, the same as @samp{1.1 1.2 1.3 4.5 -6.7 6.8 6.9}. +argument. A list element can be: + +@enumerate +@item +A thread ID as shown in the first field of the @samp{info threads} +display, with or without an inferior qualifier. E.g., @samp{2.1} or +@samp{1}. + +@item +A range of thread numbers, again with or without an inferior +qualifier, as in @var{inf}.@var{thr1}-@var{thr2} or +@var{thr1}-@var{thr2}. E.g., @samp{1.2-4} or @samp{2-4}. + +@item +All threads of an inferior, specified with a star wildcard, with or +without an inferior qualifier, as in @var{inf}.@code{*} (e.g., +@samp{1.*}) or @code{*}. The former refers to all threads of the +given inferior, and the latter form without an inferior qualifier +refers to all threads of the current inferior. + +@end enumerate + +For example, if the current inferior is 1, and inferior 7 has one +thread with ID 7.1, the thread list @samp{1 2-3 4.5 6.7-9 7.*} +includes threads 1 to 3 of inferior 1, thread 5 of inferior 4, threads +7 to 9 of inferior 6 and all threads of inferior 7. That is, in +expanded qualified form, the same as @samp{1.1 1.2 1.3 4.5 6.7 6.8 6.9 +7.1}. + @anchor{global thread numbers} @cindex global thread number diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e5e38b3..7ba90d7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2016-01-15 Pedro Alves <palves@redhat.com> + * gdb.multi/tids.exp: Test star wildcard ranges. + +2016-01-15 Pedro Alves <palves@redhat.com> + * gdb.multi/tids.exp (thr_apply_info_thr_error): Remove "p 1234" command from "thread apply" invocation. (thr_apply_info_thr_invalid): Default the expected output to the diff --git a/gdb/testsuite/gdb.multi/tids.exp b/gdb/testsuite/gdb.multi/tids.exp index 5763234..5d8701e 100644 --- a/gdb/testsuite/gdb.multi/tids.exp +++ b/gdb/testsuite/gdb.multi/tids.exp @@ -277,6 +277,36 @@ with_test_prefix "two inferiors" { "warning: Unknown thread 30.1" \ "thread apply \$inf.1" + # Star ranges. + + thr_apply_info_thr "1.*" \ + "1.1 1.2 1.3" + + thr_apply_info_thr "*" \ + "1.1 1.2 1.3" + + thr_apply_info_thr "1.* 2.1" \ + "1.1 1.2 1.3 2.1" + + thr_apply_info_thr "2.1 1.*" \ + "1.1 1.2 1.3 2.1" \ + "2.1 1.1 1.2 1.3" + + thr_apply_info_thr "1.* 2.*" \ + "1.1 1.2 1.3 2.1 2.2 2.3" + + thr_apply_info_thr "2.* 1.*" \ + "1.1 1.2 1.3 2.1 2.2 2.3" \ + "2.1 2.2 2.3 1.1 1.2 1.3" + + # There's no inferior 3, but "info threads" treats the thread list + # as a filter, so it's OK. "thread apply" complains about the + # unknown inferior through. + info_threads "1.1 3.*" \ + "1.1" + gdb_test "thread apply 1.1 3.* p 1" \ + "Thread 1.1.*warning: Unknown inferior 3" + # Now test a set of invalid thread IDs/ranges. thr_apply_info_thr_invalid "1." \ @@ -318,6 +348,11 @@ with_test_prefix "two inferiors" { thr_apply_info_thr_error "${prefix}-\$one" "negative value" thr_apply_info_thr_error "${prefix}\$minus_one" \ "negative value: ${prefix_re}\\\$minus_one" + + thr_apply_info_thr_error "${prefix}1-*" "inverted range" + thr_apply_info_thr_invalid "${prefix}*1" + thr_apply_info_thr_invalid "${prefix}*foo" + thr_apply_info_thr_invalid "${prefix}foo*" } # Check that a valid thread ID list with a missing command errors @@ -330,6 +365,7 @@ with_test_prefix "two inferiors" { gdb_test "thread apply 1-2" $output gdb_test "thread apply 1.1-2" $output gdb_test "thread apply $thr" $output + gdb_test "thread apply 1.*" $output } # Check that we do parse the inferior number and don't confuse it. diff --git a/gdb/thread.c b/gdb/thread.c index 56de6e1..c7f1467 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1864,6 +1864,26 @@ thread_apply_command (char *tidlist, int from_tty) inf = find_inferior_id (inf_num); if (inf != NULL) tp = find_thread_id (inf, thr_num); + + if (tid_range_parser_star_range (&parser)) + { + if (inf == NULL) + { + warning (_("Unknown inferior %d"), inf_num); + tid_range_parser_skip (&parser); + continue; + } + + /* No use looking for threads past the highest thread number + the inferior ever had. */ + if (thr_num >= inf->highest_thread_num) + tid_range_parser_skip (&parser); + + /* Be quiet about unknown threads numbers. */ + if (tp == NULL) + continue; + } + if (tp == NULL) { if (show_inferior_qualified_tids () diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c index 45b7ff5..68133c6 100644 --- a/gdb/tid-parse.c +++ b/gdb/tid-parse.c @@ -134,6 +134,7 @@ tid_range_parser_finished (struct tid_range_parser *parser) case TID_RANGE_STATE_INFERIOR: return *parser->string == '\0'; case TID_RANGE_STATE_THREAD_RANGE: + case TID_RANGE_STATE_STAR_RANGE: return parser->range_parser.finished; } @@ -150,6 +151,7 @@ tid_range_parser_string (struct tid_range_parser *parser) case TID_RANGE_STATE_INFERIOR: return parser->string; case TID_RANGE_STATE_THREAD_RANGE: + case TID_RANGE_STATE_STAR_RANGE: return parser->range_parser.string; } @@ -161,7 +163,8 @@ tid_range_parser_string (struct tid_range_parser *parser) void tid_range_parser_skip (struct tid_range_parser *parser) { - gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE) + gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE + || parser->state == TID_RANGE_STATE_STAR_RANGE) && parser->range_parser.in_range); tid_range_parser_init (parser, parser->range_parser.end_ptr, @@ -219,7 +222,16 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num, } init_number_or_range (&parser->range_parser, p); - parser->state = TID_RANGE_STATE_THREAD_RANGE; + if (p[0] == '*' && (p[1] == '\0' || isspace (p[1]))) + { + /* Setup the number range parser to return numbers in the + whole [1,INT_MAX] range. */ + number_range_setup_range (&parser->range_parser, 1, INT_MAX, + skip_spaces_const (p + 1)); + parser->state = TID_RANGE_STATE_STAR_RANGE; + } + else + parser->state = TID_RANGE_STATE_THREAD_RANGE; } *inf_num = parser->inf_num; @@ -247,7 +259,9 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num, /* If we're midway through a range, and the caller wants the end value, return it and skip to the end of the range. */ - if (thr_end != NULL && parser->state == TID_RANGE_STATE_THREAD_RANGE) + if (thr_end != NULL + && (parser->state == TID_RANGE_STATE_THREAD_RANGE + || parser->state == TID_RANGE_STATE_STAR_RANGE)) { *thr_end = parser->range_parser.end_value; tid_range_parser_skip (parser); @@ -281,6 +295,14 @@ tid_range_parser_get_tid (struct tid_range_parser *parser, /* See tid-parse.h. */ int +tid_range_parser_star_range (struct tid_range_parser *parser) +{ + return parser->state == TID_RANGE_STATE_STAR_RANGE; +} + +/* See gdbthread.h. */ + +int tid_is_in_list (const char *list, int default_inferior, int inf_num, int thr_num) { diff --git a/gdb/tid-parse.h b/gdb/tid-parse.h index a690edf..830cf36 100644 --- a/gdb/tid-parse.h +++ b/gdb/tid-parse.h @@ -44,6 +44,9 @@ enum tid_range_state /* Parsing the thread number or thread number range. */ TID_RANGE_STATE_THREAD_RANGE, + + /* Parsing a star wildcard thread range. E.g., "1.*". */ + TID_RANGE_STATE_STAR_RANGE, }; /* An object of this type is passed to tid_range_parser_get_tid. It @@ -142,6 +145,10 @@ extern int tid_range_parser_get_tid_range (struct tid_range_parser *parser, int *inf_num, int *thr_start, int *thr_end); +/* Returns non-zero if processing a star wildcard (e.g., "1.*") + range. */ +extern int tid_range_parser_star_range (struct tid_range_parser *parser); + /* Returns non-zero if parsing has completed. */ extern int tid_range_parser_finished (struct tid_range_parser *parser); |