The GDB command to set breakpoints, break does not immediately cause a RSP interaction. GDB only actually sets breakpoints immediately before execution (for example by a continue or step command) and immediately clears them when a breakpoint is hit. This minimizes the risk of a program being left with breakpoints inserted, for example when a serial link fails.
The RSP packet exchanges to implement the GDB
break command and a subsequent
continue are shown as a sequence diagram in Figure 3.7. In this example a breakpoint is set
at the start of the function simputs ()
.
The command sequence is very similar to that of the plain continue command (see Section 3.2.7). With two key differences.
First, immediately before the c packet, the
breakpoint is set with a Z0 packet. Secondly, as
soon as the register cache has been refreshed (g
packet) when control returns, the program counter is stepped back to
re-execute the instruction at the location of the TRAP with a
P packet and the breakpoint is cleared with a
z0 packet. In this case only a single breakpoint
(at location 0x1150, the start of function
simputs ()
) is set. If there were multiple
breakpoints, they would all be set immediately before the
c packet and cleared immediately after the
g packet.
In this example, the client ensures that the program counter is set to point to the TRAP instruction just executed, not the instruction following.
An alternative to adjusting the program counter in the target is to
use the GDB architecture value
decr_pc_after_break ()
value to specify
that the program counter should be wound back. In this case an
additional P packet would be used to reset the
program counter register. Whichever approach is used, it means that
when execution resumes, the instruction which was replaced by a trap
instruction will be executed first.
Note | |
---|---|
Perhaps rather surprisingly, it is the responsibility of the target RSP server, not the GDB client to keep track of the substituted instructions. |
Through this exchange, the GDB client shows the following output:
(gdb) break simputs Breakpoint 1 at 0x1150: file utils.c, line 90. (gdb) c Continuing. Breakpoint 1, simputs (str=0x1290 "Hello World!\n") at utils.c:90 90 for( i = 0; str[i] != '\0' ; i++ ) { (gdb)
The example here showed the use of a memory breakpoint (also known as a software breakpoint). GDB also supports use of hardware watchpoints explicitly through the hbreak command. These behave analogously to memory breakpoints in RSP, but using z1 and Z1 packets.
If a RSP server implementation does not support hardware breakpoints it should return an empty packet to any request for insertion or deletion.