組み込みフレームワーク(Crash-TesterアプリのCrashLibなど)でC ++例外がスローされた場合、KSCrashMonitor_CPPException.cの__cxa_throw関数が呼び出されていないようです。
私はこれに対する解決策を思い付くことができませんでした。 私には、組み込みライブラリは常にlibc ++の__cxa_throwを使用し、KSCrashの実装は使用しないように見えます。
さらに、組み込みフレームワークで未処理のC ++例外がスローされると、KSCrashReport.c:writeBacktrace()でstackCursor-> AdvanceCursorがNULLに等しくなるため、レポート中にKSCrashがクラッシュします。
編集:レポート中にKSCrashがクラッシュするという情報を追加しました。
これで運がいいですか? KSCrashをアプリに統合しようとしていますが、フレームワークが埋め込まれているためにスタックします。
これを回避する方法があれば教えてください。
運が悪い、そして少なくとも私たちのユースケースではそれが可能だとは思わない。 これは状況についての私の理解です:
KSCrashがスタックトレースを記録する方法は、__ cxa_throwの独自の実装を作成することです。これにより、libc ++によってスタックが巻き戻される前にスタックにアクセスできます。 これは、リンカがlibc ++での実装の代わりにKSCrashから__cxa_throwを見つけて使用するため、KSCrashがC ++コードと静的にリンクされている限り機能します。 ただし、libc ++にリンクする組み込みフレームワークの場合、フレームワークはKSCrashのコードを認識しないため、libc ++からの__cxa_throw実装が使用されます。 組み込みフレームワークを制御できる場合は回避策があるかもしれませんが、これは私たちのユースケースでは機能しません。
解決策がわかれば教えてください。
組み込みフレームワークを制御できます。 しかし、それを修正する方法がわかりません。
PLCrashReporterも試しましたが、同じ問題があります。
これは、少なくともアプリケーションコードでスローされたC ++例外をキャッチするために、KSCrashを静的ライブラリとして構築し、アプリケーションにリンクすることが理想的であることを意味しますか?
しかし、バグレポートを正しく理解していれば、KSCrashによってキャッチされないダイナミックライブラリにスローされた例外は残りますか? @pdrtrifork ? 埋め込まれた動的ライブラリを制御する場合、共有KSCrashハンドラーに従うだけの__cxa_throwスタブを使用して、静的ライブラリを各ライブラリにリンクできますか?
ああ、それでこれを調査することで私はここに行き着きましたhttp://stackoverflow.com/questions/36846628/conditionally-overriding-cxa-throw 、それは私たち自身の@kstenerudによって開かれました😄
とにかく、PR#219は、少なくともクラッシュレポート中のクラッシュを防ぐ必要があります。
@kstenerudこの問題は、_ "KSCrashに静的にリンクされていないイメージからスローされたC ++例外のスタックトレースがありません" _のような名前に変更する必要があると思います。 私の知る限り、 __cxa_throw
オーバーライドは、KSCrashと同じイメージでのみ機能するため、次のようになります。
後者は、KSCrashをフレームワークとして組み込んだsentry-swift
、 https: //docs.sentry.io/clients/cocoa/などのクライアントに影響します。
さらに調査したところ、以前のコメントは正しくなかったようです。
この問題は、_ "KSCrashに静的にリンクされていないイメージからスローされたC ++例外のスタックトレースがありません" _のような名前に変更する必要があると思います。
KSCrashが静的ライブラリとしてメインアプリケーションにリンクされている場合:
MyApplication
( main.o
、 libKSCrash.a
)libDynamicLibrary.dylib
( lib.o
)/usr/lib/libc++abi.dylib
MyApplication
からスローされた例外は、 libKSCrash.a::__cxa_throw
に入ります。 さらに、 libKSCrash.a
__cxa_throw
をweak
$として宣言するため、 main.o
に独自の__cxa_throw
がある場合、 MyApplication
のリンクは失敗しません。 __cxa_throw
オーバーライド。 ここまでは順調ですね。 ただし、このバグレポートで確認されているように、 libDynamicLibrary.dylib
からスローされた例外は、 libKSCrash.a::__cxa_throw
をトリガーせず、最終的に/usr/lib/libc++abi.dylib::__cxa_throw
になります。
KSCrashがダイナミックライブラリとしてメインアプリケーションにリンクされている場合:
MyApplication
( main.o
)libKSCrash.dylib
/usr/lib/libc++abi.dylib
libDynamicLibrary.dylib
( lib.o
)/usr/lib/libc++abi.dylib
MyApplication
からスローされた例外は、 libKSCrash.dylib::__cxa_throw
に入りますが、次の場合に限ります。
__cxa_throw
はlibKSCrash.dylib
からエクスポートされます__cxa_throw
はweak
としてマークされていません__cxa_throw
がweak
( 0000000000002e90 (__TEXT,__text) weak external ___cxa_throw
)としてマークされている場合、 libKSCrash.dylib
をリンクすると、リンカーは/usr/lib/libc++abi.dylib
を参照しているように見えます。 - __cxa_throw
が弱く、 libKSCrash.dylib::__cxa_throw
は無視する必要があると結論付けます。 MyApplication
からのスロー時の実行時シンボルルックアップ中に、 libKSCrash.dylib::__cxa_throw
は無視されます。
これにより、静的ライブラリとしてKSCrashをビルドする場合にのみ、 weak
属性を条件付きで追加する必要があると思います。
最初のユースケースと同様に、 libDynamicLibrary.dylib
からスローされた例外は、 libKSCrash.dylib::__cxa_throw
をトリガーせず、最終的に/usr/lib/libc++abi.dylib::__cxa_throw
になります。
この問題は、 __cxa_throw
への未定義の参照を含むロードされたイメージの低レベルのランタイムパッチで修正される可能性があります。 この記事で参照されているテストアプリケーションを使用して、この手法が実際に__cxa_throw
でも機能することを確認しました。
アプリのフレームワークでクラッシュをチェックしようとしています。 クラッシュログを取得しようとすると、スタックトレースに実際のクラッシュが表示されておらず、代わりにKSCrashがクラッシュしていることがわかります。
これは同じ問題ですか?
スレッド0がクラッシュしました:
0 libsystem_kernel.dylib 0x0000000181cc5348 0x181ca4000 + 136008(__ pthread_kill + 8)
1 libsystem_pthread.dylib 0x0000000181ddd7a4 0x181dd6000 + 30628(+ 360)
2 libsystem_c.dylib 0x0000000181c34fd8 0x181bd2000 + 405464(中止+ 140)
3 libc ++ abi.dylib 0x0000000181698068 0x181696000 + 8296(+ 132)
4 libc ++ abi.dylib 0x0000000181698210 0x181696000 + 8720(+ 304)
5 libobjc.A.dylib 0x00000001816c0810 0x1816b8000 + 34832(+ 124)
6 KSCrash 0x00000001054a0590 0x10549c000 + 17808(kscm_cppexception_getAPI + 280)
7 libc ++ abi.dylib 0x00000001816b054c 0x181696000 + 107852(+ 16)
8 libc ++ abi.dylib 0x00000001816b0158 0x181696000 + 106840(__ cxa_rethrow + 144)
9 libobjc.A.dylib 0x00000001816c06e8 0x1816b8000 + 34536(objc_exception_rethrow + 44)
10 CoreFoundation 0x0000000182072344 0x18206a000 + 33604(CFRunLoopRunSpecific + 544)
11 GraphicsServices 0x0000000183f03f84 0x183ef9000 + 44932(GSEventRunModal + 100)
12 UIKit 0x000000018b61e880 0x18b5ab000 + 473216(UIApplicationMain + 208)
@torarnvこんにちは、成功したmach-o-hookデモを私たちと共有できますか? mach_hook
__cxa_throwを実行しようとすると、EXC_BAD_ACCESSに遭遇しました。
void ter_handler(){
printf("custom handler\n");
}
void test(){
throw std::runtime_error("test function");
}
static void (*orig_throw)(void * thrown_exception, std::type_info *tinfo, void (*dest)(void *));
void hooked_throw(void * thrown_exception, std::type_info *tinfo, void (*dest)(void *)){
printf("hooked_throw...\n");
return orig_throw(thrown_exception, tinfo, dest);
}
int main(int argc, char * argv[])
{
<strong i="5">@autoreleasepool</strong> {
struct rebinding binds[1];
struct rebinding bind1 = {"__cxa_throw", (void *)hooked_throw, (void **)&orig_throw};
binds[0] = bind1;
rebind_symbols(binds, 1);
std::set_terminate(ter_handler);
try {
throw std::runtime_error("test error");
}
catch (...){
printf ("catch exception\n");
}
test();
}
}
これを試してください...頑張ってください
KSCrashで1つのクラッシュに遭遇しました。
それを解決する方法は?
@huakuchaによって上記の動的フックを実装するPRを作成しました:#375
最も参考になるコメント
さらに調査したところ、以前のコメントは正しくなかったようです。
KSCrashが静的ライブラリとしてメインアプリケーションにリンクされている場合:
MyApplication
(main.o
、libKSCrash.a
)libDynamicLibrary.dylib
(lib.o
)/usr/lib/libc++abi.dylib
MyApplication
からスローされた例外は、libKSCrash.a::__cxa_throw
に入ります。 さらに、libKSCrash.a
__cxa_throw
をweak
$として宣言するため、main.o
に独自の__cxa_throw
がある場合、MyApplication
のリンクは失敗しません。__cxa_throw
オーバーライド。 ここまでは順調ですね。 ただし、このバグレポートで確認されているように、libDynamicLibrary.dylib
からスローされた例外は、libKSCrash.a::__cxa_throw
をトリガーせず、最終的に/usr/lib/libc++abi.dylib::__cxa_throw
になります。KSCrashがダイナミックライブラリとしてメインアプリケーションにリンクされている場合:
MyApplication
(main.o
)libKSCrash.dylib
/usr/lib/libc++abi.dylib
libDynamicLibrary.dylib
(lib.o
)/usr/lib/libc++abi.dylib
MyApplication
からスローされた例外は、libKSCrash.dylib::__cxa_throw
に入りますが、次の場合に限ります。__cxa_throw
はlibKSCrash.dylib
からエクスポートされます__cxa_throw
はweak
としてマークされていません__cxa_throw
がweak
(0000000000002e90 (__TEXT,__text) weak external ___cxa_throw
)としてマークされている場合、libKSCrash.dylib
をリンクすると、リンカーは/usr/lib/libc++abi.dylib
を参照しているように見えます。 -__cxa_throw
が弱く、libKSCrash.dylib::__cxa_throw
は無視する必要があると結論付けます。MyApplication
からのスロー時の実行時シンボルルックアップ中に、libKSCrash.dylib::__cxa_throw
は無視されます。これにより、静的ライブラリとしてKSCrashをビルドする場合にのみ、
weak
属性を条件付きで追加する必要があると思います。最初のユースケースと同様に、
libDynamicLibrary.dylib
からスローされた例外は、libKSCrash.dylib::__cxa_throw
をトリガーせず、最終的に/usr/lib/libc++abi.dylib::__cxa_throw
になります。この問題は、
__cxa_throw
への未定義の参照を含むロードされたイメージの低レベルのランタイムパッチで修正される可能性があります。 この記事で参照されているテストアプリケーションを使用して、この手法が実際に__cxa_throw
でも機能することを確認しました。