LLDBのデバッグ活用術

December 14, 2020

こんにちわ、私は仕事でiOS開発をしています。 日頃の知見など情報共有する場にこのブログを立ち上げました。 これからよろしくお願いします。

今回は、LLDBのデバッグ活用術として共有します。

まず、LLDBとはXcode標準のデバッガです

  • [LLDB]はGDBに代わる次世代の高性能デバッガ
  • Appleソフトウェアデバッガとして利用されている
  • macOSには標準で搭載されています(Terminal or Xcode) lldb-debug-1.png

主に何ができるか?

  • ブレークポイント設定と操作
  • メモリにロードされた関数・変数をダンプと書き換え
  • カスタムコマンドの作成と実行

GUIブレークポイントの活用例

lldb-debug-2.png lldb-debug-3.png

最初にブレークポイントコマンドを紹介します

ブレークポイントを設定するには2種類のコマンドがあります

  1. breakpoint
  2. rbreak

正規表現を使用したブレークポイントを設定するには、rbreakコマンドを使用します rbreakコマンドはとてもパワフル💪 breakpointbrbreakrbに省略することができます

使用例はこんな感じです

ブレークポイントヒット数が高い場合はスコープを狭めると使い勝手が良くなる

  • ワンショットブレークポイント(1回だけヒット)

    (lldb) rb . -o

  • スコープをhello.swiftファイルに限定する

    (lldb) rb . -f hello.swift

  • スコープをCallKitフレームワークに限定する

    (lldb) rb . -s CallKit

  • ブレークポイント設定をviewDidLoadに設定する

    (lldb) b viewDidLoad

  • 正規表現ブレークポイント設定する

    (lldb) rb viewDid(Appear|Disappear)

  • ブレークポイント一覧を表示する

    (lldb) breakpoint list

  • ブレークポイント削除する

    (lldb) breakpoint delete

次にブレークポイントをLLDBで操作する、ステップ操作コマンドを紹介します

  • run (再コンパイルせずにアプリを起動できます)

    (lldb) run

  • コンティニュー

    (lldb) continue

  • ステップオーバー

    (lldb) next

  • ステップイン(おまじないが必要)

    (lldb) step -a0

  • ステップアウト

    (lldb) finish

コマンドで操作できるのでデバッグの操作がとても便利になります

実行中のアプリの関数をダンプすることもできます

image lookup コマンドを使用してコードを検索できます -rnオプションを使用することにより正規表現検索が使用できます

(lldb) image lookup -rn '\[UIViewController\ '' lldb-debug-4.png

例えば

  • UIViewController’s viewDidLoad instance method のダンプ

    (lldb) image lookup -n "-[UIViewController viewDidLoad]"

  • プライベートメソッドdescriptionのダンプ

    (lldb) image lookup -rn (?i)\ _\w+description\]

  • NSObject(IvarDescription)メソッドのダンプ

    (lldb) image lookup -rn NSObject\(IvarDescription\) と、こんな感じでプライベートの関数ですら検索することができます

po で式を評価する

実行中のアプリの値を表示したり編集したりすることができます

(lldb) po print("Hello, World")

(lldb) po UIApplication.shared

最後に便利なコマンドエイリアスについて紹介します

lldbにはエイリアス機能が整っていてコマンドと式をエイリアスとして登録することができます。

コマンドエイリアス

  • mainバンドルを表示(引数は取れない)

    (lldb) command alias bundle expression -lobjc -O -- [NSBundle mainBundle]

  • ~/.lldbinitのリロード

    (lldb) command alias reload_script command source ~/.lldbinit

~/.lldbinitにカスタムコマンドを登録しておくことでき、よく使用するコマンドを登録していると便利です。

他にも便利なコマンドもあります

  • Objective-Cコンテキストで po と引数指定のエイリアス

    (lldb) command regex cpo -- 's/(.+)/expression -lobjc -O -- %1/'

  • image lookup -rn と引数指定のエイリアス

    (lldb) command regex rlook 's/(.+)/image lookup -rn %1/'

  • 引数に指定したclassのivarsのダンプ

    (lldb) command regex ivars 's/(.+)/expression -lobjc -O -- [%1 _ivarDescription]/'

  • 引数に指定したclassのmethodsのダンプ

    (lldb) command regex methods 's/(.+)/expression -lobjc -O -- [%1 _shortMethodDescription]/'

  • 引数のclass と superclass 含む methodsのダンプ

    (lldb) command regex lmethods 's/(.+)/expression -lobjc -O -- [%1 _methodDescription]/'

  • UIViewControllerのプロパティ・メソッド定義をダンプ

ではでは、以上でした。