diff options
author | Tom Tromey <tromey@adacore.com> | 2023-05-18 11:14:08 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2023-06-12 12:10:15 -0600 |
commit | d294a0fc26891eaa8826d19f61db9ce7f7399c03 (patch) | |
tree | 751eeb3695a6c9989ee1790421950ebf076036c6 /gdb/python/lib | |
parent | 7cb909c4091c156a8242f799e18af57d702da560 (diff) | |
download | gdb-d294a0fc26891eaa8826d19f61db9ce7f7399c03.zip gdb-d294a0fc26891eaa8826d19f61db9ce7f7399c03.tar.gz gdb-d294a0fc26891eaa8826d19f61db9ce7f7399c03.tar.bz2 |
Implement DAP conditional breakpoints
I realized that I had only implemented DAP breakpoint conditions for
exception breakpoints, and not other kinds of breakpoints. This patch
corrects the oversight.
Diffstat (limited to 'gdb/python/lib')
-rw-r--r-- | gdb/python/lib/gdb/dap/breakpoint.py | 69 |
1 files changed, 53 insertions, 16 deletions
diff --git a/gdb/python/lib/gdb/dap/breakpoint.py b/gdb/python/lib/gdb/dap/breakpoint.py index ad01933..20e65aa 100644 --- a/gdb/python/lib/gdb/dap/breakpoint.py +++ b/gdb/python/lib/gdb/dap/breakpoint.py @@ -63,6 +63,14 @@ def breakpoint_descriptor(bp): } +# Extract entries from a hash table and return a list of them. Each +# entry is a string. If a key of that name appears in the hash table, +# it is removed and pushed on the result list; if it does not appear, +# None is pushed on the list. +def _remove_entries(table, *names): + return [table.pop(name, None) for name in names] + + # Helper function to set some breakpoints according to a list of # specifications and a callback function to do the work of creating # the breakpoint. @@ -78,11 +86,20 @@ def _set_breakpoints_callback(kind, specs, creator): result = [] for spec in specs: keyspec = frozenset(spec.items()) + + (condition, hit_condition) = _remove_entries(spec, "condition", "hitCondition") + if keyspec in saved_map: bp = saved_map.pop(keyspec) else: # FIXME handle exceptions here bp = creator(**spec) + + if condition is not None: + bp.condition = condition + if hit_condition is not None: + bp.ignore_count = hit_condition + breakpoint_map[kind][keyspec] = bp result.append(breakpoint_descriptor(bp)) # Delete any breakpoints that were not reused. @@ -98,9 +115,22 @@ def _set_breakpoints(kind, specs): return _set_breakpoints_callback(kind, specs, gdb.Breakpoint) +# Turn a DAP SourceBreakpoint, FunctionBreakpoint, or +# InstructionBreakpoint into a "spec" that is used by +# _set_breakpoints. SPEC is a dictionary of parameters that is used +# as the base of the result; it is modified in place. +def _basic_spec(bp_info, spec): + for name in ("condition", "hitCondition"): + if name in bp_info: + spec[name] = bp_info[name] + return spec + + # FIXME we do not specify a type for 'source'. # FIXME 'breakpoints' is really a list[SourceBreakpoint]. @request("setBreakpoints") +@capability("supportsHitConditionalBreakpoints") +@capability("supportsConditionalBreakpoints") def set_breakpoint(*, source, breakpoints: Sequence = (), **args): if "path" not in source: result = [] @@ -108,10 +138,13 @@ def set_breakpoint(*, source, breakpoints: Sequence = (), **args): specs = [] for obj in breakpoints: specs.append( - { - "source": source["path"], - "line": obj["line"], - } + _basic_spec( + obj, + { + "source": source["path"], + "line": obj["line"], + }, + ) ) # Be sure to include the path in the key, so that we only # clear out breakpoints coming from this same source. @@ -128,9 +161,12 @@ def set_fn_breakpoint(*, breakpoints: Sequence, **args): specs = [] for bp in breakpoints: specs.append( - { - "function": bp["name"], - } + _basic_spec( + bp, + { + "function": bp["name"], + }, + ) ) result = send_gdb_with_response(lambda: _set_breakpoints("function", specs)) return { @@ -151,9 +187,12 @@ def set_insn_breakpoints( if offset is not None: val = val + " + " + str(offset) specs.append( - { - "spec": val, - } + _basic_spec( + bp, + { + "spec": val, + }, + ) ) result = send_gdb_with_response(lambda: _set_breakpoints("instruction", specs)) return { @@ -162,16 +201,14 @@ def set_insn_breakpoints( @in_gdb_thread -def _catch_exception(filterId, condition=None, **args): +def _catch_exception(filterId, **args): if filterId == "assert": - args = ["-catch-assert"] + cmd = "-catch-assert" elif filterId == "exception": - args = ["-catch-exception"] + cmd = "-catch-exception" else: raise Exception(f"Invalid exception filterID: {filterId}") - if condition is not None: - args.extend(["-c", condition]) - result = gdb.execute_mi(*args) + result = gdb.execute_mi(cmd) # A little lame that there's no more direct way. for bp in gdb.breakpoints(): if bp.number == result["bkptno"]: |