Explicit locations: MI support for explicit locations
authorKeith Seitz <keiths@redhat.com>
Wed, 12 Aug 2015 00:09:36 +0000 (17:09 -0700)
committerKeith Seitz <keiths@redhat.com>
Wed, 12 Aug 2015 00:09:36 +0000 (17:09 -0700)
This patch adds support for explicit locations to MI's -break-insert
command. The new options, documented in the User Manual, are
--source, --line, --function, and --label.

gdb/ChangeLog:

* mi/mi-cmd-break.c (mi_cmd_break_insert_1): Add support for
explicit locations, options "--source", "--function",
"--label", and "--line".

gdb/testsuite/ChangeLog:

* gdb.mi/mi-break.exp (test_explicit_breakpoints): New proc.
(at toplevel): Call test_explicit_breakpoints.
* gdb.mi/mi-dprintf.exp: Add tests for explicit dprintf
breakpoints.
* lib/mi-support.exp (mi_make_breakpoint): Add support for
breakpoint conditions, "-cond".

gdb/ChangeLog
gdb/mi/mi-cmd-break.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.mi/mi-break.exp
gdb/testsuite/gdb.mi/mi-dprintf.exp
gdb/testsuite/lib/mi-support.exp

index 57717bde773870bc3ac1d49c3d9967f89cb26c91..b8d089f424720fe852e855113b0e84eb488356b9 100644 (file)
@@ -1,3 +1,9 @@
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
+       * mi/mi-cmd-break.c (mi_cmd_break_insert_1): Add support for
+       explicit locations, options "--source", "--function",
+       "--label", and "--line".
+
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
        * completer.c: Include location.h.
index c8c988dd7642fe775af8fb8a67bff431ae6d3982..4aded13781af14a31d0de6b48ce9af701486edd1 100644 (file)
@@ -182,6 +182,8 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
   enum bptype type_wanted;
   struct event_location *location;
   struct breakpoint_ops *ops;
+  int is_explicit = 0;
+  struct explicit_location explicit;
   char *extra_string = NULL;
 
   enum opt
@@ -189,6 +191,8 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
       TRACEPOINT_OPT,
+      EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
+      EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
     };
   static const struct mi_opt opts[] =
   {
@@ -200,6 +204,10 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
     {"f", PENDING_OPT, 0},
     {"d", DISABLE_OPT, 0},
     {"a", TRACEPOINT_OPT, 0},
+    {"-source" , EXPLICIT_SOURCE_OPT, 1},
+    {"-function", EXPLICIT_FUNC_OPT, 1},
+    {"-label", EXPLICIT_LABEL_OPT, 1},
+    {"-line", EXPLICIT_LINE_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -208,6 +216,8 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
   int oind = 0;
   char *oarg;
 
+  initialize_explicit_location (&explicit);
+
   while (1)
     {
       int opt = mi_getopt ("-break-insert", argc, argv,
@@ -240,16 +250,31 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
        case TRACEPOINT_OPT:
          tracepoint = 1;
          break;
+       case EXPLICIT_SOURCE_OPT:
+         is_explicit = 1;
+         explicit.source_filename = oarg;
+         break;
+       case EXPLICIT_FUNC_OPT:
+         is_explicit = 1;
+         explicit.function_name = oarg;
+         break;
+       case EXPLICIT_LABEL_OPT:
+         is_explicit = 1;
+         explicit.label_name = oarg;
+         break;
+       case EXPLICIT_LINE_OPT:
+         is_explicit = 1;
+         explicit.line_offset = linespec_parse_line_offset (oarg);
+         break;
        }
     }
 
-  if (oind >= argc)
+  if (oind >= argc && !is_explicit)
     error (_("-%s-insert: Missing <location>"),
           dprintf ? "dprintf" : "break");
-  address = argv[oind];
   if (dprintf)
     {
-      int format_num = oind + 1;
+      int format_num = is_explicit ? oind : oind + 1;
 
       if (hardware || tracepoint)
        error (_("-dprintf-insert: does not support -h or -a"));
@@ -258,11 +283,21 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
 
       extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
       make_cleanup (xfree, extra_string);
+      address = argv[oind];
     }
   else
     {
-      if (oind < argc - 1)
-       error (_("-break-insert: Garbage following <location>"));
+      if (is_explicit)
+       {
+         if (oind < argc)
+           error (_("-break-insert: Garbage following explicit location"));
+       }
+      else
+       {
+         if (oind < argc - 1)
+           error (_("-break-insert: Garbage following <location>"));
+         address = argv[oind];
+       }
     }
 
   /* Now we have what we need, let's insert the breakpoint!  */
@@ -291,11 +326,30 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
       ops = &bkpt_breakpoint_ops;
     }
 
-  location = string_to_event_location (&address, current_language);
-  make_cleanup_delete_event_location (location);
+  if (is_explicit)
+    {
+      /* Error check -- we must have one of the other
+        parameters specified.  */
+      if (explicit.source_filename != NULL
+         && explicit.function_name == NULL
+         && explicit.label_name == NULL
+         && explicit.line_offset.sign == LINE_OFFSET_UNKNOWN)
+       error (_("-%s-insert: --source option requires --function, --label,"
+                " or --line"), dprintf ? "dprintf" : "break");
+
+      location = new_explicit_location (&explicit);
+    }
+  else
+    {
+      location = string_to_event_location (&address, current_language);
+      if (*address)
+       {
+         delete_event_location (location);
+         error (_("Garbage '%s' at end of location"), address);
+       }
+    }
 
-  if (*address)
-    error (_("Garbage '%s' at end of location"), address);
+  make_cleanup_delete_event_location (location);
 
   create_breakpoint (get_current_arch (), location, condition, thread,
                     extra_string,
index ae3a2756d2d38b493545d608a8740e7ae870f67b..de6615574a935ec08a6e357f91cfa5f7fbf76e32 100644 (file)
@@ -1,3 +1,12 @@
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
+       * gdb.mi/mi-break.exp (test_explicit_breakpoints): New proc.
+       (at toplevel): Call test_explicit_breakpoints.
+       * gdb.mi/mi-dprintf.exp: Add tests for explicit dprintf
+       breakpoints.
+       * lib/mi-support.exp (mi_make_breakpoint): Add support for
+       breakpoint conditions, "-cond".
+
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
        * gdb.linespec/3explicit.c: New file.
index a86ba8c974179a3de93825849dc3d814391c274e..60bab0e3ea9cf83992f3a9d037a1a12bc7a9c4bd 100644 (file)
@@ -305,6 +305,86 @@ proc test_breakpoint_commands {} {
     mi_expect_stop "exited-normally" "" "" "" "" "" "test hitting breakpoint with commands"
 }
 
+# Test explicit breakpoints.  These tests only test the MI portion of the
+# code.  In-depth testing of explicit breakpoints is accomplished in
+# gdb.linespec tests.
+
+proc test_explicit_breakpoints {} {
+    global srcfile
+    global line_callee3_head line_callee4_head
+    global line_callee2_body line_main_body
+
+    mi_delete_breakpoints
+
+    # First check mixed explicit/parsed linespecs.
+    mi_gdb_test "-break-insert --function main $srcfile:$line_callee3_head" \
+       ".*Garbage following explicit linespec"
+
+    # Insert some breakpoints and list them
+    # Also, disable some so they do not interfere with other tests
+    # Tests:
+    # -break-insert -t --function main
+    # -break-insert -t --source basics.c --function callee2
+    # -break-insert -t --source basics.c --line $line_callee3_head
+    # -break-insert -t --source srcfile --line $line_callee4_head
+    # -break-list
+
+    set bps {}
+    lappend bps [mi_create_breakpoint "-t --function main" \
+                    "insert temp explicit breakpoint in main" \
+                    -func main -file ".*$srcfile" -line $line_main_body]
+
+    lappend bps \
+       [mi_create_breakpoint "-t --source $srcfile --function callee2" \
+            "insert temp explicit breakpoint at $srcfile:callee2" \
+            -func callee2 -file ".*$srcfile" -line $line_callee2_body]
+
+    lappend bps \
+       [mi_create_breakpoint "-t --source $srcfile --line $line_callee3_head" \
+            "insert temp explicit breakpoint at $srcfile:$line_callee3_head" \
+            -func callee3 -file ".*$srcfile" -line $line_callee3_head]
+
+    lappend bps \
+       [mi_create_breakpoint \
+            "-t --source \"$srcfile\" --line  $line_callee4_head" \
+            "insert temp explicit breakpoint at \"$srcfile\":$line_callee4_head" \
+            -func callee4 -file ".*$srcfile" -line $line_callee4_head]
+
+    mi_gdb_test "-break-list" "\\^done,[mi_make_breakpoint_table $bps]" \
+       "list of explicit breakpoints"
+
+    mi_gdb_test "-break-delete" \
+           "\\^done" \
+           "delete temp breakpoints"
+
+    mi_create_breakpoint "-c \"intarg == 3\" --function callee2" \
+       "insert explicit conditional breakpoint in callee2" \
+       -func callee2 ".*$srcfile" -line $line_callee2_body \
+       -cond "intarg == 3"
+
+    # mi_create_breakpoint cannot deal with displaying canonical
+    # linespecs.
+    mi_gdb_test \
+       "-break-insert -c \"foo == 3\" --source $srcfile --function main --label label" \
+       ".*No symbol \"foo\" in current context.*"
+
+    mi_gdb_test \
+       "-break-insert --source foobar.c --line 3" \
+       ".*No source file named foobar.c.*"
+
+    mi_gdb_test \
+       "-break-insert --source $srcfile --function foobar" \
+       ".*Function \"foobar\" not defined in \"$srcfile\".*"
+
+    mi_gdb_test \
+       "-break-insert --source $srcfile --function main --label foobar" \
+       ".*No label \"foobar\" defined in function \"main\".*"
+
+    mi_gdb_test \
+       "-break-insert --source $srcfile" \
+       ".*Source filename requires function, label, or line offset.*"
+}
+
 test_tbreak_creation_and_listing
 test_rbreak_creation_and_listing
 
@@ -318,5 +398,7 @@ test_breakpoint_commands
 
 test_abreak_creation
 
+test_explicit_breakpoints
+
 mi_gdb_exit
 return 0
index c2057244ed324f36759e64633bdb27b7da444c3c..08885e9829c91734d838a208172a268950aacad6 100644 (file)
@@ -47,6 +47,16 @@ mi_gdb_test "[incr i]-dprintf-insert 29" \
     "$i\\^error,msg=\"-dprintf-insert: Missing <format>\"" "mi insert second breakpoint without format string"
 
 mi_gdb_test "-break-insert main" ".*" "mi insert breakpoint main"
+
+mi_gdb_test "-dprintf-insert --function main \"hello\"" \
+    "\\^done,bkpt={.*}" "explicit dprintf at main"
+
+mi_gdb_test "-dprintf-insert --source $srcfile --line $dp_location1 \"hello\"" \
+    "\\^done,bkpt={.*}" "explicit breakpoint at $srcfile:$dp_location1"
+
+mi_gdb_test "-dprintf-insert --source $srcfile \"hello\"" \
+    "\\^error,msg=\"-dprintf-insert: --source option requires --function, --label, or --line\"" "invalid explicit dprintf"
+
 mi_delete_breakpoints
 
 set bps [mi_make_breakpoint -type dprintf -func foo -file ".*mi-dprintf.c" \
@@ -61,7 +71,7 @@ mi_gdb_test "[incr i]-dprintf-insert $dp_location1 \"arg=%d, g=%d\\n\" arg g" \
                   "$i\\^done,$bps" "mi insert dprintf dp_location1"
 
 set bps {}
-lappend bps [mi_make_breakpoint -number 3 -type dprintf -func foo \
+lappend bps [mi_make_breakpoint -type dprintf -func foo \
                 -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c"]
 lappend bps [mi_make_breakpoint -type dprintf -func foo \
                 -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c" \
index 27b2ebc89c343828780c6bda6e6e6493c2485f5d..74e893dbcfe75af6251ac3a74c07c4f246113ad8 100644 (file)
@@ -2395,7 +2395,7 @@ proc mi_build_kv_pairs {attr_list {joiner ,}} {
 #
 # All arguments for the breakpoint may be specified using the options
 # number, type, disp, enabled, addr, func, file, fullanme, line,
-# thread-groups, times, ignore, script, and original-location.
+# thread-groups, cond, times, ignore, script, and original-location.
 #
 # Only if -script and -ignore are given will they appear in the output.
 # Otherwise, this procedure will skip them using ".*".
@@ -2410,17 +2410,27 @@ proc mi_make_breakpoint {args} {
     parse_args {{number .*} {type .*} {disp .*} {enabled .*} {addr .*}
        {func .*} {file .*} {fullname .*} {line .*}
        {thread-groups \\\[.*\\\]} {times .*} {ignore 0}
-       {script ""} {original-location .*}}
+       {script ""} {original-location .*} {cond ""}}
 
     set attr_list {}
     foreach attr [list number type disp enabled addr func file \
-                     fullname line thread-groups times] {
+                     fullname line thread-groups] {
        lappend attr_list $attr [set $attr]
     }
 
     set result "bkpt={[mi_build_kv_pairs $attr_list]"
 
     # There are always exceptions.
+
+    # If COND is not preset, do not output it.
+    if {[string length $cond] > 0} {
+       append result ","
+       append result [mi_build_kv_pairs [list "cond" $cond]]
+    }
+
+    append result ","
+    append result [mi_build_kv_pairs [list "times" $times]]
+
     # If SCRIPT and IGNORE are not present, do not output them.
     if {$ignore != 0} {
        append result ","