Creating an iOS Debugger: Part 2: Introduction to Breakpoints

Welcome to part 2 of my debugger series. In today’s post, we will be investigating a crucial part of a debugger, Breakpoints.

What is a breakpoint?

Many programmers out there will know what breakpoints are and may have used them at some point before. I will briefly give an overview of what breakpoints are for anybody who hasn’t though.
At the highest level, a breakpoint is something a debugger will add to a process to halt its execution at a specific point. Some breakpoints can also halt a process if a certain condition is met (e.g. if a variable is equal to let’s say 55). Halting the process allows the developer to then debug and inspect aspects of the program at runtime (but I’m sure you already knew this!)

Breakpoint in Visual StudioBreakpoint in Visual Studio

That’s cool, but how do breakpoints work?

To answer that, we must first note that there are a few different types of breakpoints that can be used. In this post I will be covering software breakpoints and hardware breakpoints, the two main types of breakpoint.

Software breakpoint

A software breakpoint is, as you can tell by the name, one that is implemented in software. In most cases, software breakpoints are implemented as an assembly instruction. The ARM architecture has a software breakpoint instruction BKPT. x86 has the interrupt instruction INT which isn’t purposely built as a software breakpoint instruction but works just as well as one.

When these software breakpoints are executed by the processor, they will cause the execution of the program to halt, and will throw an exception of some type. That sounds like a bad thing, but the debugger can catch the exception and then start debugging the now paused process.

Hardware breakpoint

A hardware breakpoint is a type of breakpoint that it built directly into the processor. These breakpoints are programmed to monitor the process address bus for an address. When the address is matched, the CPU is sent a signal to halt the current process. From here, the debugger can start debugging the process.

Most modern architectures have a set of debug registers which can be programmed by somebody to monitor addresses.

Limitations

Both software breakpoints and their hardware counterparts have limitations associated with them.

As hardware breakpoints are directly part of the processor, there can only be a small number of hardware breakpoints at a time. This means it isn’t possible to set many breakpoints at once.

Software breakpoints can be used any number of times by replacing an instruction at an address with the corresponding BKPT opcode. This is perfectly adequate in 99% of cases, but they can be problematic in programs that involve just-in-time compilation (or JIT). This is because the BKPT instruction can be easily overwritten or ignored.
Another problem with software breakpoints is returning to execute original code. First, the original opcode must be written back to the process. As the breakpoint instruction is still in the instruction pipeline, the cpu cache must be flushed or the processor will still try and execute the BKPT instruction.

Something.. Something.. Software breakpoint example

Here is a small example of using a software breakpoint. We will be revisiting breakpoints later on (obviously).

#define noinline __attribute__((noinline))

 noinline void Test(int a) { 
    asm("BKPT"); // hardcode in a software breakpoint 
}

 int main() { 
    Test(0x1337);
    return 0; 
}

Other types of “breakpoints”

Instruction breakpoints aren’t the only type of breakpoint out there. Another commonly used type of breakpoint is a watchpoint. Watchpoints are placed on variables/data in memory and will cause execution of a process to stop based on certain conditions related to the data. For example a write-watchpoint will trigger if the data being watched is edited in some way.

Conclusion

I hope that this post has helped better explain breakpoints. We will be coming back to breakpoints in a later post once we have a skeleton debugger.

That’s all for now, please don’t forget to share this series with your nerd friends -Satori

Oh, and happy halloween!

Next time: Part 3: Exceptions