メインコンテンツにスキップ

macOS でのデバッグ

Electron で、JavaScript アプリケーションではなく Electron 自体が原因と思われるクラッシュや問題が発生した場合、特にネイティブ/C++ デバッグに慣れていない開発者にとっては、デバッグが少し難しい場合があります。ただし、`lldb` と Electron のソースコードを使用すると、Electron のソースコード内でブレークポイントを設定したステップ実行デバッグを有効にすることができます。グラフィカルインターフェースをご希望の場合は、XCode を使用したデバッグも可能です。

要件

  • **Electron のテストビルド**: 通常、最も簡単な方法はソースからビルドすることです。これは、ビルド手順に従って行うことができます。直接ダウンロードした Electron にアタッチしてデバッグすることもできますが、高度に最適化されているため、デバッグがかなり難しくなります。この場合、デバッガはすべての変数の内容を表示できず、インライン化、末尾呼び出し、その他のコンパイラの最適化により、実行パスが奇妙に見えることがあります。

  • **Xcode**: Xcode に加えて、Xcode コマンドラインツールもインストールする必要があります。これらには、macOS 上の Xcode のデフォルトデバッガである LLDB が含まれています。デスクトップ、iOS デバイス、シミュレータで C、Objective-C、C++ のデバッグをサポートしています。

  • **.lldbinit**: `~/.lldbinit` を作成または編集して、Chromium コードが適切にソースマップされるようにします。

    # e.g: ['~/electron/src/tools/lldb']
    script sys.path[:0] = ['<...path/to/electron/src/tools/lldb>']
    script import lldbinit

Electron へのアタッチとデバッグ

デバッグセッションを開始するには、ターミナルを開き、リリースビルドではない Electron をパラメータとして渡して `lldb` を起動します。

$ lldb ./out/Testing/Electron.app
(lldb) target create "./out/Testing/Electron.app"
Current executable set to './out/Testing/Electron.app' (x86_64).

ブレークポイントの設定

LLDB は強力なツールであり、コード検査のための複数の戦略をサポートしています。この基本的な紹介では、JavaScript から呼び出しているコマンドが正しく動作していないと仮定しましょう。そのため、Electron ソース内にあるそのコマンドの C++ 側でブレークしたいとします。

関連するコードファイルは `./shell/` にあります。

`browser.cc` で `Browser::SetName()` として定義されている `app.setName()` をデバッグするとします。`breakpoint` コマンドを使用してブレークポイントを設定し、ブレークするファイルと行を指定します

(lldb) breakpoint set --file browser.cc --line 117
Breakpoint 1: where = Electron Framework`atom::Browser::SetName(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 20 at browser.cc:118, address = 0x000000000015fdb4

次に、Electron を起動します

(lldb) run

Electron は起動時にアプリの名前を設定するため、アプリはすぐに一時停止します

(lldb) run
Process 25244 launched: '/Users/fr/Code/electron/out/Testing/Electron.app/Contents/MacOS/Electron' (x86_64)
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118
115 }
116
117 void Browser::SetName(const std::string& name) {
-> 118 name_override_ = name;
119 }
120
121 int Browser::GetBadgeCount() {
(lldb)

現在のフレームの引数とローカル変数を表示するには、`frame variable` (または `fr v`) を実行します。アプリが現在「Electron」という名前を設定していることがわかります。

(lldb) frame variable
(atom::Browser *) this = 0x0000000108b14f20
(const string &) name = "Electron": {
[...]
}

現在選択されているスレッドでソースレベルのシングルステップを実行するには、`step` (または `s`) を実行します。これは `name_override_.empty()` に移動します。続行してステップオーバーを実行するには、`next` (または `n`) を実行します。

(lldb) step
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119, queue = 'com.apple.main-thread', stop reason = step in
frame #0: 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119
116
117 void Browser::SetName(const std::string& name) {
118 name_override_ = name;
-> 119 }
120
121 int Browser::GetBadgeCount() {
122 return badge_count_;

**注:** ソースコードが表示されるべきときに表示されない場合は、上記の `~/.lldbinit` ファイルを追加していない可能性があります。

この時点でデバッグを終了するには、`process continue` を実行します。また、このスレッドで特定の行に到達するまで続行することもできます (`thread until 100`)。このコマンドは、現在のフレームのスレッドを、このフレームの 100 行目に到達するか、現在のフレームを離れるまで実行します。

これで、Electron のデベロッパーツールを開いて `setName` を呼び出すと、再びブレークポイントに到達します。

参考資料

LLDB は優れたドキュメントを備えた強力なツールです。詳細については、Apple のデバッグドキュメント、たとえば LLDB コマンド構造リファレンススタンドアロンデバッガとしての LLDB の使用 の紹介をご覧ください。

LLDB の素晴らしい マニュアルとチュートリアル もご覧ください。より複雑なデバッグシナリオについて説明しています。