Chapters

Hide chapters

Advanced Apple Debugging & Reverse Engineering

Fourth Edition · iOS 16, macOS 13.3 · Swift 5.8, Python 3 · Xcode 14

Section I: Beginning LLDB Commands

Section 1: 10 chapters
Show chapters Hide chapters

Section IV: Custom LLDB Commands

Section 4: 8 chapters
Show chapters Hide chapters

8. Watchpoints
Written by Walter Tyree

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

You’ve learned how to create breakpoints on executable code; that is, memory that has read and execute permissions. But using only breakpoints leaves out an important component to debugging — you can monitor when the instruction pointer executes an address, but with breakpoints you can’t monitor when memory is being read or written to. You can’t monitor value changes to instantiated Swift objects on the heap, nor can you monitor reads to a particular address (say, a hardcoded string) in memory. This is where a watchpoint comes into play.

A watchpoint is a special type of breakpoint that can monitor reads or writes to a particular value in memory and is not limited to executable code as are breakpoints. However, there are limitations to using watchpoints: there are a finite amount of watchpoints permitted per architecture (typically 4) and the “watched” size of memory usually caps out at 8 bytes.

Watchpoint Best Practices

Like all debugging techniques, a watchpoint is a another tool in the debugging toolbox. You’ll likely not use this tool very often, but it can be extremely useful in certain situations. Watchpoints are great for:

  • Tracking an allocated Swift/Objective-C object when you don’t know how a property is getting set, i.e. via direct ivar access, Swift inout parameter initialization, Objective-C property setter method, Swift property setter method, hardcoded offset access, or other methods.
  • Monitoring when a hardcoded string is being utilized, such as in a print/printf/NSLog/cout function call.
  • Monitoring the instruction pointer for a particular type of assembly instruction.

You should use a watchpoint when a value is getting set. You’ll learn about a different tool in an upcoming chapter, the MallocStackLogging environment variable, to monitor when an object is being allocated.

Breakpoints Limitations

Watchpoints are great for discovering when a particular piece of memory is being read or written to. A practical example of this is when an instance variable is written to a previously allocated instance created from the heap, such as in an Objective-C/Swift class instance.

class SomeClass {
  var heresAVariable: Int = 0
}

func modifyVal(_ i : inout Int) { i = 4 }

var c = SomeClass()
modifyVal(&c.heresAVariable)

Finding a Property’s Offset

You’ll explore how to use watchpoints in lieu of a breakpoint to catch a particular write in memory on a singleton.

(lldb) language objc class-table dump UnixSignalHandler -v
isa = 0x100acc5d8 name = UnixSignalHandler instance size = 56 num ivars = 4 superclass = NSObject
  ivar name = source type = id size = 8 offset = 24
  ivar name = _shouldEnableSignalHandling type = bool size = 1 offset = 32
  ivar name = _signals type = id size = 8 offset = 40
  ivar name = _sharedUserDefaults type = id size = 8 offset = 48
  instance method name = initPrivate type = @16@0:8
  instance method name = appendSignal:sig: type = v28@0:8^{__siginfo=iiiiIi^v(sigval=i^v)q[7Q]}16i24
  instance method name = setShouldEnableSignalHandling: type = v20@0:8B16
 ...

(lldb) p/x 0x600002ce8940 + 32
(lldb) watchpoint set expression -s 1 -w write -- $0

The Xcode GUI Watchpoint Equivalent

Xcode provides a GUI for setting watchpoints. You could perform the equivalent of the above methods by setting a breakpoint on the creation method of the UnixSignalHandler singleton, then set a watchpoint via the GUI. First though, you need to delete the watchpoint you just made.

(lldb) watchpoint delete
About to delete all watchpoints, do you want to do that?: [Y/n] Y
All watchpoints removed. (1 watchpoints)
(lldb) c

Other Watchpoint Tidbits

Fortunately, the syntax for watchpoints is very similar to the syntax for breakpoints. You can delete, disable, enable, list, command, or modify them just as you would using lldb’s breakpoint syntax.

(lldb) watchpoint list  -b
Number of supported hardware watchpoints: 4
Current watchpoints:
Watchpoint 2: addr = 0x60000161be60 size = 1 state = enabled type = w
(lldb) watchpoint modify 2 -c '*(BOOL*)0x60000161be60 == 0'
(lldb) watchpoint modify 2
(lldb) watchpoint command add 2
Enter your debugger command(s).  Type 'DONE' to end.
> bt 5
> continue
> DONE
(lldb) watchpoint command delete 2

Key Points

  • Watchpoints can monitor memory addresses for read, write, or read_write actions.
  • The watchpoint command has similar subcommands to breakpoints such as: list, delete, and disable.
  • Use watchpoint modify to add conditions to how often a watchpoint should fire.
  • Use watchpoint command when you want triggering of the watchpoint to do more than just pause execution of the code.
  • You are limited to four watchpoints at a time.
  • Watchpoints shine when you are tracking a variable that seems to be changing outside of its official accessor methods.
  • Find the memory addresses of variables in the instance of an object using class-table dump.

Where to Go From Here?

Watchpoints tend to play very nicely with those who understand how an executable is laid out in memory. This layout, known as Mach-O, will be discussed in detail in the “Low Level” section. Combining this knowledge with watchpoints, you can watch when strings are referenced, or when static pointers are initialized, without having to tediously track the locations at runtime.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now