【Android tombstone】ネイティブクラッシュ解析の大幅改善

Article by: Mischan Toosarani-Hausberger , Roman Zavarnitsyn (了読時間:13分) Androidにおけるネイティブクラッシュは、これまで本来あるべきよりもデバッグが難しいものでした。 Androidには独自のクラッシュレポーター(debuggerd)があり、クラッシュしたスレッド、実行中の他のすべてのスレッド、レジスタ状態、メモリマップを tombstone と呼ばれるファイルに記録します。tombstone は長年Androidの一部であり、実際にはAndroid最初期のコミットの頃から、形を変えつつ存在してきました。 問題は、Androidの歴史の大半において、アプリ内部から tombstone をプログラム的に読み取ることができなかったことです。そのため、SDKベースのネイティブクラッシュレポート機能(私たちのものを含む)は、プラットフォーム側ですでに存在している仕組みを独自に再実装せざるを得ませんでした。その代償として、バイナリサイズの増加、不完全なJavaフレームのシンボリケーション、さらに変化し続けるAOSPに追従するために維持しなければならないC++フォークが発生していました。 Android 11(SDK level 30)では ApplicationExitInfo が導入されました。さらに Android 12(SDK level 31)では、ApplicationExitInfo.REASON_CRASH_NATIVE に対する trace input stream へのアクセスが追加されました。 SentryのAndroid SDKは、バージョン8.30.0以降、Android 12以上を実行しているすべてのデバイスでこのストリームを読み取り、ネイティブクラッシュイベントとして送信します。これにより、ネイティブコードを使用するAndroidアプリのクラッシュレポートは大幅に改善されました。基本的なクラッシュ通知だけが必要なチームにも、詳細なデバッグ情報が必要なチームにも有効です。 ここからは、以前はどのように動作していたのか、既存のNDK統合を壊さずにこれをSDKへ組み込むために何が必要だったのか、そしてこれによってどのような改善がもたらされたのかを見ていきます。 tombstoneサポート以前:変化し続けるターゲットを追い続けるフォーク tombstoneサポート以前、Android SDKでは Native SDK(sentry-native)がネイティブエラーレポートの主要な仕組みとして使用されていました。AndroidはLinuxベースであるため、SDKのかなりの部分を再利用できました。しかし再利用できない部分については、2019年からAndroid固有コードの統合作業が始まりました。 特に、libunwindstack(現在も debuggerd、そして tombstone のスタックトレース生成に使用されているAOSPのプラットフォームアンワインダ)を統合したことは、Sentry Android SDKでネイティブクラッシュをサポートする上で重要な転機となりました。なぜかというと、Native Development Kit(NDK)には汎用的なスタックウォーカーが存在しなかったからです(今でも存在しません)。 libunwindstack はNDKの一部ではなく、Android Open Source Project(AOSP)のプラットフォームコードの一部であるため、通常の方法ではアプリ開発者から直接利用できません。Sentryは、NDKでビルドできるようプラットフォームコードへパッチを当てたリポジトリをフォークし、その後も上流のパッチ版に変更がないまま、そのフォークを維持してきました。 これにより、非常に複雑なAndroid […]