diff options
| author | Orlando Cazalet-Hyams <orlando.hyams@sony.com> | 2025-08-12 13:47:33 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-12 13:47:33 +0100 |
| commit | ba5ff57917e099b2292cf66da960464570729c38 (patch) | |
| tree | e0310a18b3a54d26919ae36bc730c8d41889ae8e /cross-project-tests | |
| parent | 2a4971952520b49d4db2bb734214ae2fe2e5ee34 (diff) | |
[Dexter] Track DAP capabilities (#152715)
Diffstat (limited to 'cross-project-tests')
| -rw-r--r-- | cross-project-tests/debuginfo-tests/dexter/dex/debugger/DAP.py | 42 |
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) |
