[llvm] [Dexter] Add DAP instruction and function breakpoint handling (PR #152718)

Stephen Tozer via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 03:07:09 PDT 2025


================
@@ -524,45 +550,98 @@ def clear_breakpoints(self):
     def _add_breakpoint(self, file, line):
         return self._add_conditional_breakpoint(file, line, None)
 
+    def add_function_breakpoint(self, name: str):
+        if not self._debugger_state.capabilities.supportsFunctionBreakpoints:
+            raise DebuggerException("Debugger does not support function breakpoints")
+        new_id = self.get_next_bp_id()
+        self.function_bp_info[new_id] = name
+        self.pending_function_breakpoints = True
+        return new_id
+
+    def add_instruction_breakpoint(self, addr: str):
+        if not self._debugger_state.capabilities.supportsInstructionBreakpoints:
+            raise DebuggerException("Debugger does not support instruction breakpoints")
+        new_id = self.get_next_bp_id()
+        self.instruction_bp_info[new_id] = addr
+        self.pending_instruction_breakpoints = True
+        return new_id
+
     def _add_conditional_breakpoint(self, file, line, condition):
         new_id = self.get_next_bp_id()
         self.file_to_bp[file].append(new_id)
         self.bp_info[new_id] = (file, line, condition)
         self.pending_breakpoints = True
         return new_id
 
+    def _update_breakpoint_ids_after_request(
+        self, dex_bp_ids: list, response: dict
+    ):
+        dap_bp_ids = [bp["id"] for bp in response["body"]["breakpoints"]]
+        if len(dex_bp_ids) != len(dap_bp_ids):
+            self.context.logger.error(
+                f"Sent request to set {len(dex_bp_ids)} breakpoints, but received {len(dap_bp_ids)} in response."
+            )
+        visited_dap_ids = set()
+        for i, dex_bp_id in enumerate(dex_bp_ids):
+            dap_bp_id = dap_bp_ids[i]
+            self.dex_id_to_dap_id[dex_bp_id] = dap_bp_id
+            # We take the mappings in the response as the canonical mapping, meaning that if the debug server has
+            # simply *changed* the DAP ID for a breakpoint we overwrite the existing mapping rather than adding to
+            # it, but if we receive the same DAP ID for multiple Dex IDs *then* we store a one-to-many mapping.
+            if dap_bp_id in visited_dap_ids:
+                self.dap_id_to_dex_ids[dap_bp_id].append(dex_bp_id)
+            else:
+                self.dap_id_to_dex_ids[dap_bp_id] = [dex_bp_id]
+                visited_dap_ids.add(dap_bp_id)
+
     def _flush_breakpoints(self):
-        if not self.pending_breakpoints:
-            return
-        for file in self.file_to_bp.keys():
-            desired_bps = self._get_desired_bps(file)
+        # Normal and conditional breakpoints.
+        if self.pending_breakpoints:
+            self.pending_breakpoints = False
+            for file in self.file_to_bp.keys():
+                desired_bps = self._get_desired_bps(file)
+                request_id = self.send_message(
+                    self.make_set_breakpoint_request(file, desired_bps)
+                )
+                result = self._await_response(request_id, 10)
+                if not result["success"]:
+                    raise DebuggerException(f"could not set breakpoints for '{file}'")
+                # The debug adapter may have chosen to merge our breakpoints. From here we need to identify such cases and
+                # handle them so that our internal bookkeeping is correct.
+                dex_bp_ids = self.get_current_bps(file)
+                self._update_breakpoint_ids_after_request(dex_bp_ids, result)
+
+        # Funciton breakpoints.
----------------
SLTozer wrote:

```suggestion
        # Function breakpoints.
```

https://github.com/llvm/llvm-project/pull/152718


More information about the llvm-commits mailing list