若干話題になって出尽くしてる感がありますが、XcodeのLLDBを絡めたデバッグでよく使う手法をまとめてみました。
- 特定の行をスキップ
- 特定の行を書き換える
- ブレークポイントをon/offする
- アドレスからオブジェクトに戻して変数に格納する
- 組み込みメソッドに対してブレークポイントを仕込む
- 変数の変更を監視する
- その他のよく使うコマンド
特定の行をスキップ
行をスキップしたい際は、thread jump
やthread return
を活用します。
# 1行スキップ (lldb) th j --by 1 c
th j
がthread jump
の、c
がcontinue
のように一意に決まれば先頭だけで短縮してよいので、こちらを利用すると便利です。
ある1行だけコメントアウトしたい際は、ブレークポイントを挟んで再度ビルドせずにXcodeのGUIを利用してこのようにすると、同様のことができます。
thread return
は実行中の関数から即return
することが出来ます。
(lldb) th r c
特定の行を書き換える
書き換えたい行の手前にブレークポイントを挟んで、expression
コマンドを実行して、thread jump
することで実現できます。
# Viewの背景色を赤に書き換える例 (lldb) e view.backgroundColor = UIColor.red th j --by 1 c
e
がexpression
のエイリアスになっています。
こちらも毎回書き換えたい場合には、XcodeのGUIを利用するのが便利です。
このようにすることで、上の3行のLLDBコマンドと同様のことを毎回実行してくれます。
ブレークポイントをon/offする
アクティブなブレークポイントは、breakpoint list
で確認します。
(lldb) br l Current breakpoints: 1: file = '/Users/hoge/iOS/ColorStock/ColorStock/Domain/Model/EditingThemeDataStore.swift', line = 18, exact_match = 0, locations = 0 (pending) 2: file = '/Users/hoge/iOS/ColorStock/ColorStock/Presentation/ViewController/ColorSelectorViewController.swift', line = 88, exact_match = 0, locations = 1, resolved = 1, hit count = 0 2.1: where = ColorStock`ColorStock.ColorSelectorViewController.toastViewRecoveryButtonTapped(Any) -> () + 1295 at ColorSelectorViewController.swift:88:5, address = 0x00000001029bcf0f, resolved, hit count = 0
ブレークポイントを無効にしたい場合は、breakpoint disable
を使います。削除の場合はbreakpoint delete
です。複数指定も可能です。
# リストの2番目と4番目のブレークポイントを無効にする (lldb) br di 2 4 1 breakpoints disabled. # リストの1番目のブレークポイントを削除する (lldb) br de 1 1 breakpoints deleted; 0 breakpoint locations disabled.
disable
したブレークポイントはenable
で有効にできます。
# リストの1番目のブレークポイントを有効にする (lldb) br e 1 1 breakpoints enabled.
アドレスからオブジェクトに戻して変数に格納する
デバッグ時の出力が不足している場合、アドレスから元のオブジェクトを取り出したいケースがあります。
その場合、Swift
の文としてexpression
でunsafeBitCast
を利用するのが、一つの手法としてあります。
# Viewの親VCを取得する (lldb) e -l swift -- let $view = unsafeBitCast(0x01234567, UIView.self) e -l swift -- print(view.parentVIewController)
let
を使って変数を定義したい場合は、e -l swift
のように言語を明示する必要があります。--
はセパレータになります。
その上、変数名は$view
のように$
で始まる必要があります。
~/.lldbinit
や~/.lldbinit-Xcode
などに以下のように記載すると、LLDBのエイリアスを定義することが出来るため、
swi let $view = unsafeBitCast(0x012345678900, UIView.self)
のように書くことが出来て、記述が楽になります。
command alias swi expr -l swift --
単純に変数に格納せずにprint
したい場合は、po
コマンドを利用します。
po unsafeBitCast(0x012345678900, UIView.self).parentViewController
組み込みメソッドに対してブレークポイントを仕込む
Symbolic Breakpointを使うことで、組み込みのメソッドに対してもブレークポイントを追加することが出来ます。
viewDidLoad
のように、UIKit
のメソッドを対象にする場合は、Obj-C記法で-[UIViewController viewDidLoad]
のように書きます。
$arg1
にオブジェクトが入るので、po $arg1
とすることで、どのオブジェクトの該当シンボルが呼ばれているか確認することが出来ます。
変数の変更を監視する
watchpoint
を使うことで、指定した変数の変更を監視ができます。
設定はwatchpoint set var
で行い、ブレークポイントのようにlist
で一覧表示してdisable
で無効にできます。
# self.redを監視 (lldb) w s v self.red Watchpoint created: Watchpoint 3: addr = 0x7ffee3515a28 size = 1 state = enabled type = w declare @ '/Users/hoge/iOS/ColorStock/ColorStock/Data/Entity/Color.swift:21' watchpoint spec = 'self.red' (lldb) w l Number of supported hardware watchpoints: 4 Current watchpoints: Watchpoint 2: addr = 0x7ffee3515c58 size = 8 state = disabled type = w declare @ '/Users/hoge/iOS/ColorStock/ColorStock/Presentation/View/ColorDetailView.swift:31' watchpoint spec = 'self' old value: 0x000000010c709300 new value: 0x000000010c709300 Watchpoint 3: addr = 0x7ffee3515a28 size = 1 state = enabled type = w declare @ '/Users/hoge/iOS/ColorStock/ColorStock/Data/Entity/Color.swift:21' watchpoint spec = 'self.red' (lldb) w di 2 1 watchpoints disabled.
その他のよく使うコマンド
Xcodeのボタンでも操作できますが、以下の操作はLLDBでも出来ます。
コマンド | 操作 |
---|---|
bt |
スタックトレース |
step |
ステップ実行 |
stepi |
ステップイン |
continue |
実行の継続 |