objc-exception.mm 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. /*
  2. * Copyright (c) 2002-2007 Apple Inc. All rights reserved.
  3. *
  4. * @APPLE_LICENSE_HEADER_START@
  5. *
  6. * This file contains Original Code and/or Modifications of Original Code
  7. * as defined in and that are subject to the Apple Public Source License
  8. * Version 2.0 (the 'License'). You may not use this file except in
  9. * compliance with the License. Please obtain a copy of the License at
  10. * http://www.opensource.apple.com/apsl/ and read it before using this
  11. * file.
  12. *
  13. * The Original Code and all software distributed under the License are
  14. * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  15. * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  16. * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  18. * Please see the License for the specific language governing rights and
  19. * limitations under the License.
  20. *
  21. * @APPLE_LICENSE_HEADER_END@
  22. */
  23. #if !__OBJC2__
  24. /***********************************************************************
  25. * 32-bit implementation
  26. **********************************************************************/
  27. #include "objc-private.h"
  28. #include <stdlib.h>
  29. #include <setjmp.h>
  30. #include <execinfo.h>
  31. #include "objc-exception.h"
  32. static objc_exception_functions_t xtab;
  33. // forward declaration
  34. static void set_default_handlers();
  35. /*
  36. * Exported functions
  37. */
  38. // get table; version tells how many
  39. void objc_exception_get_functions(objc_exception_functions_t *table) {
  40. // only version 0 supported at this point
  41. if (table && table->version == 0)
  42. *table = xtab;
  43. }
  44. // set table
  45. void objc_exception_set_functions(objc_exception_functions_t *table) {
  46. // only version 0 supported at this point
  47. if (table && table->version == 0)
  48. xtab = *table;
  49. }
  50. /*
  51. * The following functions are
  52. * synthesized by the compiler upon encountering language constructs
  53. */
  54. void objc_exception_throw(id exception) {
  55. if (!xtab.throw_exc) {
  56. set_default_handlers();
  57. }
  58. if (PrintExceptionThrow) {
  59. _objc_inform("EXCEPTIONS: throwing %p (%s)",
  60. (void*)exception, object_getClassName(exception));
  61. void* callstack[500];
  62. int frameCount = backtrace(callstack, 500);
  63. backtrace_symbols_fd(callstack, frameCount, fileno(stderr));
  64. }
  65. OBJC_RUNTIME_OBJC_EXCEPTION_THROW(exception); // dtrace probe to log throw activity.
  66. xtab.throw_exc(exception);
  67. _objc_fatal("objc_exception_throw failed");
  68. }
  69. void objc_exception_try_enter(void *localExceptionData) {
  70. if (!xtab.throw_exc) {
  71. set_default_handlers();
  72. }
  73. xtab.try_enter(localExceptionData);
  74. }
  75. void objc_exception_try_exit(void *localExceptionData) {
  76. if (!xtab.throw_exc) {
  77. set_default_handlers();
  78. }
  79. xtab.try_exit(localExceptionData);
  80. }
  81. id objc_exception_extract(void *localExceptionData) {
  82. if (!xtab.throw_exc) {
  83. set_default_handlers();
  84. }
  85. return xtab.extract(localExceptionData);
  86. }
  87. int objc_exception_match(Class exceptionClass, id exception) {
  88. if (!xtab.throw_exc) {
  89. set_default_handlers();
  90. }
  91. return xtab.match(exceptionClass, exception);
  92. }
  93. // quick and dirty exception handling code
  94. // default implementation - mostly a toy for use outside/before Foundation
  95. // provides its implementation
  96. // Perhaps the default implementation should just complain loudly and quit
  97. extern void _objc_inform(const char *fmt, ...);
  98. typedef struct { jmp_buf buf; void *pointers[4]; } LocalData_t;
  99. typedef struct _threadChain {
  100. LocalData_t *topHandler;
  101. objc_thread_t perThreadID;
  102. struct _threadChain *next;
  103. }
  104. ThreadChainLink_t;
  105. static ThreadChainLink_t ThreadChainLink;
  106. static ThreadChainLink_t *getChainLink() {
  107. // follow links until thread_self() found (someday) XXX
  108. objc_thread_t self = thread_self();
  109. ThreadChainLink_t *walker = &ThreadChainLink;
  110. while (walker->perThreadID != self) {
  111. if (walker->next != nil) {
  112. walker = walker->next;
  113. continue;
  114. }
  115. // create a new one
  116. // XXX not thread safe (!)
  117. // XXX Also, we don't register to deallocate on thread death
  118. walker->next = (ThreadChainLink_t *)malloc(sizeof(ThreadChainLink_t));
  119. walker = walker->next;
  120. walker->next = nil;
  121. walker->topHandler = nil;
  122. walker->perThreadID = self;
  123. }
  124. return walker;
  125. }
  126. static void default_try_enter(void *localExceptionData) {
  127. LocalData_t *data = (LocalData_t *)localExceptionData;
  128. ThreadChainLink_t *chainLink = getChainLink();
  129. data->pointers[1] = chainLink->topHandler;
  130. chainLink->topHandler = data;
  131. if (PrintExceptions) _objc_inform("EXCEPTIONS: entered try block %p\n", chainLink->topHandler);
  132. }
  133. static void default_throw(id value) {
  134. ThreadChainLink_t *chainLink = getChainLink();
  135. LocalData_t *led;
  136. if (value == nil) {
  137. if (PrintExceptions) _objc_inform("EXCEPTIONS: objc_exception_throw with nil value\n");
  138. return;
  139. }
  140. if (chainLink == nil) {
  141. if (PrintExceptions) _objc_inform("EXCEPTIONS: No handler in place!\n");
  142. return;
  143. }
  144. if (PrintExceptions) _objc_inform("EXCEPTIONS: exception thrown, going to handler block %p\n", chainLink->topHandler);
  145. led = chainLink->topHandler;
  146. chainLink->topHandler = (LocalData_t *)
  147. led->pointers[1]; // pop top handler
  148. led->pointers[0] = value; // store exception that is thrown
  149. #if TARGET_OS_WIN32
  150. longjmp(led->buf, 1);
  151. #else
  152. _longjmp(led->buf, 1);
  153. #endif
  154. }
  155. static void default_try_exit(void *led) {
  156. ThreadChainLink_t *chainLink = getChainLink();
  157. if (!chainLink || led != chainLink->topHandler) {
  158. if (PrintExceptions) _objc_inform("EXCEPTIONS: *** mismatched try block exit handlers\n");
  159. return;
  160. }
  161. if (PrintExceptions) _objc_inform("EXCEPTIONS: removing try block handler %p\n", chainLink->topHandler);
  162. chainLink->topHandler = (LocalData_t *)
  163. chainLink->topHandler->pointers[1]; // pop top handler
  164. }
  165. static id default_extract(void *localExceptionData) {
  166. LocalData_t *led = (LocalData_t *)localExceptionData;
  167. return (id)led->pointers[0];
  168. }
  169. static int default_match(Class exceptionClass, id exception) {
  170. //return [exception isKindOfClass:exceptionClass];
  171. Class cls;
  172. for (cls = exception->getIsa(); nil != cls; cls = cls->superclass)
  173. if (cls == exceptionClass) return 1;
  174. return 0;
  175. }
  176. static void set_default_handlers() {
  177. objc_exception_functions_t default_functions = {
  178. 0, default_throw, default_try_enter, default_try_exit, default_extract, default_match };
  179. // should this always print?
  180. if (PrintExceptions) _objc_inform("EXCEPTIONS: *** Setting default (non-Foundation) exception mechanism\n");
  181. objc_exception_set_functions(&default_functions);
  182. }
  183. void exception_init(void)
  184. {
  185. // nothing to do
  186. }
  187. void _destroyAltHandlerList(struct alt_handler_list *list)
  188. {
  189. // nothing to do
  190. }
  191. // !__OBJC2__
  192. #else
  193. // __OBJC2__
  194. /***********************************************************************
  195. * 64-bit implementation.
  196. **********************************************************************/
  197. #include "objc-private.h"
  198. #include <objc/objc-abi.h>
  199. #include <objc/objc-exception.h>
  200. #include <objc/NSObject.h>
  201. #include <execinfo.h>
  202. // unwind library types and functions
  203. // Mostly adapted from Itanium C++ ABI: Exception Handling
  204. // http://www.codesourcery.com/cxx-abi/abi-eh.html
  205. struct _Unwind_Exception;
  206. struct _Unwind_Context;
  207. typedef int _Unwind_Action;
  208. enum : _Unwind_Action {
  209. _UA_SEARCH_PHASE = 1,
  210. _UA_CLEANUP_PHASE = 2,
  211. _UA_HANDLER_FRAME = 4,
  212. _UA_FORCE_UNWIND = 8
  213. };
  214. typedef int _Unwind_Reason_Code;
  215. enum : _Unwind_Reason_Code {
  216. _URC_NO_REASON = 0,
  217. _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
  218. _URC_FATAL_PHASE2_ERROR = 2,
  219. _URC_FATAL_PHASE1_ERROR = 3,
  220. _URC_NORMAL_STOP = 4,
  221. _URC_END_OF_STACK = 5,
  222. _URC_HANDLER_FOUND = 6,
  223. _URC_INSTALL_CONTEXT = 7,
  224. _URC_CONTINUE_UNWIND = 8
  225. };
  226. struct dwarf_eh_bases
  227. {
  228. uintptr_t tbase;
  229. uintptr_t dbase;
  230. uintptr_t func;
  231. };
  232. OBJC_EXTERN uintptr_t _Unwind_GetIP (struct _Unwind_Context *);
  233. OBJC_EXTERN uintptr_t _Unwind_GetCFA (struct _Unwind_Context *);
  234. OBJC_EXTERN uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *);
  235. // C++ runtime types and functions
  236. // copied from cxxabi.h
  237. OBJC_EXTERN void *__cxa_allocate_exception(size_t thrown_size);
  238. OBJC_EXTERN void __cxa_throw(void *exc, void *typeinfo, void (*destructor)(void *)) __attribute__((noreturn));
  239. OBJC_EXTERN void *__cxa_begin_catch(void *exc);
  240. OBJC_EXTERN void __cxa_end_catch(void);
  241. OBJC_EXTERN void __cxa_rethrow(void);
  242. OBJC_EXTERN void *__cxa_current_exception_type(void);
  243. #if SUPPORT_ZEROCOST_EXCEPTIONS
  244. # define CXX_PERSONALITY __gxx_personality_v0
  245. #else
  246. # define CXX_PERSONALITY __gxx_personality_sj0
  247. #endif
  248. OBJC_EXTERN _Unwind_Reason_Code
  249. CXX_PERSONALITY(int version,
  250. _Unwind_Action actions,
  251. uint64_t exceptionClass,
  252. struct _Unwind_Exception *exceptionObject,
  253. struct _Unwind_Context *context);
  254. // objc's internal exception types and data
  255. struct objc_typeinfo {
  256. // Position of vtable and name fields must match C++ typeinfo object
  257. const void ** __ptrauth_cxx_vtable_pointer vtable; // objc_ehtype_vtable+2
  258. const char *name; // c++ typeinfo string
  259. Class cls_unremapped;
  260. };
  261. struct objc_exception {
  262. id obj;
  263. struct objc_typeinfo tinfo;
  264. };
  265. extern "C" void _objc_exception_noop(void) { }
  266. extern "C" bool _objc_exception_false(void) { return 0; }
  267. // extern "C" bool _objc_exception_true(void) { return 1; }
  268. extern "C" void _objc_exception_abort1(void) {
  269. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 1);
  270. }
  271. extern "C" void _objc_exception_abort2(void) {
  272. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 2);
  273. }
  274. extern "C" void _objc_exception_abort3(void) {
  275. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 3);
  276. }
  277. extern "C" void _objc_exception_abort4(void) {
  278. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 4);
  279. }
  280. extern "C" bool _objc_exception_do_catch(struct objc_typeinfo *catch_tinfo,
  281. struct objc_typeinfo *throw_tinfo,
  282. void **throw_obj_p,
  283. unsigned outer);
  284. // C++ pointers to vtables are signed with no extra data.
  285. // C++ vtable entries are signed with a number derived from the function name.
  286. // For this fake vtable, we hardcode number as deciphered from the
  287. // assembly output during libc++abi's build.
  288. #if __has_feature(ptrauth_calls)
  289. # define VTABLE_PTR_AUTH "@AUTH(da, 0)"
  290. # define VTABLE_ENTRY_AUTH(x) "@AUTH(ia," #x ",addr)"
  291. #else
  292. # define VTABLE_PTR_AUTH ""
  293. # define VTABLE_ENTRY_AUTH(x) ""
  294. #endif
  295. #if __LP64__
  296. # define PTR ".quad "
  297. # define TWOPTRSIZE "16"
  298. #else
  299. # define PTR ".long "
  300. # define TWOPTRSIZE "8"
  301. #endif
  302. // Hand-built vtable for objc exception typeinfo.
  303. // "OLD" is GNU libcpp, "NEW" is libc++abi.
  304. asm(
  305. "\n .cstring"
  306. "\n l_.id_str: .asciz \"id\""
  307. "\n .section __DATA,__const"
  308. "\n .globl _OBJC_EHTYPE_id"
  309. "\n .globl _objc_ehtype_vtable"
  310. "\n .p2align 4"
  311. "\n _OBJC_EHTYPE_id:"
  312. "\n " PTR "(_objc_ehtype_vtable+" TWOPTRSIZE ") " VTABLE_PTR_AUTH
  313. "\n " PTR "l_.id_str"
  314. "\n " PTR "0"
  315. "\n _objc_ehtype_vtable:"
  316. "\n " PTR "0"
  317. // typeinfo's typeinfo - fixme hack
  318. "\n " PTR "_OBJC_EHTYPE_id"
  319. // destructor and in-place destructor
  320. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(52634)
  321. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(10344)
  322. // OLD __is_pointer_p
  323. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(6889)
  324. // OLD __is_function_p
  325. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(23080)
  326. // OLD __do_catch, NEW can_catch
  327. "\n " PTR "__objc_exception_do_catch" VTABLE_ENTRY_AUTH(27434)
  328. // OLD __do_upcast, NEW search_above_dst
  329. "\n " PTR "__objc_exception_false" VTABLE_ENTRY_AUTH(48481)
  330. // NEW search_below_dst
  331. "\n " PTR "__objc_exception_false" VTABLE_ENTRY_AUTH(41165)
  332. // NEW has_unambiguous_public_base (fixme need this?)
  333. "\n " PTR "__objc_exception_abort1" VTABLE_ENTRY_AUTH(14357)
  334. // paranoia: die if libcxxabi adds anything else
  335. "\n " PTR "__objc_exception_abort2"
  336. "\n " PTR "__objc_exception_abort3"
  337. "\n " PTR "__objc_exception_abort4"
  338. );
  339. /***********************************************************************
  340. * Foundation customization
  341. **********************************************************************/
  342. /***********************************************************************
  343. * _objc_default_exception_preprocessor
  344. * Default exception preprocessor. Expected to be overridden by Foundation.
  345. **********************************************************************/
  346. static id _objc_default_exception_preprocessor(id exception)
  347. {
  348. return exception;
  349. }
  350. static objc_exception_preprocessor exception_preprocessor = _objc_default_exception_preprocessor;
  351. /***********************************************************************
  352. * _objc_default_exception_matcher
  353. * Default exception matcher. Expected to be overridden by Foundation.
  354. **********************************************************************/
  355. static int _objc_default_exception_matcher(Class catch_cls, id exception)
  356. {
  357. Class cls;
  358. for (cls = exception->getIsa();
  359. cls != nil;
  360. cls = cls->superclass)
  361. {
  362. if (cls == catch_cls) return 1;
  363. }
  364. return 0;
  365. }
  366. static objc_exception_matcher exception_matcher = _objc_default_exception_matcher;
  367. /***********************************************************************
  368. * _objc_default_uncaught_exception_handler
  369. * Default uncaught exception handler. Expected to be overridden by Foundation.
  370. **********************************************************************/
  371. static void _objc_default_uncaught_exception_handler(id exception)
  372. {
  373. }
  374. static objc_uncaught_exception_handler uncaught_handler = _objc_default_uncaught_exception_handler;
  375. /***********************************************************************
  376. * objc_setExceptionPreprocessor
  377. * Set a handler for preprocessing Objective-C exceptions.
  378. * Returns the previous handler.
  379. **********************************************************************/
  380. objc_exception_preprocessor
  381. objc_setExceptionPreprocessor(objc_exception_preprocessor fn)
  382. {
  383. objc_exception_preprocessor result = exception_preprocessor;
  384. exception_preprocessor = fn;
  385. return result;
  386. }
  387. /***********************************************************************
  388. * objc_setExceptionMatcher
  389. * Set a handler for matching Objective-C exceptions.
  390. * Returns the previous handler.
  391. **********************************************************************/
  392. objc_exception_matcher
  393. objc_setExceptionMatcher(objc_exception_matcher fn)
  394. {
  395. objc_exception_matcher result = exception_matcher;
  396. exception_matcher = fn;
  397. return result;
  398. }
  399. /***********************************************************************
  400. * objc_setUncaughtExceptionHandler
  401. * Set a handler for uncaught Objective-C exceptions.
  402. * Returns the previous handler.
  403. **********************************************************************/
  404. objc_uncaught_exception_handler
  405. objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler fn)
  406. {
  407. objc_uncaught_exception_handler result = uncaught_handler;
  408. uncaught_handler = fn;
  409. return result;
  410. }
  411. /***********************************************************************
  412. * Exception personality
  413. **********************************************************************/
  414. static void call_alt_handlers(struct _Unwind_Context *ctx);
  415. _Unwind_Reason_Code
  416. __objc_personality_v0(int version,
  417. _Unwind_Action actions,
  418. uint64_t exceptionClass,
  419. struct _Unwind_Exception *exceptionObject,
  420. struct _Unwind_Context *context)
  421. {
  422. bool unwinding = ((actions & _UA_CLEANUP_PHASE) ||
  423. (actions & _UA_FORCE_UNWIND));
  424. if (PrintExceptions) {
  425. _objc_inform("EXCEPTIONS: %s through frame [ip=%p sp=%p] "
  426. "for exception %p",
  427. unwinding ? "unwinding" : "searching",
  428. (void*)(_Unwind_GetIP(context)-1),
  429. (void*)_Unwind_GetCFA(context), exceptionObject);
  430. }
  431. // If we're executing the unwind, call this frame's alt handlers, if any.
  432. if (unwinding) {
  433. call_alt_handlers(context);
  434. }
  435. // Let C++ handle the unwind itself.
  436. return CXX_PERSONALITY(version, actions, exceptionClass,
  437. exceptionObject, context);
  438. }
  439. /***********************************************************************
  440. * Compiler ABI
  441. **********************************************************************/
  442. static void _objc_exception_destructor(void *exc_gen)
  443. {
  444. // Release the retain from objc_exception_throw().
  445. struct objc_exception *exc = (struct objc_exception *)exc_gen;
  446. id obj = exc->obj;
  447. if (PrintExceptions) {
  448. _objc_inform("EXCEPTIONS: releasing completed exception %p (object %p, a %s)",
  449. exc, obj, object_getClassName(obj));
  450. }
  451. [obj release];
  452. }
  453. void objc_exception_throw(id obj)
  454. {
  455. struct objc_exception *exc = (struct objc_exception *)
  456. __cxa_allocate_exception(sizeof(struct objc_exception));
  457. obj = (*exception_preprocessor)(obj);
  458. // Retain the exception object during unwinding
  459. // because otherwise an autorelease pool pop can cause a crash
  460. [obj retain];
  461. exc->obj = obj;
  462. exc->tinfo.vtable = objc_ehtype_vtable+2;
  463. exc->tinfo.name = object_getClassName(obj);
  464. exc->tinfo.cls_unremapped = obj ? obj->getIsa() : Nil;
  465. if (PrintExceptions) {
  466. _objc_inform("EXCEPTIONS: throwing %p (object %p, a %s)",
  467. exc, (void*)obj, object_getClassName(obj));
  468. }
  469. if (PrintExceptionThrow) {
  470. if (!PrintExceptions)
  471. _objc_inform("EXCEPTIONS: throwing %p (object %p, a %s)",
  472. exc, (void*)obj, object_getClassName(obj));
  473. void* callstack[500];
  474. int frameCount = backtrace(callstack, 500);
  475. backtrace_symbols_fd(callstack, frameCount, fileno(stderr));
  476. }
  477. OBJC_RUNTIME_OBJC_EXCEPTION_THROW(obj); // dtrace probe to log throw activity
  478. __cxa_throw(exc, &exc->tinfo, &_objc_exception_destructor);
  479. __builtin_trap();
  480. }
  481. void objc_exception_rethrow(void)
  482. {
  483. // exception_preprocessor doesn't get another bite of the apple
  484. if (PrintExceptions) {
  485. _objc_inform("EXCEPTIONS: rethrowing current exception");
  486. }
  487. OBJC_RUNTIME_OBJC_EXCEPTION_RETHROW(); // dtrace probe to log throw activity.
  488. __cxa_rethrow();
  489. __builtin_trap();
  490. }
  491. id objc_begin_catch(void *exc_gen)
  492. {
  493. if (PrintExceptions) {
  494. _objc_inform("EXCEPTIONS: handling exception %p at %p",
  495. exc_gen, __builtin_return_address(0));
  496. }
  497. // NOT actually an id in the catch(...) case!
  498. return (id)__cxa_begin_catch(exc_gen);
  499. }
  500. void objc_end_catch(void)
  501. {
  502. if (PrintExceptions) {
  503. _objc_inform("EXCEPTIONS: finishing handler");
  504. }
  505. __cxa_end_catch();
  506. }
  507. // `outer` is not passed by the new libcxxabi
  508. bool _objc_exception_do_catch(struct objc_typeinfo *catch_tinfo,
  509. struct objc_typeinfo *throw_tinfo,
  510. void **throw_obj_p,
  511. unsigned outer UNAVAILABLE_ATTRIBUTE)
  512. {
  513. id exception;
  514. if (throw_tinfo->vtable != objc_ehtype_vtable+2) {
  515. // Only objc types can be caught here.
  516. if (PrintExceptions) _objc_inform("EXCEPTIONS: skipping catch(?)");
  517. return false;
  518. }
  519. // Adjust exception pointer.
  520. // Old libcppabi: we lied about __is_pointer_p() so we have to do it here
  521. // New libcxxabi: we have to do it here regardless
  522. *throw_obj_p = **(void***)throw_obj_p;
  523. // `catch (id)` always catches objc types.
  524. if (catch_tinfo == &OBJC_EHTYPE_id) {
  525. if (PrintExceptions) _objc_inform("EXCEPTIONS: catch(id)");
  526. return true;
  527. }
  528. exception = *(id *)throw_obj_p;
  529. Class handler_cls = _class_remap(catch_tinfo->cls_unremapped);
  530. if (!handler_cls) {
  531. // catch handler's class is weak-linked and missing. Not a match.
  532. }
  533. else if ((*exception_matcher)(handler_cls, exception)) {
  534. if (PrintExceptions) _objc_inform("EXCEPTIONS: catch(%s)",
  535. handler_cls->nameForLogging());
  536. return true;
  537. }
  538. if (PrintExceptions) _objc_inform("EXCEPTIONS: skipping catch(%s)",
  539. handler_cls->nameForLogging());
  540. return false;
  541. }
  542. /***********************************************************************
  543. * _objc_terminate
  544. * Custom std::terminate handler.
  545. *
  546. * The uncaught exception callback is implemented as a std::terminate handler.
  547. * 1. Check if there's an active exception
  548. * 2. If so, check if it's an Objective-C exception
  549. * 3. If so, call our registered callback with the object.
  550. * 4. Finally, call the previous terminate handler.
  551. **********************************************************************/
  552. static void (*old_terminate)(void) = nil;
  553. static void _objc_terminate(void)
  554. {
  555. if (PrintExceptions) {
  556. _objc_inform("EXCEPTIONS: terminating");
  557. }
  558. if (! __cxa_current_exception_type()) {
  559. // No current exception.
  560. (*old_terminate)();
  561. }
  562. else {
  563. // There is a current exception. Check if it's an objc exception.
  564. @try {
  565. __cxa_rethrow();
  566. } @catch (id e) {
  567. // It's an objc object. Call Foundation's handler, if any.
  568. (*uncaught_handler)((id)e);
  569. (*old_terminate)();
  570. } @catch (...) {
  571. // It's not an objc object. Continue to C++ terminate.
  572. (*old_terminate)();
  573. }
  574. }
  575. }
  576. /***********************************************************************
  577. * objc_terminate
  578. * Calls std::terminate for clients who don't link to C++ themselves.
  579. * Called by the compiler if an exception is thrown
  580. * from a context where exceptions may not be thrown.
  581. **********************************************************************/
  582. void objc_terminate(void)
  583. {
  584. std::terminate();
  585. }
  586. /***********************************************************************
  587. * alt handler support - zerocost implementation only
  588. **********************************************************************/
  589. #if !SUPPORT_ALT_HANDLERS
  590. void _destroyAltHandlerList(struct alt_handler_list *list)
  591. {
  592. }
  593. static void call_alt_handlers(struct _Unwind_Context *ctx)
  594. {
  595. // unsupported in sjlj environments
  596. }
  597. #else
  598. #include <libunwind.h>
  599. #include <execinfo.h>
  600. #include <dispatch/dispatch.h>
  601. // Dwarf eh data encodings
  602. #define DW_EH_PE_omit 0xff // no data follows
  603. #define DW_EH_PE_absptr 0x00
  604. #define DW_EH_PE_uleb128 0x01
  605. #define DW_EH_PE_udata2 0x02
  606. #define DW_EH_PE_udata4 0x03
  607. #define DW_EH_PE_udata8 0x04
  608. #define DW_EH_PE_sleb128 0x09
  609. #define DW_EH_PE_sdata2 0x0A
  610. #define DW_EH_PE_sdata4 0x0B
  611. #define DW_EH_PE_sdata8 0x0C
  612. #define DW_EH_PE_pcrel 0x10
  613. #define DW_EH_PE_textrel 0x20
  614. #define DW_EH_PE_datarel 0x30
  615. #define DW_EH_PE_funcrel 0x40
  616. #define DW_EH_PE_aligned 0x50 // fixme
  617. #define DW_EH_PE_indirect 0x80 // gcc extension
  618. /***********************************************************************
  619. * read_uleb
  620. * Read a LEB-encoded unsigned integer from the address stored in *pp.
  621. * Increments *pp past the bytes read.
  622. * Adapted from DWARF Debugging Information Format 1.1, appendix 4
  623. **********************************************************************/
  624. static uintptr_t read_uleb(uintptr_t *pp)
  625. {
  626. uintptr_t result = 0;
  627. uintptr_t shift = 0;
  628. unsigned char byte;
  629. do {
  630. byte = *(const unsigned char *)(*pp)++;
  631. result |= (byte & 0x7f) << shift;
  632. shift += 7;
  633. } while (byte & 0x80);
  634. return result;
  635. }
  636. /***********************************************************************
  637. * read_sleb
  638. * Read a LEB-encoded signed integer from the address stored in *pp.
  639. * Increments *pp past the bytes read.
  640. * Adapted from DWARF Debugging Information Format 1.1, appendix 4
  641. **********************************************************************/
  642. static intptr_t read_sleb(uintptr_t *pp)
  643. {
  644. uintptr_t result = 0;
  645. uintptr_t shift = 0;
  646. unsigned char byte;
  647. do {
  648. byte = *(const unsigned char *)(*pp)++;
  649. result |= (byte & 0x7f) << shift;
  650. shift += 7;
  651. } while (byte & 0x80);
  652. if ((shift < 8*sizeof(intptr_t)) && (byte & 0x40)) {
  653. result |= ((intptr_t)-1) << shift;
  654. }
  655. return result;
  656. }
  657. /***********************************************************************
  658. * read_address
  659. * Reads an encoded address from the address stored in *pp.
  660. * Increments *pp past the bytes read.
  661. * The data is interpreted according to the given dwarf encoding
  662. * and base addresses.
  663. **********************************************************************/
  664. static uintptr_t read_address(uintptr_t *pp,
  665. const struct dwarf_eh_bases *bases,
  666. unsigned char encoding)
  667. {
  668. uintptr_t result = 0;
  669. uintptr_t oldp = *pp;
  670. // fixme need DW_EH_PE_aligned?
  671. #define READ(type) \
  672. result = *(type *)(*pp); \
  673. *pp += sizeof(type);
  674. if (encoding == DW_EH_PE_omit) return 0;
  675. switch (encoding & 0x0f) {
  676. case DW_EH_PE_absptr:
  677. READ(uintptr_t);
  678. break;
  679. case DW_EH_PE_uleb128:
  680. result = read_uleb(pp);
  681. break;
  682. case DW_EH_PE_udata2:
  683. READ(uint16_t);
  684. break;
  685. case DW_EH_PE_udata4:
  686. READ(uint32_t);
  687. break;
  688. #if __LP64__
  689. case DW_EH_PE_udata8:
  690. READ(uint64_t);
  691. break;
  692. #endif
  693. case DW_EH_PE_sleb128:
  694. result = read_sleb(pp);
  695. break;
  696. case DW_EH_PE_sdata2:
  697. READ(int16_t);
  698. break;
  699. case DW_EH_PE_sdata4:
  700. READ(int32_t);
  701. break;
  702. #if __LP64__
  703. case DW_EH_PE_sdata8:
  704. READ(int64_t);
  705. break;
  706. #endif
  707. default:
  708. _objc_inform("unknown DWARF EH encoding 0x%x at %p",
  709. encoding, (void *)*pp);
  710. break;
  711. }
  712. #undef READ
  713. if (result) {
  714. switch (encoding & 0x70) {
  715. case DW_EH_PE_pcrel:
  716. // fixme correct?
  717. result += (uintptr_t)oldp;
  718. break;
  719. case DW_EH_PE_textrel:
  720. result += bases->tbase;
  721. break;
  722. case DW_EH_PE_datarel:
  723. result += bases->dbase;
  724. break;
  725. case DW_EH_PE_funcrel:
  726. result += bases->func;
  727. break;
  728. case DW_EH_PE_aligned:
  729. _objc_inform("unknown DWARF EH encoding 0x%x at %p",
  730. encoding, (void *)*pp);
  731. break;
  732. default:
  733. // no adjustment
  734. break;
  735. }
  736. if (encoding & DW_EH_PE_indirect) {
  737. result = *(uintptr_t *)result;
  738. }
  739. }
  740. return (uintptr_t)result;
  741. }
  742. struct frame_ips {
  743. uintptr_t start;
  744. uintptr_t end;
  745. };
  746. struct frame_range {
  747. uintptr_t ip_start;
  748. uintptr_t ip_end;
  749. uintptr_t cfa;
  750. // precise ranges within ip_start..ip_end; nil or {0,0} terminated
  751. frame_ips *ips;
  752. };
  753. static bool isObjCExceptionCatcher(uintptr_t lsda, uintptr_t ip,
  754. const struct dwarf_eh_bases* bases,
  755. struct frame_range *frame)
  756. {
  757. unsigned char LPStart_enc = *(const unsigned char *)lsda++;
  758. if (LPStart_enc != DW_EH_PE_omit) {
  759. read_address(&lsda, bases, LPStart_enc); // LPStart
  760. }
  761. unsigned char TType_enc = *(const unsigned char *)lsda++;
  762. if (TType_enc != DW_EH_PE_omit) {
  763. read_uleb(&lsda); // TType
  764. }
  765. unsigned char call_site_enc = *(const unsigned char *)lsda++;
  766. uintptr_t length = read_uleb(&lsda);
  767. uintptr_t call_site_table = lsda;
  768. uintptr_t call_site_table_end = call_site_table + length;
  769. uintptr_t action_record_table = call_site_table_end;
  770. uintptr_t action_record = 0;
  771. uintptr_t p = call_site_table;
  772. uintptr_t try_start;
  773. uintptr_t try_end;
  774. uintptr_t try_landing_pad;
  775. while (p < call_site_table_end) {
  776. uintptr_t start = read_address(&p, bases, call_site_enc)+bases->func;
  777. uintptr_t len = read_address(&p, bases, call_site_enc);
  778. uintptr_t pad = read_address(&p, bases, call_site_enc);
  779. uintptr_t action = read_uleb(&p);
  780. if (ip < start) {
  781. // no more source ranges
  782. return false;
  783. }
  784. else if (ip < start + len) {
  785. // found the range
  786. if (!pad) return false; // ...but it has no landing pad
  787. // found the landing pad
  788. action_record = action ? action_record_table + action - 1 : 0;
  789. try_start = start;
  790. try_end = start + len;
  791. try_landing_pad = pad;
  792. break;
  793. }
  794. }
  795. if (!action_record) return false; // no catch handlers
  796. // has handlers, destructors, and/or throws specifications
  797. // Use this frame if it has any handlers
  798. bool has_handler = false;
  799. p = action_record;
  800. intptr_t offset;
  801. do {
  802. intptr_t filter = read_sleb(&p);
  803. uintptr_t temp = p;
  804. offset = read_sleb(&temp);
  805. p += offset;
  806. if (filter < 0) {
  807. // throws specification - ignore
  808. } else if (filter == 0) {
  809. // destructor - ignore
  810. } else /* filter >= 0 */ {
  811. // catch handler - use this frame
  812. has_handler = true;
  813. break;
  814. }
  815. } while (offset);
  816. if (!has_handler) return false;
  817. // Count the number of source ranges with the same landing pad as our match
  818. unsigned int range_count = 0;
  819. p = call_site_table;
  820. while (p < call_site_table_end) {
  821. /*start*/ read_address(&p, bases, call_site_enc)/*+bases->func*/;
  822. /*len*/ read_address(&p, bases, call_site_enc);
  823. uintptr_t pad = read_address(&p, bases, call_site_enc);
  824. /*action*/ read_uleb(&p);
  825. if (pad == try_landing_pad) {
  826. range_count++;
  827. }
  828. }
  829. if (range_count == 1) {
  830. // No other source ranges with the same landing pad. We're done here.
  831. frame->ips = nil;
  832. }
  833. else {
  834. // Record all ranges with the same landing pad as our match.
  835. frame->ips = (frame_ips *)
  836. malloc((range_count + 1) * sizeof(frame->ips[0]));
  837. unsigned int r = 0;
  838. p = call_site_table;
  839. while (p < call_site_table_end) {
  840. uintptr_t start = read_address(&p, bases, call_site_enc)+bases->func;
  841. uintptr_t len = read_address(&p, bases, call_site_enc);
  842. uintptr_t pad = read_address(&p, bases, call_site_enc);
  843. /*action*/ read_uleb(&p);
  844. if (pad == try_landing_pad) {
  845. if (start < try_start) try_start = start;
  846. if (start+len > try_end) try_end = start+len;
  847. frame->ips[r].start = start;
  848. frame->ips[r].end = start+len;
  849. r++;
  850. }
  851. }
  852. frame->ips[r].start = 0;
  853. frame->ips[r].end = 0;
  854. }
  855. frame->ip_start = try_start;
  856. frame->ip_end = try_end;
  857. return true;
  858. }
  859. static struct frame_range findHandler(void)
  860. {
  861. // walk stack looking for frame with objc catch handler
  862. unw_context_t uc;
  863. unw_cursor_t cursor;
  864. unw_proc_info_t info;
  865. unw_getcontext(&uc);
  866. unw_init_local(&cursor, &uc);
  867. while ( (unw_step(&cursor) > 0) && (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS) ) {
  868. // must use objc personality handler
  869. if ( info.handler != (uintptr_t)__objc_personality_v0 )
  870. continue;
  871. // must have landing pad
  872. if ( info.lsda == 0 )
  873. continue;
  874. // must have landing pad that catches objc exceptions
  875. struct dwarf_eh_bases bases;
  876. bases.tbase = 0; // from unwind-dw2-fde-darwin.c:examine_objects()
  877. bases.dbase = 0; // from unwind-dw2-fde-darwin.c:examine_objects()
  878. bases.func = info.start_ip;
  879. unw_word_t ip;
  880. unw_get_reg(&cursor, UNW_REG_IP, &ip);
  881. ip -= 1;
  882. struct frame_range try_range = {0, 0, 0, 0};
  883. if ( isObjCExceptionCatcher(info.lsda, ip, &bases, &try_range) ) {
  884. unw_word_t cfa;
  885. unw_get_reg(&cursor, UNW_REG_SP, &cfa);
  886. try_range.cfa = cfa;
  887. return try_range;
  888. }
  889. }
  890. return (struct frame_range){0, 0, 0, 0};
  891. }
  892. // This data structure assumes the number of
  893. // active alt handlers per frame is small.
  894. // for OBJC_DEBUG_ALT_HANDLERS, record the call to objc_addExceptionHandler.
  895. #define BACKTRACE_COUNT 46
  896. #define THREADNAME_COUNT 64
  897. struct alt_handler_debug {
  898. uintptr_t token;
  899. int backtraceSize;
  900. void *backtrace[BACKTRACE_COUNT];
  901. char thread[THREADNAME_COUNT];
  902. char queue[THREADNAME_COUNT];
  903. };
  904. struct alt_handler_data {
  905. struct frame_range frame;
  906. objc_exception_handler fn;
  907. void *context;
  908. struct alt_handler_debug *debug;
  909. };
  910. struct alt_handler_list {
  911. unsigned int allocated;
  912. unsigned int used;
  913. struct alt_handler_data *handlers;
  914. struct alt_handler_list *next_DEBUGONLY;
  915. };
  916. static struct alt_handler_list *DebugLists;
  917. static uintptr_t DebugCounter;
  918. __attribute__((noinline, noreturn))
  919. void alt_handler_error(uintptr_t token);
  920. static struct alt_handler_list *
  921. fetch_handler_list(bool create)
  922. {
  923. _objc_pthread_data *data = _objc_fetch_pthread_data(create);
  924. if (!data) return nil;
  925. struct alt_handler_list *list = data->handlerList;
  926. if (!list) {
  927. if (!create) return nil;
  928. list = (struct alt_handler_list *)calloc(1, sizeof(*list));
  929. data->handlerList = list;
  930. if (DebugAltHandlers) {
  931. // Save this list so the debug code can find it from other threads
  932. mutex_locker_t lock(AltHandlerDebugLock);
  933. list->next_DEBUGONLY = DebugLists;
  934. DebugLists = list;
  935. }
  936. }
  937. return list;
  938. }
  939. void _destroyAltHandlerList(struct alt_handler_list *list)
  940. {
  941. if (list) {
  942. if (DebugAltHandlers) {
  943. // Detach from the list-of-lists.
  944. mutex_locker_t lock(AltHandlerDebugLock);
  945. struct alt_handler_list **listp = &DebugLists;
  946. while (*listp && *listp != list) listp = &(*listp)->next_DEBUGONLY;
  947. if (*listp) *listp = (*listp)->next_DEBUGONLY;
  948. }
  949. if (list->handlers) {
  950. for (unsigned int i = 0; i < list->allocated; i++) {
  951. if (list->handlers[i].frame.ips) {
  952. free(list->handlers[i].frame.ips);
  953. }
  954. }
  955. free(list->handlers);
  956. }
  957. free(list);
  958. }
  959. }
  960. uintptr_t objc_addExceptionHandler(objc_exception_handler fn, void *context)
  961. {
  962. // Find the closest enclosing frame with objc catch handlers
  963. struct frame_range target_frame = findHandler();
  964. if (!target_frame.ip_start) {
  965. // No suitable enclosing handler found.
  966. return 0;
  967. }
  968. // Record this alt handler for the discovered frame.
  969. struct alt_handler_list *list = fetch_handler_list(YES);
  970. unsigned int i = 0;
  971. if (list->used == list->allocated) {
  972. list->allocated = list->allocated*2 ?: 4;
  973. list->handlers = (struct alt_handler_data *)
  974. realloc(list->handlers,
  975. list->allocated * sizeof(list->handlers[0]));
  976. bzero(&list->handlers[list->used], (list->allocated - list->used) * sizeof(list->handlers[0]));
  977. i = list->used;
  978. }
  979. else {
  980. for (i = 0; i < list->allocated; i++) {
  981. if (list->handlers[i].frame.ip_start == 0 &&
  982. list->handlers[i].frame.ip_end == 0 &&
  983. list->handlers[i].frame.cfa == 0)
  984. {
  985. break;
  986. }
  987. }
  988. if (i == list->allocated) {
  989. _objc_fatal("alt handlers in objc runtime are buggy!");
  990. }
  991. }
  992. struct alt_handler_data *data = &list->handlers[i];
  993. data->frame = target_frame;
  994. data->fn = fn;
  995. data->context = context;
  996. list->used++;
  997. uintptr_t token = i+1;
  998. if (DebugAltHandlers) {
  999. // Record backtrace in case this handler is misused later.
  1000. mutex_locker_t lock(AltHandlerDebugLock);
  1001. token = DebugCounter++;
  1002. if (token == 0) token = DebugCounter++;
  1003. if (!data->debug) {
  1004. data->debug = (struct alt_handler_debug *)
  1005. calloc(sizeof(*data->debug), 1);
  1006. } else {
  1007. bzero(data->debug, sizeof(*data->debug));
  1008. }
  1009. pthread_getname_np(pthread_self(), data->debug->thread, THREADNAME_COUNT);
  1010. strlcpy(data->debug->queue,
  1011. dispatch_queue_get_label(dispatch_get_current_queue()),
  1012. THREADNAME_COUNT);
  1013. data->debug->backtraceSize =
  1014. backtrace(data->debug->backtrace, BACKTRACE_COUNT);
  1015. data->debug->token = token;
  1016. }
  1017. if (PrintAltHandlers) {
  1018. _objc_inform("ALT HANDLERS: installing alt handler #%lu %p(%p) on "
  1019. "frame [ip=%p..%p sp=%p]", (unsigned long)token,
  1020. data->fn, data->context, (void *)data->frame.ip_start,
  1021. (void *)data->frame.ip_end, (void *)data->frame.cfa);
  1022. if (data->frame.ips) {
  1023. unsigned int r = 0;
  1024. while (1) {
  1025. uintptr_t start = data->frame.ips[r].start;
  1026. uintptr_t end = data->frame.ips[r].end;
  1027. r++;
  1028. if (start == 0 && end == 0) break;
  1029. _objc_inform("ALT HANDLERS: ip=%p..%p",
  1030. (void*)start, (void*)end);
  1031. }
  1032. }
  1033. }
  1034. if (list->used > 1000) {
  1035. static int warned = 0;
  1036. if (!warned) {
  1037. _objc_inform("ALT HANDLERS: *** over 1000 alt handlers installed; "
  1038. "this is probably a bug");
  1039. warned = 1;
  1040. }
  1041. }
  1042. return token;
  1043. }
  1044. void objc_removeExceptionHandler(uintptr_t token)
  1045. {
  1046. if (!token) {
  1047. // objc_addExceptionHandler failed
  1048. return;
  1049. }
  1050. struct alt_handler_list *list = fetch_handler_list(NO);
  1051. if (!list || !list->handlers) {
  1052. // no alt handlers active
  1053. alt_handler_error(token);
  1054. }
  1055. uintptr_t i = token-1;
  1056. if (DebugAltHandlers) {
  1057. // search for the token instead of using token-1
  1058. for (i = 0; i < list->allocated; i++) {
  1059. struct alt_handler_data *data = &list->handlers[i];
  1060. if (data->debug && data->debug->token == token) break;
  1061. }
  1062. }
  1063. if (i >= list->allocated) {
  1064. // token out of range
  1065. alt_handler_error(token);
  1066. }
  1067. struct alt_handler_data *data = &list->handlers[i];
  1068. if (data->frame.ip_start == 0 && data->frame.ip_end == 0 && data->frame.cfa == 0) {
  1069. // token in range, but invalid
  1070. alt_handler_error(token);
  1071. }
  1072. if (PrintAltHandlers) {
  1073. _objc_inform("ALT HANDLERS: removing alt handler #%lu %p(%p) on "
  1074. "frame [ip=%p..%p sp=%p]", (unsigned long)token,
  1075. data->fn, data->context, (void *)data->frame.ip_start,
  1076. (void *)data->frame.ip_end, (void *)data->frame.cfa);
  1077. }
  1078. if (data->debug) free(data->debug);
  1079. if (data->frame.ips) free(data->frame.ips);
  1080. bzero(data, sizeof(*data));
  1081. list->used--;
  1082. }
  1083. BREAKPOINT_FUNCTION(
  1084. void objc_alt_handler_error(void));
  1085. __attribute__((noinline, noreturn))
  1086. void alt_handler_error(uintptr_t token)
  1087. {
  1088. _objc_inform
  1089. ("objc_removeExceptionHandler() called with unknown alt handler; "
  1090. "this is probably a bug in multithreaded AppKit use. "
  1091. "Set environment variable OBJC_DEBUG_ALT_HANDLERS=YES "
  1092. "or break in objc_alt_handler_error() to debug.");
  1093. if (DebugAltHandlers) {
  1094. AltHandlerDebugLock.lock();
  1095. // Search other threads' alt handler lists for this handler.
  1096. struct alt_handler_list *list;
  1097. for (list = DebugLists; list; list = list->next_DEBUGONLY) {
  1098. unsigned h;
  1099. for (h = 0; h < list->allocated; h++) {
  1100. struct alt_handler_data *data = &list->handlers[h];
  1101. if (data->debug && data->debug->token == token) {
  1102. // found it
  1103. int i;
  1104. // Build a string from the recorded backtrace
  1105. char *symbolString;
  1106. char **symbols =
  1107. backtrace_symbols(data->debug->backtrace,
  1108. data->debug->backtraceSize);
  1109. size_t len = 1;
  1110. for (i = 0; i < data->debug->backtraceSize; i++){
  1111. len += 4 + strlen(symbols[i]) + 1;
  1112. }
  1113. symbolString = (char *)calloc(len, 1);
  1114. for (i = 0; i < data->debug->backtraceSize; i++){
  1115. strcat(symbolString, " ");
  1116. strcat(symbolString, symbols[i]);
  1117. strcat(symbolString, "\n");
  1118. }
  1119. free(symbols);
  1120. _objc_inform_now_and_on_crash
  1121. ("The matching objc_addExceptionHandler() was called "
  1122. "by:\nThread '%s': Dispatch queue: '%s': \n%s",
  1123. data->debug->thread, data->debug->queue, symbolString);
  1124. goto done;
  1125. }
  1126. }
  1127. }
  1128. done:
  1129. AltHandlerDebugLock.unlock();
  1130. }
  1131. objc_alt_handler_error();
  1132. _objc_fatal
  1133. ("objc_removeExceptionHandler() called with unknown alt handler; "
  1134. "this is probably a bug in multithreaded AppKit use. ");
  1135. }
  1136. // called in order registered, to match 32-bit _NSAddAltHandler2
  1137. // fixme reverse registration order matches c++ destructors better
  1138. static void call_alt_handlers(struct _Unwind_Context *ctx)
  1139. {
  1140. uintptr_t ip = _Unwind_GetIP(ctx) - 1;
  1141. uintptr_t cfa = _Unwind_GetCFA(ctx);
  1142. unsigned int i;
  1143. struct alt_handler_list *list = fetch_handler_list(NO);
  1144. if (!list || list->used == 0) return;
  1145. for (i = 0; i < list->allocated; i++) {
  1146. struct alt_handler_data *data = &list->handlers[i];
  1147. if (ip >= data->frame.ip_start && ip < data->frame.ip_end && data->frame.cfa == cfa)
  1148. {
  1149. if (data->frame.ips) {
  1150. unsigned int r = 0;
  1151. bool found;
  1152. while (1) {
  1153. uintptr_t start = data->frame.ips[r].start;
  1154. uintptr_t end = data->frame.ips[r].end;
  1155. r++;
  1156. if (start == 0 && end == 0) {
  1157. found = false;
  1158. break;
  1159. }
  1160. if (ip >= start && ip < end) {
  1161. found = true;
  1162. break;
  1163. }
  1164. }
  1165. if (!found) continue;
  1166. }
  1167. // Copy and clear before the callback, in case the
  1168. // callback manipulates the alt handler list.
  1169. struct alt_handler_data copy = *data;
  1170. bzero(data, sizeof(*data));
  1171. list->used--;
  1172. if (PrintExceptions || PrintAltHandlers) {
  1173. _objc_inform("EXCEPTIONS: calling alt handler %p(%p) from "
  1174. "frame [ip=%p..%p sp=%p]", copy.fn, copy.context,
  1175. (void *)copy.frame.ip_start,
  1176. (void *)copy.frame.ip_end,
  1177. (void *)copy.frame.cfa);
  1178. }
  1179. if (copy.fn) (*copy.fn)(nil, copy.context);
  1180. if (copy.frame.ips) free(copy.frame.ips);
  1181. }
  1182. }
  1183. }
  1184. // SUPPORT_ALT_HANDLERS
  1185. #endif
  1186. /***********************************************************************
  1187. * exception_init
  1188. * Initialize libobjc's exception handling system.
  1189. * Called by map_images().
  1190. **********************************************************************/
  1191. void exception_init(void)
  1192. {
  1193. old_terminate = std::set_terminate(&_objc_terminate);
  1194. }
  1195. // __OBJC2__
  1196. #endif
  1197. // Define this everywhere even if it isn't used, to simplify fork() safety code
  1198. mutex_t AltHandlerDebugLock;