From 0c3bfda0ac6044b3515193f25b1555d912e22baf Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 5 Jul 2024 09:57:03 -0600 Subject: [PATCH] Make DAP instruction breakpoints unverified Currently, when a DAP client uses setInstructionBreakpoints, the resulting breakpoints are created as "verified", even though there is no symbol file and thus the breakpoint can't possibly have a source location. This patch changes the DAP code to assume that all breakpoints are unverified before launch. Reviewed-by: Keith Seitz --- gdb/python/lib/gdb/dap/breakpoint.py | 9 ++- gdb/testsuite/gdb.dap/insn-bp.exp | 90 ++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.dap/insn-bp.exp diff --git a/gdb/python/lib/gdb/dap/breakpoint.py b/gdb/python/lib/gdb/dap/breakpoint.py index 0ffb5074670..d44e50b0056 100644 --- a/gdb/python/lib/gdb/dap/breakpoint.py +++ b/gdb/python/lib/gdb/dap/breakpoint.py @@ -104,11 +104,16 @@ breakpoint_map = {} @in_gdb_thread def _breakpoint_descriptor(bp): "Return the Breakpoint object descriptor given a gdb Breakpoint." + # If there are no objfiles (that is, before the launch request), + # we consider all breakpoints to be pending. This is done to work + # around the gdb oddity that setting a breakpoint by address will + # always succeed. + pending = bp.pending or len(gdb.objfiles()) == 0 result = { "id": bp.number, - "verified": not bp.pending, + "verified": not pending, } - if bp.pending: + if pending: result["reason"] = "pending" if bp.locations: # Just choose the first location, because DAP doesn't allow diff --git a/gdb/testsuite/gdb.dap/insn-bp.exp b/gdb/testsuite/gdb.dap/insn-bp.exp new file mode 100644 index 00000000000..e98eb8c3935 --- /dev/null +++ b/gdb/testsuite/gdb.dap/insn-bp.exp @@ -0,0 +1,90 @@ +# Copyright 2024 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test instruction breakpoint resolution. + +require allow_dap_tests + +load_lib dap-support.exp + +standard_testfile basic-dap.c + +if {[build_executable ${testfile}.exp $testfile $srcfile] == -1} { + return +} + +# Get the address of a function. Make sure the inferior is running +# first -- on the ARM builder, the function address changed during +# startup, and we want to find the final relocated address. +clean_restart $testfile +if {![runto_main]} { + return +} +set addr [get_var_address address_breakpoint_here] +gdb_exit + +if {[dap_initialize] == ""} { + return +} + +set obj [dap_check_request_and_response "set breakpoint by address" \ + setInstructionBreakpoints \ + [format {o breakpoints [a [o instructionReference [s %s]]]} \ + $addr]] +set bpno [dap_get_breakpoint_number $obj] + +set bp [lindex [dict get [lindex $obj 0] body breakpoints] 0] +gdb_assert {[dict get $bp verified] == "false"} \ + "breakpoint is not verified" + +dap_check_request_and_response "configurationDone" configurationDone + +if {[dap_launch $testfile] == ""} { + return +} +dap_wait_for_event_and_check "inferior started" thread "body reason" started + +# While waiting for the stopped event, we should receive breakpoint +# changed events. +lassign [dap_wait_for_event_and_check "stopped at breakpoint" stopped \ + "body reason" breakpoint \ + "body hitBreakpointIds" $bpno] unused objs +set found_bp_event 0 +foreach obj $objs { + if { [dict get $obj "type"] != "event" } { + continue + } + + if { [dict get $obj "event"] != "breakpoint" } { + continue + } + + set body [dict get $obj "body"] + + if { [dict get $body "reason"] != "changed" } { + continue + } + + set breakpoint [dict get $body breakpoint] + gdb_assert {[dict get $breakpoint id] == $bpno} \ + "breakpoint modification event has correct id" + gdb_assert {[dict get $breakpoint source name] == "basic-dap.c"} \ + "breakpoint modification event has source" + set found_bp_event 1 +} + +gdb_assert {$found_bp_event} "found the breakpoint event" + +dap_shutdown -- 2.39.5