Sepertinya fungsi __cxa_throw di KSCrashMonitor_CPPException.c tidak dipanggil ketika pengecualian C++ dilemparkan ke dalam kerangka kerja yang disematkan, misalnya CrashLib di aplikasi Crash-Tester.
Saya belum bisa menemukan solusi untuk ini. Bagi saya sepertinya perpustakaan yang disematkan akan selalu menggunakan __cxa_throw dari libc++, dan bukan implementasi di KSCrash.
Selain itu: Ketika pengecualian C++ yang tidak ditangani dilemparkan ke dalam kerangka kerja yang disematkan, KSCrash akan macet selama pelaporan, karena stackCursor->advanceCursor akan sama dengan NULL di KSCrashReport.c:writeBacktrace().
Sunting: Menambahkan informasi KSCrash mogok selama pelaporan.
Adakah keberuntungan dengan ini? Saya mencoba mengintegrasikan KSCrash di aplikasi saya, tetapi macet karena kerangka kerja yang disematkan.
Tolong beri tahu saya jika Anda memiliki pekerjaan untuk ini.
Tidak berhasil, dan saya tidak percaya itu mungkin, setidaknya tidak dalam kasus penggunaan kami. Inilah pemahaman saya tentang situasinya:
Cara KSCrash merekam jejak tumpukan adalah dengan membuat implementasi __cxa_throw-nya sendiri, yang memungkinkan akses ke tumpukan sebelum dibatalkan oleh libc++. Ini berfungsi selama KSCrash ditautkan secara statis dengan kode C++, karena tautan akan menemukan dan menggunakan __cxa_throw dari KSCrash alih-alih implementasi di libc++. Tetapi dalam kasus kerangka kerja tertanam yang tertaut ke libc++, implementasi __cxa_throw dari libc++ akan digunakan, karena kerangka kerja tidak tahu tentang kode di KSCrash. Mungkin ada solusi jika Anda memiliki kendali atas kerangka kerja yang disematkan, tetapi ini tidak akan berfungsi dalam kasus penggunaan kami.
Tolong beri tahu saya jika Anda menemukan solusi.
Saya memiliki kendali atas kerangka kerja yang disematkan. Tapi tidak yakin bagaimana cara memperbaikinya.
Saya juga mencoba PLCrashReporter, masalah yang sama dengannya.
Apakah ini berarti bahwa KSCrash idealnya harus dibangun sebagai perpustakaan statis dan ditautkan ke dalam aplikasi, untuk setidaknya menangkap pengecualian C++ yang dilemparkan ke dalam kode aplikasi?
Tapi itu masih akan meninggalkan pengecualian apa pun yang dilemparkan ke perpustakaan dinamis apa pun yang tidak tertangkap oleh KSCrash jika saya memahami laporan bug Anda dengan benar @pdrtrifork ? Jika kita mengontrol lib dinamis yang disematkan, dapatkah kita menautkan lib statis ke masing-masing lib hanya dengan rintisan __cxa_throw itu, yang hanya akan tunduk pada penangan KSCrash yang dibagikan?
Hah, jadi dalam menyelidiki ini saya berakhir di sini http://stackoverflow.com/questions/36846628/conditionally-overriding-cxa-throw , yang dibuka oleh @kstenerud kami sendiri
Bagaimanapun, PR #219 setidaknya harus mencegah kerusakan selama pelaporan kerusakan.
@kstenerud Saya pikir masalah ini harus diganti namanya menjadi sesuatu seperti _"Jejak tumpukan yang hilang untuk pengecualian C++ yang dilemparkan dari gambar yang tidak ditautkan secara statis dengan KSCrash"_. Sejauh yang saya tahu, penggantian __cxa_throw
hanya berfungsi pada gambar yang sama dengan KSCrash, jadi:
Yang terakhir akan mempengaruhi klien seperti sentry-swift
, https://docs.sentry.io/clients/cocoa/ , yang menyematkan KSCrash sebagai kerangka kerja.
Setelah penyelidikan lebih lanjut, sepertinya komentar saya sebelumnya salah:
Saya pikir masalah ini harus diganti namanya menjadi sesuatu seperti _"Jejak tumpukan yang hilang untuk pengecualian C++ yang dilemparkan dari gambar yang tidak ditautkan secara statis dengan KSCrash"_.
Dalam kasus KSCrash ditautkan ke aplikasi utama sebagai perpustakaan statis:
MyApplication
( main.o
, libKSCrash.a
)libDynamicLibrary.dylib
( lib.o
)/usr/lib/libc++abi.dylib
Pengecualian apa pun yang dilemparkan dari MyApplication
akan masuk ke libKSCrash.a::__cxa_throw
. Sebagai tambahan, karena libKSCrash.a
mendeklarasikan __cxa_throw
sebagai weak
, menautkan MyApplication
tidak gagal jika main.o
memiliki __cxa_throw
sendiri libDynamicLibrary.dylib
tidak akan memicu libKSCrash.a::__cxa_throw
, dan akan berakhir di /usr/lib/libc++abi.dylib::__cxa_throw
.
Dalam kasus KSCrash ditautkan ke aplikasi utama sebagai pustaka dinamis:
MyApplication
( main.o
)libKSCrash.dylib
/usr/lib/libc++abi.dylib
libDynamicLibrary.dylib
( lib.o
)/usr/lib/libc++abi.dylib
Pengecualian apa pun yang dilemparkan dari MyApplication
akan masuk ke libKSCrash.dylib::__cxa_throw
, tetapi hanya jika:
__cxa_throw
diekspor dari libKSCrash.dylib
__cxa_throw
tidak ditandai sebagai weak
Jika __cxa_throw
ditandai sebagai weak
( 0000000000002e90 (__TEXT,__text) weak external ___cxa_throw
), maka ketika menautkan libKSCrash.dylib
penaut tampaknya melihat /usr/lib/libc++abi.dylib
, temukan non -lemah __cxa_throw
, dan menyimpulkan bahwa libKSCrash.dylib::__cxa_throw
harus diabaikan. Selama pencarian simbol runtime pada waktu lempar dari MyApplication
, libKSCrash.dylib::__cxa_throw
kemudian diabaikan.
Ini membuat saya percaya bahwa atribut weak
harus ditambahkan secara kondisional hanya saat membangun KSCrash sebagai pustaka statis.
Seperti untuk kasus penggunaan pertama, pengecualian apa pun yang dilemparkan dari libDynamicLibrary.dylib
tidak akan memicu libKSCrash.dylib::__cxa_throw
, dan akan berakhir di /usr/lib/libc++abi.dylib::__cxa_throw
.
Masalah ini berpotensi diperbaiki dengan beberapa patch runtime tingkat rendah dari gambar yang dimuat dengan referensi yang tidak ditentukan ke __cxa_throw
. Dengan menggunakan aplikasi uji yang dirujuk dalam artikel, saya telah memverifikasi bahwa teknik ini memang bekerja untuk __cxa_throw
juga.
Saya mencoba memeriksa kerusakan dalam kerangka kerja di aplikasi saya. Ketika saya mencoba untuk mendapatkan log kerusakan, saya melihat bahwa jejak tumpukan tidak menunjukkan kerusakan yang sebenarnya, melainkan KSCrash yang mogok.
Apakah ini masalah yang sama?
Utas 0 Rusak:
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 (batalkan + 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 Layanan Grafik 0x0000000183f03f84 0x183ef9000 + 44932 (GSEventRunModal + 100)
12 UIKit 0x000000018b61e880 0x18b5ab000 + 473216 (UIApplicationMain + 208)
@torarnv Hai, bisakah Anda membagikan demo mach-o-hook Anda yang sukses dengan kami? Saya mengalami EXC_BAD_ACCESS saat mencoba mach_hook
__cxa_throw.
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();
}
}
coba ini ... semoga berhasil
Saya bertemu satu crash dengan KSCrash ,
bagaimana mengatasinya?
Kami telah membuat PR yang mengimplementasikan kait dinamis yang disebutkan di atas oleh @huakucha : #375
Komentar yang paling membantu
Setelah penyelidikan lebih lanjut, sepertinya komentar saya sebelumnya salah:
Dalam kasus KSCrash ditautkan ke aplikasi utama sebagai perpustakaan statis:
MyApplication
(main.o
,libKSCrash.a
)libDynamicLibrary.dylib
(lib.o
)/usr/lib/libc++abi.dylib
Pengecualian apa pun yang dilemparkan dari
MyApplication
akan masuk kelibKSCrash.a::__cxa_throw
. Sebagai tambahan, karenalibKSCrash.a
mendeklarasikan__cxa_throw
sebagaiweak
, menautkanMyApplication
tidak gagal jikamain.o
memiliki__cxa_throw
sendirilibDynamicLibrary.dylib
tidak akan memiculibKSCrash.a::__cxa_throw
, dan akan berakhir di/usr/lib/libc++abi.dylib::__cxa_throw
.Dalam kasus KSCrash ditautkan ke aplikasi utama sebagai pustaka dinamis:
MyApplication
(main.o
)libKSCrash.dylib
/usr/lib/libc++abi.dylib
libDynamicLibrary.dylib
(lib.o
)/usr/lib/libc++abi.dylib
Pengecualian apa pun yang dilemparkan dari
MyApplication
akan masuk kelibKSCrash.dylib::__cxa_throw
, tetapi hanya jika:__cxa_throw
diekspor darilibKSCrash.dylib
__cxa_throw
tidak ditandai sebagaiweak
Jika
__cxa_throw
ditandai sebagaiweak
(0000000000002e90 (__TEXT,__text) weak external ___cxa_throw
), maka ketika menautkanlibKSCrash.dylib
penaut tampaknya melihat/usr/lib/libc++abi.dylib
, temukan non -lemah__cxa_throw
, dan menyimpulkan bahwalibKSCrash.dylib::__cxa_throw
harus diabaikan. Selama pencarian simbol runtime pada waktu lempar dariMyApplication
,libKSCrash.dylib::__cxa_throw
kemudian diabaikan.Ini membuat saya percaya bahwa atribut
weak
harus ditambahkan secara kondisional hanya saat membangun KSCrash sebagai pustaka statis.Seperti untuk kasus penggunaan pertama, pengecualian apa pun yang dilemparkan dari
libDynamicLibrary.dylib
tidak akan memiculibKSCrash.dylib::__cxa_throw
, dan akan berakhir di/usr/lib/libc++abi.dylib::__cxa_throw
.Masalah ini berpotensi diperbaiki dengan beberapa patch runtime tingkat rendah dari gambar yang dimuat dengan referensi yang tidak ditentukan ke
__cxa_throw
. Dengan menggunakan aplikasi uji yang dirujuk dalam artikel, saya telah memverifikasi bahwa teknik ini memang bekerja untuk__cxa_throw
juga.