]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/dap/breakpoint.py
1 # Copyright 2022 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 from .server
import request
, capability
20 from .startup
import send_gdb_with_response
, in_gdb_thread
23 # Map from the breakpoint "kind" (like "function") to a second map, of
24 # breakpoints of that type. The second map uses the breakpoint spec
25 # as a key, and the gdb.Breakpoint itself as a value. This is used to
26 # implement the clearing behavior specified by the protocol, while
27 # allowing for reuse when a breakpoint can be kept.
32 def breakpoint_descriptor(bp
):
33 "Return the Breakpoint object descriptor given a gdb Breakpoint."
35 # Just choose the first location, because DAP doesn't allow
36 # multiple locations. See
37 # https://github.com/microsoft/debug-adapter-protocol/issues/13
39 (basename
, line
) = loc
.source
44 "name": os
.path
.basename(basename
),
46 # We probably don't need this but it doesn't hurt to
51 "instructionReference": hex(loc
.address
),
60 # Helper function to set some breakpoints according to a list of
63 def _set_breakpoints(kind
, specs
):
65 # Try to reuse existing breakpoints if possible.
66 if kind
in breakpoint_map
:
67 saved_map
= breakpoint_map
[kind
]
70 breakpoint_map
[kind
] = {}
73 keyspec
= frozenset(spec
.items())
74 if keyspec
in saved_map
:
75 bp
= saved_map
.pop(keyspec
)
77 # FIXME handle exceptions here
78 bp
= gdb
.Breakpoint(**spec
)
79 breakpoint_map
[kind
][keyspec
] = bp
80 result
.append(breakpoint_descriptor(bp
))
81 # Delete any breakpoints that were not reused.
82 for entry
in saved_map
.values():
87 @request("setBreakpoints")
88 def set_breakpoint(source
, *, breakpoints
=[], **args
):
89 if "path" not in source
:
93 for obj
in breakpoints
:
96 "source": source
["path"],
100 # Be sure to include the path in the key, so that we only
101 # clear out breakpoints coming from this same source.
102 key
= "source:" + source
["path"]
103 result
= send_gdb_with_response(lambda: _set_breakpoints(key
, specs
))
105 "breakpoints": result
,
109 @request("setFunctionBreakpoints")
110 @capability("supportsFunctionBreakpoints")
111 def set_fn_breakpoint(breakpoints
, **args
):
113 for bp
in breakpoints
:
116 "function": bp
["name"],
119 result
= send_gdb_with_response(lambda: _set_breakpoints("function", specs
))
121 "breakpoints": result
,
125 @request("setInstructionBreakpoints")
126 @capability("supportsInstructionBreakpoints")
127 def set_insn_breakpoints(*, breakpoints
, offset
=None, **args
):
129 for bp
in breakpoints
:
130 # There's no way to set an explicit address breakpoint
131 # from Python, so we rely on "spec" instead.
132 val
= "*" + bp
["instructionReference"]
133 if offset
is not None:
134 val
= val
+ " + " + str(offset
)
140 result
= send_gdb_with_response(lambda: _set_breakpoints("instruction", specs
))
142 "breakpoints": result
,