Search code examples
swiftlldb

Evaluate Swift expressions in LLDB


I want to define a Swift extension, including a method / computed var, only for LLDB debugging purposes. Here is the regular Swift code:

extension Collection where Self.Element == Int {
  var elementsOver30: [Self.Element]? {
    return self.filter { $0 > 30 }
  }
}

How can I define elementsOver30 in this example in pure LLDB? I think expression command is the right tool to use, but I sometimes get parsing errors.

Also, is there an equivalent syntax for other Swift symbols in LLDB, like structs?


Solution

  • Working with Swift code in LLDB 📺

    Most Swift code can be executed as part of LLDB if it's part of the stdlib with the right syntax. The key is to prefix type names with the symbol identifier $. I've used $ even for variable names here (new LLDB improvements make this unnecessary) because I prefer to distinguish LLDB definitions.

    Extensions 📏

    With improvements to LLDB, you can actually copy-paste the Swift code directly after expression.

    I've added an example for your extension with $ symbols for clarity:

    (lldb) expression
    extension Collection where Self.Element == Int {
    var $elementsOver30: [Self.Element]? {
    return self.filter { $0 > 30 }
    }
    }
    (lldb) po [32,31,4].$elementsOver30
    ▿ Optional<Array<Int>>
      ▿ some : 2 elements
        - 0 : 32
        - 1 : 31
    

    Pressing Enter after expression prompts a multi-line evaluation where we can input the remaining Swift code.

    Structs/Class definitions 🧱

    (lldb) expression
    struct $Person {
    let name: String
    }
    (lldb) po let $pranav = $Person.init(name: "pranav")
    (lldb) po $pranav
    ▿ $Person
      - name : "pranav"
    

    Reading a Swift instance from memory

    Sometimes, we need to read Swift code using Objective-C in LLDB. For example, if we have a Swift file with a View Controller:

    class LoginViewController: UIViewController {
    ...
    }
    

    We can print the dynamic type of the result of a memory address as follows:

    (lldb) expr -O --language objc -- 0x14160c260
    <SharedSettings.LoginViewController: 0x14160c260>
    

    View Swift docs 📝

    Use type lookup to read a minified version of the type definitions:

    (lldb) type lookup Equatable
    protocol Equatable {
      static func == (lhs: Self, rhs: Self) -> Swift.Bool
    }
    extension Swift.Equatable {
      static func != (lhs: Self, rhs: Self) -> Swift.Bool
    }