From: Pedro Alves Date: Fri, 15 Jan 2016 21:46:22 +0000 (+0000) Subject: Fix "thread apply $conv_var" and misc other related problems X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3f5b7598805c8253c43c989a540a2408c8b685ad;p=binutils-gdb.git 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 * 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 * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ad4049ca418..99245d70a88 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2016-01-15 Pedro Alves + + * 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 * arm-linux-tdep.c (arm_linux_get_next_pcs_syscall_next_pc): diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index dcdc09cc1dc..e5e38b3b180 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2016-01-15 Pedro Alves + + * 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 * gdb.base/default.exp: Expect $_gthread as well. diff --git a/gdb/testsuite/gdb.multi/tids.exp b/gdb/testsuite/gdb.multi/tids.exp index b72695d43dc..57632346fb7 100644 --- a/gdb/testsuite/gdb.multi/tids.exp +++ b/gdb/testsuite/gdb.multi/tids.exp @@ -90,15 +90,19 @@ proc thr_apply_info_thr_error {tid_list exp_error} { gdb_test "info threads $tid_list" \ $exp_error - gdb_test "thread apply $tid_list p 1234" \ + gdb_test "thread apply $tid_list" \ $exp_error \ "thread apply $tid_list" } # Issue both "info threads TID_LIST" and "thread apply TID_LIST" and # expect the command to error out with "Invalid thread ID: $EXPECTED". -# EXPECTED is a literal string, not a regexp. -proc thr_apply_info_thr_invalid {tid_list expected} { +# EXPECTED is a literal string, not a regexp. If EXPECTED is omitted, +# 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] gdb_test "info threads $tid_list" \ "Invalid thread ID: $expected" @@ -183,6 +187,12 @@ with_test_prefix "two inferiors" { 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" \ "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" \ "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. thr_apply_info_thr_invalid "1." \ @@ -234,17 +297,40 @@ with_test_prefix "two inferiors" { thr_apply_info_thr_invalid "1-2.1" \ "1-2.1" - thr_apply_info_thr_error "1-0" "inverted range" - thr_apply_info_thr_error "1.1-0" "inverted range" - - thr_apply_info_thr_error "1-" "inverted range" - thr_apply_info_thr_error "1.1-" "inverted range" - - thr_apply_info_thr_error "2-1" "inverted range" - thr_apply_info_thr_error "1.2-1" "inverted range" + gdb_test "p \$zero = 0" " = 0" + 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_invalid "${prefix}foo" + thr_apply_info_thr_invalid "${prefix}1foo" + thr_apply_info_thr_invalid "${prefix}foo1" + + thr_apply_info_thr_error "${prefix}1-0" "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" - thr_apply_info_thr_error "1.-1" "negative value" + # Check that a valid thread ID list with a missing command errors + # 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. gdb_test "info threads 3.1" \ diff --git a/gdb/thread.c b/gdb/thread.c index b3b3995d60e..56de6e1c089 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1818,7 +1818,7 @@ thread_apply_all_command (char *cmd, int from_tty) static void thread_apply_command (char *tidlist, int from_tty) { - char *cmd; + char *cmd = NULL; struct cleanup *old_chain; char *saved_cmd; struct tid_range_parser parser; @@ -1826,11 +1826,25 @@ thread_apply_command (char *tidlist, int from_tty) if (tidlist == NULL || *tidlist == '\000') 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 (!tid_range_parser_get_tid_range (&parser, + &inf_num, &thr_start, &thr_end)) + { + cmd = (char *) tid_range_parser_string (&parser); + break; + } + } - if (*cmd == '\000') + if (cmd == NULL) 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 execute_command. */ saved_cmd = xstrdup (cmd); diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c index 21b872d39d3..45b7ff56dc2 100644 --- a/gdb/tid-parse.c +++ b/gdb/tid-parse.c @@ -31,6 +31,23 @@ invalid_thread_id_error (const char *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. */ struct thread_info * @@ -51,7 +68,7 @@ parse_thread_id (const char *tidstr, const char **end) int inf_num; p1 = number; - inf_num = get_number_trailer (&p1, '.'); + inf_num = get_positive_number_trailer (&p1, '.', number); if (inf_num == 0) invalid_thread_id_error (number); @@ -69,7 +86,7 @@ parse_thread_id (const char *tidstr, const char **end) p1 = number; } - thr_num = get_number_const (&p1); + thr_num = get_positive_number_trailer (&p1, 0, number); if (thr_num == 0) 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. */ 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) - invalid_thread_id_error (parser->string); + return 0; parser->qualified = 1; p = dot + 1; if (isspace (*p)) - invalid_thread_id_error (parser->string); + return 0; } else { @@ -206,8 +224,13 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num, *inf_num = parser->inf_num; *thr_start = get_number_or_range (&parser->range_parser); + if (*thr_start < 0) + error (_("negative value: %s"), parser->string); 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 thread range, switch back to assuming the next TID is