Skip to content

Breakpoints and Watchpoints

The BreakpointManager subsystem wraps OpenOCD’s bp, rbp, wp, and rwp commands to manage breakpoints that pause execution at a specific instruction address, and watchpoints that trigger on data memory access.

Access it through the session:

# Async
session.breakpoints
# Sync
sync_session.breakpoints

Breakpoints come in two flavors, each with different tradeoffs:

Software breakpoints replace the instruction at the target address with a special breakpoint instruction (e.g. BKPT on ARM). When the CPU executes that address, it traps into debug mode. The original instruction is restored transparently. Software breakpoints are plentiful but require writable memory — they do not work in flash unless the debugger patches flash.

Hardware breakpoints use dedicated comparator registers built into the CPU core (e.g. the Flash Patch and Breakpoint unit on Cortex-M). They work on any memory region including flash, but the number available is limited — typically 4 to 8 on Cortex-M devices.

add(address, length=2, hw=False) sets a breakpoint at the given instruction address.

The length parameter indicates the instruction size:

  • 2 for Thumb instructions (16-bit, the default on Cortex-M)
  • 4 for ARM instructions (32-bit)
import asyncio
from openocd import Session
async def main():
async with await Session.connect() as session:
# Software breakpoint on a Thumb instruction
await session.breakpoints.add(0x0800_1234, length=2)
# Hardware breakpoint on an ARM instruction
await session.breakpoints.add(0x0800_5678, length=4, hw=True)
asyncio.run(main())

remove(address) removes the breakpoint at the specified address.

async with await Session.connect() as session:
await session.breakpoints.add(0x0800_1234)
# ... debug ...
await session.breakpoints.remove(0x0800_1234)

list() returns all active breakpoints as a list of Breakpoint dataclasses.

async with await Session.connect() as session:
await session.breakpoints.add(0x0800_1234)
await session.breakpoints.add(0x0800_5678, hw=True)
bps = await session.breakpoints.list()
for bp in bps:
print(f"BP #{bp.number}: 0x{bp.address:08X} "
f"type={bp.type} len={bp.length} enabled={bp.enabled}")

Watchpoints monitor data memory access rather than instruction execution. They trigger when the CPU reads from, writes to, or accesses a specific address range.

add_watchpoint(address, length, access="rw") creates a data watchpoint.

The access parameter controls which operations trigger the watchpoint:

  • "r" — read access only
  • "w" — write access only
  • "rw" — any access (read or write)
async with await Session.connect() as session:
# Break on any write to a 4-byte variable
await session.breakpoints.add_watchpoint(
address=0x2000_0100,
length=4,
access="w"
)
# Break on any access to a buffer
await session.breakpoints.add_watchpoint(
address=0x2000_0200,
length=16,
access="rw"
)

remove_watchpoint(address) removes the watchpoint at the given address.

await session.breakpoints.remove_watchpoint(0x2000_0100)

list_watchpoints() returns all active watchpoints.

async with await Session.connect() as session:
await session.breakpoints.add_watchpoint(0x2000_0100, 4, "w")
wps = await session.breakpoints.list_watchpoints()
for wp in wps:
print(f"WP #{wp.number}: 0x{wp.address:08X} "
f"len={wp.length} access={wp.access}")
FieldTypeDescription
numberintBreakpoint index
typeLiteral["hw", "sw"]Hardware or software breakpoint
addressintInstruction address
lengthintInstruction length in bytes (2 = Thumb, 4 = ARM)
enabledboolWhether the breakpoint is active
FieldTypeDescription
numberintWatchpoint index
addressintWatched memory address
lengthintSize of watched region in bytes
accessLiteral["r", "w", "rw"]Access type that triggers the watchpoint

Breakpoint and watchpoint operations raise BreakpointError (a subclass of OpenOCDError) when OpenOCD reports a failure.

from openocd.breakpoints import BreakpointError
try:
session.breakpoints.add(0x0800_1234, hw=True)
except BreakpointError as e:
print(f"Could not set breakpoint: {e}")

Common failure causes:

  • No hardware breakpoint comparators available (reduce the number of HW breakpoints)
  • Target not halted when attempting to set a software breakpoint
  • Invalid address or length
MethodReturn TypeDescription
add(address, length=2, hw=False)NoneSet a breakpoint
remove(address)NoneRemove a breakpoint
list()list[Breakpoint]List active breakpoints
add_watchpoint(address, length, access="rw")NoneSet a data watchpoint
remove_watchpoint(address)NoneRemove a watchpoint
list_watchpoints()list[Watchpoint]List active watchpoints