summaryrefslogtreecommitdiff
path: root/cross-project-tests
diff options
context:
space:
mode:
authorOrlando Cazalet-Hyams <orlando.hyams@sony.com>2025-08-12 13:47:33 +0100
committerGitHub <noreply@github.com>2025-08-12 13:47:33 +0100
commitba5ff57917e099b2292cf66da960464570729c38 (patch)
treee0310a18b3a54d26919ae36bc730c8d41889ae8e /cross-project-tests
parent2a4971952520b49d4db2bb734214ae2fe2e5ee34 (diff)
[Dexter] Track DAP capabilities (#152715)
Diffstat (limited to 'cross-project-tests')
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py42
1 files changed, 42 insertions, 0 deletions
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py
index 3921e7f407f0..5c27775202fa 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py
@@ -100,6 +100,36 @@ class DAPMessageLogger:
)
+# Debuggers communicate optional feature support.
+class DAPDebuggerCapabilities:
+ def __init__(self):
+ self.supportsConfigurationDoneRequest: bool = False
+ self.supportsFunctionBreakpoints: bool = False
+ self.supportsConditionalBreakpoints: bool = False
+ self.supportsHitConditionalBreakpoints: bool = False
+ self.supportsEvaluateForHovers: bool = False
+ self.supportsSetVariable: bool = False
+ self.supportsStepInTargetsRequest: bool = False
+ self.supportsModulesRequest: bool = False
+ self.supportsValueFormattingOptions: bool = False
+ self.supportsLogPoints: bool = False
+ self.supportsSetExpression: bool = False
+ self.supportsDataBreakpoints: bool = False
+ self.supportsReadMemoryRequest: bool = False
+ self.supportsWriteMemoryRequest: bool = False
+ self.supportsDisassembleRequest: bool = False
+ self.supportsCancelRequest: bool = False
+ self.supportsSteppingGranularity: bool = False
+ self.supportsInstructionBreakpoints: bool = False
+
+ def update(self, logger: Logger, feature_dict: dict):
+ for k, v in feature_dict.items():
+ if hasattr(self, k):
+ setattr(self, k, v)
+ else:
+ logger.warning(f"DAP: Unknown support flag: {k}")
+
+
# As DAP does not give us a trivially query-able process, we are responsible for maintaining our own state information,
# including what breakpoints are currently set, and whether the debugger is running or stopped.
# This class holds all state that is set based on events sent by the debug adapter; most responses are forwarded through
@@ -142,6 +172,9 @@ class DAPDebuggerState:
# Map of DAP breakpoint IDs to resolved instruction addresses.
self.bp_addr_map = {}
+ # DAP features supported by the debugger.
+ self.capabilities = DAPDebuggerCapabilities()
+
def set_response(self, req_id: int, response: dict):
if len(self.responses) > req_id:
self.responses[req_id] = response
@@ -315,6 +348,9 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta):
and debugger_state.thread is None
):
debugger_state.thread = event_details["threadId"]
+ elif event_type == "capabilities":
+ # Unchanged capabilites may not be included.
+ debugger_state.capabilities.update(logger, event_details)
# There are many events we do not care about, just skip processing them.
else:
pass
@@ -338,6 +374,12 @@ class DAP(DebuggerBase, metaclass=abc.ABCMeta):
debugger_state.frame_map = [
stackframe["id"] for stackframe in message["body"]["stackFrames"]
]
+ # The debugger communicates which optional DAP features are
+ # supported in its initalize response.
+ if message["command"] == "initialize" and message["success"] == True:
+ body = message.get("body")
+ if body:
+ debugger_state.capabilities.update(logger, body)
def _colorize_dap_message(message: dict) -> dict:
colorized_message = copy.deepcopy(message)