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

5. Expression
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

Now that you’ve learned how to set breakpoints, it’s time to learn how to query and manipulate the software you’re debugging. In this chapter, you’ll learn about the expression command, which allows you to inspect variables and execute arbitrary code. This is kind of a big deal, because you can declare, initialize and inject code on the fly without recompiling your program!

Formatting With p and po

You might be familiar with the common debugging command, po. po is used to display information in your program or execute code. If lldb knows how to interpret the value you’ve po‘d, it will be able to interpret that value and display meaningful information to you. For example lldb can interpret: a C int, Objective-C NSObject or a Swift struct, a variable in source code, a register’s value, etc.

If you do a quick help po in the lldb console, you’ll find po is actually a shorthand expression for expression -O --. The -O argument is used to print the object’s description.

po’s often overlooked sibling, p, is another abbreviation with the -O option omitted, resulting in expression --. The format of what p will print out is dependent on the LLDB type system. LLDB’s type formatting helps determine a variable’s description in lldb and is fully customizable.

In the following sections, you’ll learn how to modify the output of both p and po to be more useful for your debugging needs.

You can influence the content of po in the source code of a debugged program. Likewise, one can control the formatting of what p displays via lldb’s options/public APIs.

Modifying an Object’s Description

In order to change how lldb displays an object using po, you needs to modify an object’s description in the source code. You will continue using the Signals project for this chapter.

override var description: String {
  return "Yay! debugging " + super.description
}
print("\(self)")

(lldb) po self
Yay! debugging <Signals.MainViewController: 0x14851c520>
override var debugDescription: String {
  return "debugDescription: " + super.debugDescription
}
(lldb) po self
debugDescription: Yay! debugging <Signals.MainViewController: 0x15c608650>
(lldb) image lookup -rn '\ debugDescription\]'
(lldb) po self.view!.layer.description
"<CALayer: 0x600002e9eb00>"
(lldb) po self.view!.layer
<CALayer:0x600001829a80; name = "VC:Signals.MainViewController"; position = CGPoint (195 422); bounds = CGRect (0 0; 390 844); delegate = <UITableView: 0x131065400; frame = (0 0; 390 844); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x600001608960>; layer = <CALayer: 0x600001829a80>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; dataSource: Yay! debugging <Signals.MainViewController: 0x132020a70>>; sublayers = (<CALayer: 0x600001829d40>, <CALayer: 0x600001829d80>); masksToBounds = YES; allowsGroupOpacity = YES; name = VC:Signals.MainViewController; backgroundColor = <CGColor 0x600003c56dc0> [<CGColorSpace 0x600003c721c0> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 0.980392 0.980392 0.980392 1 )>
(lldb) p self
Signals.MainViewController) $R2 = 0x0000000132020a70 {
  UIKit.UITableViewController = {
    baseUIViewController@0 = {
      baseUIResponder@0 = {
        baseNSObject@0 = {
          isa = Signals.MainViewController
        }
      }
      _overrideTransitioningDelegate = 0x0000000000000000
      _view = some {
        some = 0x0000000131065400 {
          baseUIScrollView@0 = {
...
(lldb) p $R2
(lldb) type summary add Signals.MainViewController --summary-string "Wahoo!"
(lldb) p self
(lldb) (Signals.MainViewController) $R7 = 0x0000000132020a70 Wahoo!
(lldb) type summary clear
print("\(self)")
dump(self)

Swift vs Objective-C Debugging Contexts

It’s important to note there are two debugging contexts when debugging your program: a non-Swift debugging context and a Swift context. By default, when you stop in Objective-C code, lldb will use the non-Swift (Objective-C, C, C++) debugging context, and if you’re stopped in Swift code, lldb will use the Swift context. Sounds logical, right?

(lldb) po [UIApplication sharedApplication]
error: <EXPR>:8:16: error: expected ',' separator
[UIApplication sharedApplication]
               ^
              ,
(lldb) expression -l objc -O -- [UIApplication sharedApplication]
(lldb) po UIApplication.shared
(lldb) po UIApplication.shared
error: <user expression 2>:1:15: property 'shared' not found on object of type 'UIApplication'
UIApplication.shared

User Defined Variables

As you saw earlier, lldb will automatically create local variables on your behalf when printing out objects. You can create your own variables as well.

(lldb) po id test = [NSObject new]
(lldb) po test
error: <user expression 4>:1:1: function 'test' with unknown type must be given a function type
test
^~~~
(lldb) po id $test = [NSObject new]
(lldb) po $test
(lldb) expression -l swift -O -- $test
(lldb) expression -l swift -O -- $test.description
error: <EXPR>:3:1: error: cannot find '$test' in scope
$test
^~~~~
Signals.MainContainerViewController.viewDidLoad

(lldb) p self
(lldb) po $R0.title
error: use of undeclared identifier '$R0'
(lldb) expression -O -l swift -- $R0.title
▿ Optional<String>
  - some : "Quarterback"
(lldb) expression -l swift -- $R0.title = "💩💩💩💩💩"

(lldb) expression -l swift -O -- $R0.viewDidLoad()
(lldb) expression -l swift -O -i 0 -- $R0.viewDidLoad()

Code Injection

You’re not just limited to defining data in lldb. You can also create functions, classes, and methods on the fly through lldb! In order to persist these values, you’ll need to prepend a dollar sign to the code/class just like you did with the test variable earlier.

(lldb) expression -l swift -- func $donothing() -> Int { return 4 }
(lldb) exp -l swift -- $donothing()
(Int) $R5 = 4
(lldb) exp -l swift -- $donothing
() $R6 = 0x0000000102e85770
(lldb) memory region 0x0000000102e85770
[0x0000000102e84000-0x0000000102e88000) r-x

Type Formatting

One of the nice options lldb has is the ability to format the output of basic data types. This makes lldb a great tool to learn how the compiler formats basic C types. This is a must to know when you’re exploring at the assembly level, which you’ll do later in this book.

(lldb) expression -G x -- 10
(int) $0 = 0x0000000a
(lldb) p/x 10
(lldb) p/t 10
(lldb) p/t -10
(lldb) p/t 10.0
(lldb) p/d 'D'
(lldb) p/c 2051829580
(lldb) expression -f Y -- 2051829580
(int) $0 = 4c 6f 4c 7a             LoLz

Key Points

  • The po command, like Swift’s print function, allows you to view the description and debugDescription properties of objects.
  • The p command, like Swift’s dump function, gives you information about the internals of an object.
  • Variables in an lldb session begin with a $ and are valid for the entire session.
  • Switch between language contexts in lldb using expression -l <language> -O --.
  • When you pause the debugger using the button in Xcode you will probably be in an Objective-C context.
  • You can use the expression command to add functions and inject code into an application without recompiling.
  • expression supports GDB type formatters using -G as well as its own using -f.

Where to Go From Here?

Pat yourself on the back — this was another jam-packed round of what you can do with the expression command. Try exploring some of the other expression options yourself by executing help expression and see if you can figure out what they do.

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