์๋ฒ ๋๋ ํ๋ ์์ํฌ(์: Crash-Tester ์ฑ์ CrashLib)์์ C++ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด KSCrashMonitor_CPPException.c์ __cxa_throw ํจ์๊ฐ ํธ์ถ๋์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋๋ ์ด๊ฒ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค. ์ ๊ฒ๋ ๋ชจ๋ ์๋ฒ ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ KSCrash์ ๊ตฌํ์ด ์๋ libc++์ __cxa_throw๋ฅผ ํญ์ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค.
์ถ๊ฐ๋ก: ํฌํจ๋ ํ๋ ์์ํฌ์์ ์ฒ๋ฆฌ๋์ง ์์ C++ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด stackCursor->advanceCursor๊ฐ KSCrashReport.c:writeBacktrace()์์ NULL๊ณผ ๊ฐ์ผ๋ฏ๋ก ๋ณด๊ณ ์ค์ KSCrash๊ฐ ์ถฉ๋ํฉ๋๋ค.
ํธ์ง: ๋ณด๊ณ ์ค KSCrash ์ถฉ๋ ์ ๋ณด๊ฐ ์ถ๊ฐ๋์์ต๋๋ค.
์ด๊ฒ์ ํ์ด์ด ์์ต๋๊น? ๋ด ์ฑ์ KSCrash๋ฅผ ํตํฉํ๋ ค๊ณ ํ๋๋ฐ ์๋ฒ ๋๋ ํ๋ ์์ํฌ ๋๋ฌธ์ ๋ฉ์ท์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ผ๋ฉด ์๋ ค์ฃผ์ธ์.
์ด์ด ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ ๊ทธ๊ฒ์ด ๊ฐ๋ฅํ๋ค๊ณ ๋ฏฟ์ง ์์ต๋๋ค. ์ ์ด๋ ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก์์๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ์ด๊ฒ์ ์ํฉ์ ๋ํ ๋์ ์ดํด์ ๋๋ค.
KSCrash๊ฐ ์คํ ์ถ์ ์ ๊ธฐ๋กํ๋ ๋ฐฉ๋ฒ์ libc++์ ์ํด ํด์ ๋๊ธฐ ์ ์ ์คํ์ ๋ํ ์ก์ธ์ค๋ฅผ ํ์ฉํ๋ __cxa_throw์ ์์ฒด ๊ตฌํ์ ๋ง๋๋ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ๋ง์ปค๊ฐ libc++์์ ๊ตฌํํ๋ ๋์ KSCrash์์ __cxa_throw๋ฅผ ์ฐพ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ KSCrash๊ฐ C++ ์ฝ๋์ ์ ์ ์ผ๋ก ์ฐ๊ฒฐ๋์ด ์๋ ํ ์๋ํฉ๋๋ค. ๊ทธ๋ฌ๋ libc++์ ๋งํฌ๋๋ ์๋ฒ ๋๋ ํ๋ ์์ํฌ์ ๊ฒฝ์ฐ ํ๋ ์์ํฌ๊ฐ KSCrash์ ์ฝ๋์ ๋ํด ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ libc++์ __cxa_throw ๊ตฌํ์ด ์ฌ์ฉ๋ฉ๋๋ค. ์๋ฒ ๋๋ ํ๋ ์์ํฌ๋ฅผ ์ ์ดํ ์ ์๋ ๊ฒฝ์ฐ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ ์ ์์ง๋ง ์ด ์ฌ์ฉ ์ฌ๋ก์์๋ ์๋ํ์ง ์์ต๋๋ค.
ํด๊ฒฐ์ฑ ์ ์ฐพ์ผ๋ฉด ์๋ ค์ฃผ์ญ์์ค.
์๋ฒ ๋๋ ํ๋ ์์ํฌ๋ฅผ ์ ์ดํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๊ณ ์น ๋ฐฉ๋ฒ์ด ํ์คํ์ง ์์ต๋๋ค.
๋๋ ๋ํ PLCrashReporter์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์๋ํ์ต๋๋ค.
์ด๊ฒ์ KSCrash๊ฐ ์ต์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋์์ throw๋ C++ ์์ธ๋ฅผ ํฌ์ฐฉํ๊ธฐ ์ํด ์ด์์ ์ผ๋ก ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋น๋๋๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฐ๊ฒฐ๋์ด์ผ ํจ์ ์๋ฏธํฉ๋๊น?
๊ทธ๋ฌ๋ ๋ฒ๊ทธ ๋ณด๊ณ ์ @pdrtrifork ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ฉด KSCrash๊ฐ ํฌ์ฐฉํ์ง ๋ชปํ ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์์ธ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค. ๋ด์ฅ๋ ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ดํ๋ โโ๊ฒฝ์ฐ ๊ณต์ KSCrash ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ๋ __cxa_throw ์คํ ์ ์ฌ์ฉํ์ฌ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฐ๊ฒฐํ ์ ์์ต๋๊น?
ํ, ๊ทธ๋์ ์ด๊ฒ์ ์กฐ์ฌํ๋ฉด์ ๋๋ http://stackoverflow.com/questions/36846628/conditionally-overriding-cxa-throw ์ ์ด๋ฅด๋ ์ต๋๋ค. ์ด๊ฒ์ ์ฐ๋ฆฌ ์์ ์ @kstenerud ์ ์ํด ์ด๋ ธ์ต๋๋ค ๐
์ด์จ๋ PR #219๋ ์ต์ํ ์ถฉ๋ ๋ณด๊ณ ์ค์ ์ถฉ๋์ ๋ฐฉ์งํด์ผ ํฉ๋๋ค.
@kstenerud ์ ์๊ฐ์๋ ์ด ๋ฌธ์ ์ ์ด๋ฆ์ _"KSCrash์ ์ ์ ์ผ๋ก ์ฐ๊ฒฐ๋์ง ์์ ์ด๋ฏธ์ง์์ ๋ฐ์ํ C++ ์์ธ์ ๋ํ ์คํ ์ถ์ ๋๋ฝ"_๊ณผ ๊ฐ์ ๊ฒ์ผ๋ก ์ด๋ฆ์ ๋ฐ๊ฟ์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ด๊ฐ ๋งํ ์ ์๋ ํ __cxa_throw
์ฌ์ ์๋ KSCrash์ ๋์ผํ ์ด๋ฏธ์ง์์๋ง ์๋ํ๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ํ์๋ sentry-swift
, https://docs.sentry.io/clients/cocoa/ ์ ๊ฐ์ ํด๋ผ์ด์ธํธ์ ์ํฅ์ ๋ฏธ์น๋ฉฐ, ์ด๋ KSCrash๋ฅผ ํ๋ ์์ํฌ๋ก ํฌํจํฉ๋๋ค.
์ถ๊ฐ ์กฐ์ฌ ํ ๋ด ์ด์ ์๊ฒฌ์ด ์๋ชป๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด ๋ฌธ์ ๋ _"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
, -weak __cxa_throw
, libKSCrash.dylib::__cxa_throw
๋ ๋ฌด์ํด์ผ ํ๋ค๋ ๊ฒฐ๋ก ์ ๋ด๋ฆฝ๋๋ค. MyApplication
์์ ์คํ ์๊ฐ ๊ธฐํธ ์กฐํ ์ค์ libKSCrash.dylib::__cxa_throw
๋ ๋ฌด์๋ฉ๋๋ค.
์ด๊ฒ์ weak
์์ฑ์ด KSCrash๋ฅผ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋น๋ํ ๋๋ง ์กฐ๊ฑด๋ถ๋ก ์ถ๊ฐ๋์ด์ผ ํ๋ค๊ณ ๋ฏฟ๊ฒ ํฉ๋๋ค.
์ฒซ ๋ฒ์งธ ์ฌ์ฉ ์ฌ๋ก์ ๋ง์ฐฌ๊ฐ์ง๋ก 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 ๊ทธ๋ํฝ ์๋น์ค 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์ ํ๋์ ์ถฉ๋์ ๋ง๋ฉ๋๋ค.
๊ทธ๊ฒ์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ?
์์์ ์ธ๊ธํ @huakucha : #375 ๋์ ํํฌ๋ฅผ ๊ตฌํํ๋ PR์ ๋ง๋ค์์ต๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ถ๊ฐ ์กฐ์ฌ ํ ๋ด ์ด์ ์๊ฒฌ์ด ์๋ชป๋ ๊ฒ ๊ฐ์ต๋๋ค.
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
, -weak__cxa_throw
,libKSCrash.dylib::__cxa_throw
๋ ๋ฌด์ํด์ผ ํ๋ค๋ ๊ฒฐ๋ก ์ ๋ด๋ฆฝ๋๋ค.MyApplication
์์ ์คํ ์๊ฐ ๊ธฐํธ ์กฐํ ์ค์libKSCrash.dylib::__cxa_throw
๋ ๋ฌด์๋ฉ๋๋ค.์ด๊ฒ์
weak
์์ฑ์ด KSCrash๋ฅผ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋น๋ํ ๋๋ง ์กฐ๊ฑด๋ถ๋ก ์ถ๊ฐ๋์ด์ผ ํ๋ค๊ณ ๋ฏฟ๊ฒ ํฉ๋๋ค.์ฒซ ๋ฒ์งธ ์ฌ์ฉ ์ฌ๋ก์ ๋ง์ฐฌ๊ฐ์ง๋ก
libDynamicLibrary.dylib
libKSCrash.dylib::__cxa_throw
๋ฅผ ํธ๋ฆฌ๊ฑฐํ์ง ์๊ณ $/usr/lib/libc++abi.dylib::__cxa_throw
๋ก ๋๋ฉ๋๋ค.์ด ๋ฌธ์ ๋
__cxa_throw
์ ๋ํ ์ ์๋์ง ์์ ์ฐธ์กฐ๊ฐ ์๋ ๋ก๋๋ ์ด๋ฏธ์ง์ ์ผ๋ถ ์ ์์ค ๋ฐํ์ ํจ์น ๋ก ์ ์ฌ์ ์ผ๋ก ์์ ๋ ์ ์์ต๋๋ค. ๊ธฐ์ฌ์์ ์ฐธ์กฐํ ํ ์คํธ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ์ฌ ์ด ๊ธฐ์ ์ด ์ค์ ๋ก__cxa_throw
์์๋ ์๋ํ๋์ง ํ์ธํ์ต๋๋ค.