[3/3] Fix gdb.base/dprintf.exp and gdbserver + breakpoints always-inserted

Message ID 20201127221958.18585-4-pedro@palves.net
State New
Headers show
Series
  • Fix "set breakpoint always-inserted" + gdbserver
Related show

Commit Message

Pedro Alves Nov. 27, 2020, 10:19 p.m.
Running gdb.base/dprintf.exp against gdbserver with breakpoints
always-inserted, like:

 $ make check \
   RUNTESTFLAGS="--target_board=native-gdbserver GDBFLAGS='-ex set\ breakpoint\ always-inserted\ on'" \
   TESTS="gdb.base/dprintf.exp"

Shows a regression compared to always-inserted off:

 continue
 Continuing.
 FAIL: gdb.base/dprintf.exp: agent: always-inserted=on: 1st dprintf (timeout)

The testcase does the equivalent of this:

    (gdb) set dprintf-style gdb
 #1 (gdb) dprintf foo,"foo\n"
    Sending packet: $m555555555275,1#45...Packet received: 8b
    Dprintf 8 at 0x555555555275: file src/gdb/testsuite/gdb.base/dprintf.c, line 27.
    Sending packet: $Z0,555555555275,1#8e...Packet received: OK
 #2 (gdb) set dprintf-style agent
    (gdb)
 #3 (gdb) continue
    *hang forever*

I.e., with breakpoint always-inserted on, #1 makes GDB send a Z0
packet to gdbserver immediately, for a regular breakpoint with no
command attached, since GDB is supposed to handle the dprintf
printing.

In #2 we see the problem -- "set dprintf-style" didn't result in GDB
updating the breakpoint location on the target -- no new Z0 packet
with a command attached was sent.

And then #3 results in the program continually running into the
dprintf breakpoint and not making progress.  I.e., with "set debug
infrun 1", we see a constant stream of:

 [infrun] handle_inferior_event: status->kind = stopped, signal = GDB_SIGNAL_TRAP
 [infrun] handle_signal_stop: stop_pc=0x555555555275
 [infrun] handle_signal_stop: delayed software breakpoint trap, ignoring

The fix is to make "set dprintf-style" force reinsertion of any
inserted dprintf, vis:

 (gdb) set dprintf-style agent
 Sending packet: $Z0,555555555275,1;cmds:1,Xf,2200220034000006666f6f5c6e0027#a6...Packet received: OK
 (gdb) set dprintf-style gdb
 Sending packet: $Z0,555555555275,1#8e...Packet received: OK

gdb/ChangeLog:

	* breakpoint.c (update_dprintf_commands): Force update of all
	inserted bp_dprintf locations, and update global locations list.

gdb/testsuite/ChangeLog:

	* gdb.base/dprintf.exp (restart): Add ALWAYS_INSERTED parameter
	and handle it.
	(test_call, test_call): Update.
	(test_agent): Add ALWAYS_INSERTED parameter and pass it down to
	'restart'.  Add comment.
	(top level): Test "agent" with both breakpoint always-inserted
	"off" and "on".
---
 gdb/breakpoint.c                   |  8 ++++++++
 gdb/testsuite/gdb.base/dprintf.exp | 21 +++++++++++++++------
 2 files changed, 23 insertions(+), 6 deletions(-)

-- 
2.14.5

Patch

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index e39ca288c93..7ac00eb425e 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -8841,6 +8841,14 @@  update_dprintf_commands (const char *args, int from_tty,
       if (b->type == bp_dprintf)
 	update_dprintf_command_list (b);
     }
+
+  /* Force breakpoint reinsertion.  */
+  bp_location *loc, **loc_tmp;
+  ALL_BP_LOCATIONS (loc, loc_tmp)
+    if (loc->owner->type == bp_dprintf && loc->inserted)
+      loc->needs_update = true;
+
+  update_global_location_list (UGLL_MAY_INSERT);
 }
 
 /* Create a breakpoint with SAL as location.  Use LOCATION
diff --git a/gdb/testsuite/gdb.base/dprintf.exp b/gdb/testsuite/gdb.base/dprintf.exp
index 9fa2e64993c..4e719692f1e 100644
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -66,12 +66,14 @@  gdb_test "continue" "At foo entry.*arg=1235, g=2222.*" "2nd dprintf, gdb"
 
 # Restart GDB and set set up for testing.
 
-proc restart {} {
+proc restart {always_inserted} {
     global binfile
     global bp_location1 dp_location1
 
     clean_restart $binfile
 
+    gdb_test_no_output "set breakpoint always-inserted $always_inserted"
+
     if ![runto_main] {
 	return -1
     }
@@ -102,7 +104,7 @@  proc test_call {} {
     # output should be the same.
 
     with_test_prefix "printf" {
-	restart
+	restart "off"
 
 	gdb_test_no_output "set dprintf-style call" "set dprintf style to call"
 
@@ -112,7 +114,7 @@  proc test_call {} {
     }
 
     with_test_prefix "fprintf" {
-	restart
+	restart "off"
 
 	gdb_test_no_output "set dprintf-function fprintf" "set dprintf function"
 	gdb_test_no_output "set dprintf-channel stderr" "set dprintf channel"
@@ -135,11 +137,16 @@  if ![target_info exists gdb,noinferiorio] {
 
 # Test the "agent" style.
 
-proc test_agent {} {
+proc test_agent {always_inserted} {
     global binfile
     global gdb_prompt
 
-    restart
+    restart $always_inserted
+
+    # Note the above created the dprintfs with host style, and now
+    # we'll flip style to agent.  With breakpoint always-inserted on,
+    # this ends up testing that "set dprintf-style" resets the dprints
+    # and forces dprintf reinsertion in the target.
 
     set target_can_dprintf 1
     set msg "set dprintf style to agent"
@@ -194,7 +201,9 @@  proc test_agent {} {
 }
 
 with_test_prefix "agent" {
-    test_agent
+    foreach_with_prefix always-inserted {"off" "on"} {
+	test_agent ${always-inserted}
+    }
 }
 
 gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \