Fix "thread apply $conv_var" and misc other related problems
This fixes a few bugs in "thread apply". While this works: (gdb) thread apply 1 p 1234 Thread 1 (Thread 0x7ffff7fc1740 (LWP 14048)): $1 = 1234 This doesn't: (gdb) thread apply $thr p 1234 Thread 1 (Thread 0x7ffff7fc1740 (LWP 12039)): Invalid thread ID: p 1234 (gdb) ~~~~ Also, while this works: (gdb) thread apply 1 Please specify a command following the thread ID list This doesn't: (gdb) thread apply $thr Thread 1 (Thread 0x7ffff7fc1740 (LWP 12039)): [Current thread is 1 (Thread 0x7ffff7fc1740 (LWP 12039))] (gdb) ~~~~ And, while this works: (gdb) thread apply Please specify a thread ID list This obviously bogus invocation is just silent: (gdb) thread apply bt (gdb) gdb/ChangeLog: 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. (parse_thread_id): Use it. (get_tid_or_range): Use it. Return 0 instead of throwing invalid thread ID error. (get_tid_or_range): Detect negative values. Return 0 instead of throwing invalid thread ID error. gdb/testsuite/ChangeLog: 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 input tid list. (top level): Add tests that use convenience variables. Add tests for "thread apply" with a valid TID list, but missing the command.
This commit is contained in:
parent
9c03a84f6c
commit
3f5b759880
5 changed files with 163 additions and 20 deletions
|
@ -1,3 +1,14 @@
|
||||||
|
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.
|
||||||
|
(parse_thread_id): Use it.
|
||||||
|
(get_tid_or_range): Use it. Return 0 instead of throwing invalid
|
||||||
|
thread ID error.
|
||||||
|
(get_tid_or_range): Detect negative values. Return 0 instead of
|
||||||
|
throwing invalid thread ID error.
|
||||||
|
|
||||||
2016-01-14 Yao Qi <yao.qi@linaro.org>
|
2016-01-14 Yao Qi <yao.qi@linaro.org>
|
||||||
|
|
||||||
* arm-linux-tdep.c (arm_linux_get_next_pcs_syscall_next_pc):
|
* arm-linux-tdep.c (arm_linux_get_next_pcs_syscall_next_pc):
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
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
|
||||||
|
input tid list.
|
||||||
|
(top level): Add tests that use convenience variables. Add tests
|
||||||
|
for "thread apply" with a valid TID list, but missing the command.
|
||||||
|
|
||||||
2016-01-13 Pedro Alves <palves@redhat.com>
|
2016-01-13 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* gdb.base/default.exp: Expect $_gthread as well.
|
* gdb.base/default.exp: Expect $_gthread as well.
|
||||||
|
|
|
@ -90,15 +90,19 @@ proc thr_apply_info_thr_error {tid_list exp_error} {
|
||||||
gdb_test "info threads $tid_list" \
|
gdb_test "info threads $tid_list" \
|
||||||
$exp_error
|
$exp_error
|
||||||
|
|
||||||
gdb_test "thread apply $tid_list p 1234" \
|
gdb_test "thread apply $tid_list" \
|
||||||
$exp_error \
|
$exp_error \
|
||||||
"thread apply $tid_list"
|
"thread apply $tid_list"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Issue both "info threads TID_LIST" and "thread apply TID_LIST" and
|
# Issue both "info threads TID_LIST" and "thread apply TID_LIST" and
|
||||||
# expect the command to error out with "Invalid thread ID: $EXPECTED".
|
# expect the command to error out with "Invalid thread ID: $EXPECTED".
|
||||||
# EXPECTED is a literal string, not a regexp.
|
# EXPECTED is a literal string, not a regexp. If EXPECTED is omitted,
|
||||||
proc thr_apply_info_thr_invalid {tid_list expected} {
|
# TID_LIST is expected instead.
|
||||||
|
proc thr_apply_info_thr_invalid {tid_list {expected ""}} {
|
||||||
|
if {$expected == ""} {
|
||||||
|
set expected $tid_list
|
||||||
|
}
|
||||||
set expected [string_to_regexp $expected]
|
set expected [string_to_regexp $expected]
|
||||||
gdb_test "info threads $tid_list" \
|
gdb_test "info threads $tid_list" \
|
||||||
"Invalid thread ID: $expected"
|
"Invalid thread ID: $expected"
|
||||||
|
@ -183,6 +187,12 @@ with_test_prefix "two inferiors" {
|
||||||
gdb_continue_to_breakpoint "twice"
|
gdb_continue_to_breakpoint "twice"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thr_apply_info_thr "1" \
|
||||||
|
"1.1"
|
||||||
|
|
||||||
|
thr_apply_info_thr "1.1" \
|
||||||
|
"1.1"
|
||||||
|
|
||||||
thr_apply_info_thr "1 2 3" \
|
thr_apply_info_thr "1 2 3" \
|
||||||
"1.1 1.2 1.3"
|
"1.1 1.2 1.3"
|
||||||
|
|
||||||
|
@ -214,6 +224,59 @@ with_test_prefix "two inferiors" {
|
||||||
thr_apply_info_thr "1.1-2 2.2-3" \
|
thr_apply_info_thr "1.1-2 2.2-3" \
|
||||||
"1.1 1.2 2.2 2.3"
|
"1.1 1.2 2.2 2.3"
|
||||||
|
|
||||||
|
# Now test using GDB convenience variables.
|
||||||
|
|
||||||
|
gdb_test "p \$inf = 1" " = 1"
|
||||||
|
gdb_test "p \$thr_start = 2" " = 2"
|
||||||
|
gdb_test "p \$thr_end = 3" " = 3"
|
||||||
|
|
||||||
|
# Convenience variable for the inferior number, only.
|
||||||
|
thr_apply_info_thr "\$inf.2" \
|
||||||
|
"1.2"
|
||||||
|
thr_apply_info_thr "\$inf.2-3" \
|
||||||
|
"1.2 1.3"
|
||||||
|
|
||||||
|
# Convenience variables for thread numbers as well.
|
||||||
|
foreach prefix {"" "1." "\$inf."} {
|
||||||
|
thr_apply_info_thr "${prefix}\$thr_start" \
|
||||||
|
"1.2"
|
||||||
|
thr_apply_info_thr "${prefix}\$thr_start-\$thr_end" \
|
||||||
|
"1.2 1.3"
|
||||||
|
thr_apply_info_thr "${prefix}2-\$thr_end" \
|
||||||
|
"1.2 1.3"
|
||||||
|
thr_apply_info_thr "${prefix}\$thr_start-3" \
|
||||||
|
"1.2 1.3"
|
||||||
|
|
||||||
|
# Undefined convenience variable.
|
||||||
|
set prefix_re [string_to_regexp $prefix]
|
||||||
|
thr_apply_info_thr_error "${prefix}\$conv123" \
|
||||||
|
[multi_line \
|
||||||
|
"Convenience variable must have integer value\." \
|
||||||
|
"Invalid thread ID: ${prefix_re}\\\$conv123"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convenience variables pointing at an inexisting thread and/or
|
||||||
|
# inferior.
|
||||||
|
gdb_test "p \$inf = 30" " = 30"
|
||||||
|
gdb_test "p \$thr = 20" " = 20"
|
||||||
|
# Try both the convenience variable and the literal number.
|
||||||
|
foreach thr {"\$thr" "20" "1.20" "\$inf.1" "30.1" } {
|
||||||
|
set expected [string_to_regexp $thr]
|
||||||
|
gdb_test "info threads $thr" "No threads match '${expected}'."
|
||||||
|
# "info threads" works like a filter. If there's any other
|
||||||
|
# valid thread in the list, there's no error.
|
||||||
|
info_threads "$thr 1.1" "1.1"
|
||||||
|
info_threads "1.1 $thr" "1.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "thread apply \$thr p 1234" \
|
||||||
|
"warning: Unknown thread 1.20" \
|
||||||
|
"thread apply \$thr"
|
||||||
|
|
||||||
|
gdb_test "thread apply \$inf.1 p 1234" \
|
||||||
|
"warning: Unknown thread 30.1" \
|
||||||
|
"thread apply \$inf.1"
|
||||||
|
|
||||||
# Now test a set of invalid thread IDs/ranges.
|
# Now test a set of invalid thread IDs/ranges.
|
||||||
|
|
||||||
thr_apply_info_thr_invalid "1." \
|
thr_apply_info_thr_invalid "1." \
|
||||||
|
@ -234,17 +297,40 @@ with_test_prefix "two inferiors" {
|
||||||
thr_apply_info_thr_invalid "1-2.1" \
|
thr_apply_info_thr_invalid "1-2.1" \
|
||||||
"1-2.1"
|
"1-2.1"
|
||||||
|
|
||||||
thr_apply_info_thr_error "1-0" "inverted range"
|
gdb_test "p \$zero = 0" " = 0"
|
||||||
thr_apply_info_thr_error "1.1-0" "inverted range"
|
gdb_test "p \$one = 1" " = 1"
|
||||||
|
gdb_test "p \$minus_one = -11" " = -11"
|
||||||
|
foreach prefix {"" "1." "$one."} {
|
||||||
|
set prefix_re [string_to_regexp $prefix]
|
||||||
|
|
||||||
thr_apply_info_thr_error "1-" "inverted range"
|
thr_apply_info_thr_invalid "${prefix}foo"
|
||||||
thr_apply_info_thr_error "1.1-" "inverted range"
|
thr_apply_info_thr_invalid "${prefix}1foo"
|
||||||
|
thr_apply_info_thr_invalid "${prefix}foo1"
|
||||||
|
|
||||||
thr_apply_info_thr_error "2-1" "inverted range"
|
thr_apply_info_thr_error "${prefix}1-0" "inverted range"
|
||||||
thr_apply_info_thr_error "1.2-1" "inverted range"
|
thr_apply_info_thr_error "${prefix}1-\$zero" "inverted range"
|
||||||
|
thr_apply_info_thr_error "${prefix}\$one-0" "inverted range"
|
||||||
|
thr_apply_info_thr_error "${prefix}\$one-\$zero" "inverted range"
|
||||||
|
thr_apply_info_thr_error "${prefix}1-" "inverted range"
|
||||||
|
thr_apply_info_thr_error "${prefix}2-1" "inverted range"
|
||||||
|
thr_apply_info_thr_error "${prefix}2-\$one" "inverted range"
|
||||||
|
thr_apply_info_thr_error "${prefix}-1" "negative value"
|
||||||
|
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 "-1" "negative value"
|
# Check that a valid thread ID list with a missing command errors
|
||||||
thr_apply_info_thr_error "1.-1" "negative value"
|
# out.
|
||||||
|
with_test_prefix "missing command" {
|
||||||
|
set output "Please specify a command following the thread ID list"
|
||||||
|
gdb_test "thread apply 1" $output
|
||||||
|
gdb_test "thread apply 1.1" $output
|
||||||
|
gdb_test "thread apply 1.1 1.2" $output
|
||||||
|
gdb_test "thread apply 1-2" $output
|
||||||
|
gdb_test "thread apply 1.1-2" $output
|
||||||
|
gdb_test "thread apply $thr" $output
|
||||||
|
}
|
||||||
|
|
||||||
# Check that we do parse the inferior number and don't confuse it.
|
# Check that we do parse the inferior number and don't confuse it.
|
||||||
gdb_test "info threads 3.1" \
|
gdb_test "info threads 3.1" \
|
||||||
|
|
20
gdb/thread.c
20
gdb/thread.c
|
@ -1818,7 +1818,7 @@ thread_apply_all_command (char *cmd, int from_tty)
|
||||||
static void
|
static void
|
||||||
thread_apply_command (char *tidlist, int from_tty)
|
thread_apply_command (char *tidlist, int from_tty)
|
||||||
{
|
{
|
||||||
char *cmd;
|
char *cmd = NULL;
|
||||||
struct cleanup *old_chain;
|
struct cleanup *old_chain;
|
||||||
char *saved_cmd;
|
char *saved_cmd;
|
||||||
struct tid_range_parser parser;
|
struct tid_range_parser parser;
|
||||||
|
@ -1826,11 +1826,25 @@ thread_apply_command (char *tidlist, int from_tty)
|
||||||
if (tidlist == NULL || *tidlist == '\000')
|
if (tidlist == NULL || *tidlist == '\000')
|
||||||
error (_("Please specify a thread ID list"));
|
error (_("Please specify a thread ID list"));
|
||||||
|
|
||||||
for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++);
|
tid_range_parser_init (&parser, tidlist, current_inferior ()->num);
|
||||||
|
while (!tid_range_parser_finished (&parser))
|
||||||
|
{
|
||||||
|
int inf_num, thr_start, thr_end;
|
||||||
|
|
||||||
if (*cmd == '\000')
|
if (!tid_range_parser_get_tid_range (&parser,
|
||||||
|
&inf_num, &thr_start, &thr_end))
|
||||||
|
{
|
||||||
|
cmd = (char *) tid_range_parser_string (&parser);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == NULL)
|
||||||
error (_("Please specify a command following the thread ID list"));
|
error (_("Please specify a command following the thread ID list"));
|
||||||
|
|
||||||
|
if (tidlist == cmd || !isalpha (cmd[0]))
|
||||||
|
invalid_thread_id_error (cmd);
|
||||||
|
|
||||||
/* Save a copy of the command in case it is clobbered by
|
/* Save a copy of the command in case it is clobbered by
|
||||||
execute_command. */
|
execute_command. */
|
||||||
saved_cmd = xstrdup (cmd);
|
saved_cmd = xstrdup (cmd);
|
||||||
|
|
|
@ -31,6 +31,23 @@ invalid_thread_id_error (const char *string)
|
||||||
error (_("Invalid thread ID: %s"), string);
|
error (_("Invalid thread ID: %s"), string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrapper for get_number_trailer that throws an error if we get back
|
||||||
|
a negative number. We'll see a negative value if the number is
|
||||||
|
stored in a negative convenience variable (e.g., $minus_one = -1).
|
||||||
|
STRING is the parser string to be used in the error message if we
|
||||||
|
do get back a negative number. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_positive_number_trailer (const char **pp, int trailer, const char *string)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
|
||||||
|
num = get_number_trailer (pp, trailer);
|
||||||
|
if (num < 0)
|
||||||
|
error (_("negative value: %s"), string);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
/* See tid-parse.h. */
|
/* See tid-parse.h. */
|
||||||
|
|
||||||
struct thread_info *
|
struct thread_info *
|
||||||
|
@ -51,7 +68,7 @@ parse_thread_id (const char *tidstr, const char **end)
|
||||||
int inf_num;
|
int inf_num;
|
||||||
|
|
||||||
p1 = number;
|
p1 = number;
|
||||||
inf_num = get_number_trailer (&p1, '.');
|
inf_num = get_positive_number_trailer (&p1, '.', number);
|
||||||
if (inf_num == 0)
|
if (inf_num == 0)
|
||||||
invalid_thread_id_error (number);
|
invalid_thread_id_error (number);
|
||||||
|
|
||||||
|
@ -69,7 +86,7 @@ parse_thread_id (const char *tidstr, const char **end)
|
||||||
p1 = number;
|
p1 = number;
|
||||||
}
|
}
|
||||||
|
|
||||||
thr_num = get_number_const (&p1);
|
thr_num = get_positive_number_trailer (&p1, 0, number);
|
||||||
if (thr_num == 0)
|
if (thr_num == 0)
|
||||||
invalid_thread_id_error (number);
|
invalid_thread_id_error (number);
|
||||||
|
|
||||||
|
@ -183,15 +200,16 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
|
||||||
|
|
||||||
/* Parse number to the left of the dot. */
|
/* Parse number to the left of the dot. */
|
||||||
p = parser->string;
|
p = parser->string;
|
||||||
parser->inf_num = get_number_trailer (&p, '.');
|
parser->inf_num
|
||||||
|
= get_positive_number_trailer (&p, '.', parser->string);
|
||||||
if (parser->inf_num == 0)
|
if (parser->inf_num == 0)
|
||||||
invalid_thread_id_error (parser->string);
|
return 0;
|
||||||
|
|
||||||
parser->qualified = 1;
|
parser->qualified = 1;
|
||||||
p = dot + 1;
|
p = dot + 1;
|
||||||
|
|
||||||
if (isspace (*p))
|
if (isspace (*p))
|
||||||
invalid_thread_id_error (parser->string);
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -206,8 +224,13 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
|
||||||
|
|
||||||
*inf_num = parser->inf_num;
|
*inf_num = parser->inf_num;
|
||||||
*thr_start = get_number_or_range (&parser->range_parser);
|
*thr_start = get_number_or_range (&parser->range_parser);
|
||||||
|
if (*thr_start < 0)
|
||||||
|
error (_("negative value: %s"), parser->string);
|
||||||
if (*thr_start == 0)
|
if (*thr_start == 0)
|
||||||
invalid_thread_id_error (parser->string);
|
{
|
||||||
|
parser->state = TID_RANGE_STATE_INFERIOR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we successfully parsed a thread number or finished parsing a
|
/* If we successfully parsed a thread number or finished parsing a
|
||||||
thread range, switch back to assuming the next TID is
|
thread range, switch back to assuming the next TID is
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue