私はそれを理解するために次の算術を使用しました:
slide
+ stack address
- load address
=symbol address
と
stack address
は、スタックダンプクラッシュレポートから取得した16進値です(.crashファイルではなく、スタックダンプのみ)。
と
slide
実行時のLC_SEGMENTコマンドのvmaddrですotool -arch armv7 -l APP_BINARY_PATH
。鉱山は通常0x00001000になります。
と
load address
複雑な作品です。これは、実際には、メインスレッドの最下位のスタックアドレスと、実行時にシンボルを含むバイナリの部分の最初のアドレスとの違いdwarfdump --arch armv7 --all DSYM_BINARY_PATH
です。これは単にmain
関数のシンボリックアドレスです。したがって、最下位のクラッシュアドレスが0x8000で、メイン関数のシンボリックアドレスが0x2000の場合、load address
は0x6000になります。
これらすべての要素を使用して、シンボルアドレスを計算し、それをatosまたはdwarfdumpに入れることができますdwarfdump --lookup SYM_ADDR --arch armv7 APP_BINARY_PATH
。
ダンプの例(load address
0x00003af4であることがわかります):
----------------------------------------------------------------------
ファイル:/Users/user/Desktop/MyApp.xcarchive/dSYMs/MyApp.app.dSYM/Contents/Resources/DWARF/MyApp(armv7)
----------------------------------------------------------------------
0x00000024:[0x00003af4-0x00003b4e)メイン
0x00000098:[0x00003b50-0x00003d8c)-[MyAppDelegateアプリケーション:didFinishLaunchingWithOptions:]
...残りのダンプ
最も難しかったのは、私が含めた2つの静的ライブラリの1つで、アプリのバイナリにリンクする前にシンボルが削除されていることに気づいたことです。そのため、シンボルアドレスに大きなギャップが生じたため、dSYMで必要なシンボルの3分の2しか使用できませんでした。
静的ライブラリのxcodeプロジェクトで次のフラグをNOに設定してください。これにより、静的ライブラリに対してリンクするときに、シンボルをアプリのバイナリ(後で削除できます)にプルできます:COPY_PHASE_STRIP
、、、。DEAD_CODE_STRIPPING
STRIP_INSTALLED_PRODUCT
ここで、「スタックダンプにメイン関数が含まれていないためにメインスレッドにないため、メイン関数のスタックアドレスを取得できない場合はどうすればよいですか?」と質問することができます。それに対して、私は「私は気まぐれな手がかりを持っていません!」と答えます。指を交差させるだけで、シンボルアドレスを含むスタックトレースを取得できるか、PLCrashReporterなどのAppleのクラッシュログを模倣したクラッシュレポートシステムを使用できることを願っています。
[2013年5月26日編集]-
これがload address
実際にはmach-oバイナリのアドレスであることに気づきました。私が上で説明したことはしばしばうまくいくかもしれませんが、それは実際には正しくありません。これはクラッシュレポートから取得できますが、この回答のポイントは、クラッシュレポートがない場合にクラッシュのシンボルを提供することでした。load address
象徴したいときを理解するために私が来た最良の方法は、を使用しload address
てログに記録することを確認することstack addresses
です。
クラッシュをログに記録し(クラッシュレポートではなく)、後でデバッグのために取得できるS3バケットに送信するためのシステムを個人的に作成しました。アプリケーションを起動すると、アプリがクラッシュした場合に使用するために、、およびをキャッシュし、を送信しslide
ます。load address
main function address
stack addresses
注:dyld関数は#include <mach-o/dyld.h>
slide
=によって返されるアドレス_dyld_get_image_vmaddr_slide(0)
load address
=によって返されるアドレス_dyld_get_image_header(0)
main function address
[NSThread callStackReturnAddresses]
=メインスレッドで呼び出されたときの最後のアドレス
クラッシュ時には、次のメソッドを使用して取得できるアーキテクチャだけでなく、ログ[NSThread callStackReturnAddresses]
にも記録する必要があります。[NSThread callStackSymbols]
- (NSString*) arch
{
NSString* arch =
#ifdef _ARM_ARCH_7
@"armv7";
#elif defined (_ARM_ARCH_6)
@"armv6";
#else
nil;
#endif
return arch;
}
ただし、armv7とarmv7sを区別する方法はまだわかりません。
したがって、これは将来役立つ可能性があります。私は学んだことをすべて取り入れて、これを単純なクラッシュツールに変えることを計画しています-natosツール(おそらくnatosv2)よりも優れています。
load address
手動での供給をサポートするようにnatosを更新しました: https ://github.com/NSProgrammer/natos