ペンギン村 Tech Blog

技術をこよなく愛するエンジニア集団が在住するペンギン村から、世界へ役立つ(かもしれない)技術情報を発信する技術系ブログです。某アラレちゃんが済む村とは一切関係ありません。んちゃ!

自由にクラスインスタンスにアクセスできるLLDBコマンド作りました。

自己紹介

ペンギン村の通行人 、po_miyasakaです。
名前の「po」はLLDBのコマンドから拝借しました。 (プロダクトオーナーでは🍆😎)

概要

vinfoというLLDBコマンド を作ったので紹介します。

vinfoとは
  • 任意のタイミングで 任意のクラスインスタンスにアクセスできる程度の能力を持つ。
  • SwiftもしくはObjective-Cで利用可能。
  • 使用イメージGIFはこちら
使い所
  • メモリ上のどこかに展開されているログイン情報にアクセスしたいとき
  • FluxアーキテクチャにおけるStoreの状態をデバッグしたいとき
  • 任意のインスタンスのメソッドを実行したいとき
    • 本来一度しか表示されないであろうチュートリアルを表示するメソッドを呼んだりとか。
    • privateとして定義されていても実行可能😎

コマンドの設定方法

  1. pm_lldb_commands.pyをローカルに保存
  2. ~ /.lldbinit*1に以下のコマンドを書き込んで保存
command script import <パス>/pm_lldb_commands.py

vinfoの使い方

  1. 適当にアプリを止める(ViewHierarchy もしくは Memory Graphのクリック)
  2. 左サイドバーでアクセスしたい変数を選んで、右サイドバーからアドレスをコピー
  3. コンソール vinfoにアドレスを渡して実行

vinfoの出力内容

以下の画像の出力例をもとに説明する。 f:id:po_miyasaka:20190131013206p:plain

  • MewExample.MainViewController
    • クラス名
  • Use in swift context
    • 変数にアクセスできる言語コンテキスト(SwiftもしくはObjective-C)
  • type lookup MewExample.MainViewController
    • この行をコピってLLDBコマンドとして実行すると、この変数のメソッドやプロパティが一覧で表示される
  • $R153
    • コンソールで使える一時変数

vinfoの注意点

基本的には通常のインスタンスのようにプロパティの参照やメソッドの実行ができるが注意点がある。

生成した一時変数の使用するときは、言語コンテキストを指定しないとエラーになる。

p, poコマンドの挙動はブレークしている箇所の言語コンテキストに左右される。
例えば Swiftのコード上でブレークして po print("hoge")といったようにSwiftのコードを実行すると "hoge"を出力することができるが、 f:id:po_miyasaka:20190131020435p:plain 停止ボタンを押してから同じコードを実行すると、以下のような見慣れたエラーがでる。 f:id:po_miyasaka:20190131014453p:plain

これはブレークしている場所がSwiftのコンテキスト上でないからである。
ブレークしている箇所に関わらずコマンドを実行するためには以下のコマンドを使用する。

pos , ps, poc, pcコマンド*2

これらのコマンドにより、どこでアプリを停止しても任意の一時変数にアクセスできる。

  • pos
    • poをSwiftコンテキストで実行する
  • ps
    • pをSwiftコンテキストで実行する
  • poc
    • poをObjcコンテキストで実行する
  • pc
    • pをObjcコンテキストで実行する
プロジェクトによってはXcode10でpopが失敗する事例があるらしく、その場合vinfoも失敗します(;_;)
  • 現在workaroundを探し中
  • XCode9では安定して動く
SwiftのStuctには vinfoではアクセスできません。。
  • Structの変数にはvinfoではインスタンス化できません
  • StructはDebug Memory Graphにも表示されない
  • ViewControllerなどのクラスがStructを保持している場合はViewControllerのインスタンス経由でアクセスすることはできます

備考

  • 実はView Hierarchyおよび Debug Memory Graphにおいては 、
    左サイドバーから任意のコンポーネントをコンソールにドラッグしてくるだけでも使えます。
    Debug Memory GraphのGIF
    View HierarchyのGIF

脚注

*1:ホームディレクトリにおいておくと、アプリのデバッグ開始時に記載したコマンドを自動で実行してくれる。カスタムコマンドやエイリアスの設定に便利

*2:pm_lldb_commands.pyにエイリアス として定義されている。