aboutsummaryrefslogtreecommitdiff
path: root/lldb/packages/Python/lldbsuite/test
diff options
context:
space:
mode:
authorEly Ronnen <elyronnen@gmail.com>2025-08-08 22:29:47 +0200
committerGitHub <noreply@github.com>2025-08-08 22:29:47 +0200
commit4d3feaea66f43758518d15e07a975e3492317b1c (patch)
tree5bad316ef044c6816a2a406a20c96d70642740a6 /lldb/packages/Python/lldbsuite/test
parentff616b4806ed6c9b9698290a9c807626aa3844f7 (diff)
downloadllvm-4d3feaea66f43758518d15e07a975e3492317b1c.zip
llvm-4d3feaea66f43758518d15e07a975e3492317b1c.tar.gz
llvm-4d3feaea66f43758518d15e07a975e3492317b1c.tar.bz2
[lldb-dap] persistent assembly breakpoints (#148061)
Resolves #141955 - Adds data to breakpoints `Source` object, in order for assembly breakpoints, which rely on a temporary `sourceReference` value, to be able to resolve in future sessions like normal path+line breakpoints - Adds optional `instructions_offset` parameter to `BreakpointResolver`
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test')
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py39
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py22
2 files changed, 44 insertions, 17 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 0b09893..939be99 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -107,17 +107,23 @@ def dump_dap_log(log_file):
class Source(object):
def __init__(
- self, path: Optional[str] = None, source_reference: Optional[int] = None
+ self,
+ path: Optional[str] = None,
+ source_reference: Optional[int] = None,
+ raw_dict: Optional[dict[str, Any]] = None,
):
self._name = None
self._path = None
self._source_reference = None
+ self._raw_dict = None
if path is not None:
self._name = os.path.basename(path)
self._path = path
elif source_reference is not None:
self._source_reference = source_reference
+ elif raw_dict is not None:
+ self._raw_dict = raw_dict
else:
raise ValueError("Either path or source_reference must be provided")
@@ -125,6 +131,9 @@ class Source(object):
return f"Source(name={self.name}, path={self.path}), source_reference={self.source_reference})"
def as_dict(self):
+ if self._raw_dict is not None:
+ return self._raw_dict
+
source_dict = {}
if self._name is not None:
source_dict["name"] = self._name
@@ -135,6 +144,19 @@ class Source(object):
return source_dict
+class Breakpoint(object):
+ def __init__(self, obj):
+ self._breakpoint = obj
+
+ def is_verified(self):
+ """Check if the breakpoint is verified."""
+ return self._breakpoint.get("verified", False)
+
+ def source(self):
+ """Get the source of the breakpoint."""
+ return self._breakpoint.get("source", {})
+
+
class NotSupportedError(KeyError):
"""Raised if a feature is not supported due to its capabilities."""
@@ -170,7 +192,7 @@ class DebugCommunication(object):
self.initialized = False
self.frame_scopes = {}
self.init_commands = init_commands
- self.resolved_breakpoints = {}
+ self.resolved_breakpoints: dict[str, Breakpoint] = {}
@classmethod
def encode_content(cls, s: str) -> bytes:
@@ -326,8 +348,8 @@ class DebugCommunication(object):
def _update_verified_breakpoints(self, breakpoints: list[Event]):
for breakpoint in breakpoints:
if "id" in breakpoint:
- self.resolved_breakpoints[str(breakpoint["id"])] = breakpoint.get(
- "verified", False
+ self.resolved_breakpoints[str(breakpoint["id"])] = Breakpoint(
+ breakpoint
)
def send_packet(self, command_dict: Request, set_sequence=True):
@@ -484,7 +506,14 @@ class DebugCommunication(object):
if breakpoint_event is None:
break
- return [id for id in breakpoint_ids if id not in self.resolved_breakpoints]
+ return [
+ id
+ for id in breakpoint_ids
+ if (
+ id not in self.resolved_breakpoints
+ or not self.resolved_breakpoints[id].is_verified()
+ )
+ ]
def wait_for_exited(self, timeout: Optional[float] = None):
event_dict = self.wait_for_event("exited", timeout=timeout)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 1567462..c51b4b1 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -59,24 +59,22 @@ class DAPTestCaseBase(TestBase):
Each object in data is 1:1 mapping with the entry in lines.
It contains optional location/hitCondition/logMessage parameters.
"""
- response = self.dap_server.request_setBreakpoints(
- Source(source_path), lines, data
+ return self.set_source_breakpoints_from_source(
+ Source(path=source_path), lines, data, wait_for_resolve
)
- if response is None or not response["success"]:
- return []
- breakpoints = response["body"]["breakpoints"]
- breakpoint_ids = []
- for breakpoint in breakpoints:
- breakpoint_ids.append("%i" % (breakpoint["id"]))
- if wait_for_resolve:
- self.wait_for_breakpoints_to_resolve(breakpoint_ids)
- return breakpoint_ids
def set_source_breakpoints_assembly(
self, source_reference, lines, data=None, wait_for_resolve=True
):
+ return self.set_source_breakpoints_from_source(
+ Source(source_reference=source_reference), lines, data, wait_for_resolve
+ )
+
+ def set_source_breakpoints_from_source(
+ self, source: Source, lines, data=None, wait_for_resolve=True
+ ):
response = self.dap_server.request_setBreakpoints(
- Source(source_reference=source_reference),
+ source,
lines,
data,
)