objc-exception.mm 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442
  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 objc_thread_self() found (someday) XXX
  108. objc_thread_t self = objc_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" {
  266. __attribute__((used))
  267. void _objc_exception_noop(void) { }
  268. __attribute__((used))
  269. bool _objc_exception_false(void) { return 0; }
  270. // bool _objc_exception_true(void) { return 1; }
  271. __attribute__((used))
  272. void _objc_exception_abort1(void) {
  273. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 1);
  274. }
  275. __attribute__((used))
  276. void _objc_exception_abort2(void) {
  277. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 2);
  278. }
  279. __attribute__((used))
  280. void _objc_exception_abort3(void) {
  281. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 3);
  282. }
  283. __attribute__((used))
  284. void _objc_exception_abort4(void) {
  285. _objc_fatal("unexpected call into objc exception typeinfo vtable %d", 4);
  286. }
  287. __attribute__((used))
  288. bool _objc_exception_do_catch(struct objc_typeinfo *catch_tinfo,
  289. struct objc_typeinfo *throw_tinfo,
  290. void **throw_obj_p,
  291. unsigned outer);
  292. }
  293. // C++ pointers to vtables are signed with no extra data.
  294. // C++ vtable entries are signed with a number derived from the function name.
  295. // For this fake vtable, we hardcode number as deciphered from the
  296. // assembly output during libc++abi's build.
  297. #if __has_feature(ptrauth_calls)
  298. # define VTABLE_PTR_AUTH "@AUTH(da, 0)"
  299. # define VTABLE_ENTRY_AUTH(x) "@AUTH(ia," #x ",addr)"
  300. #else
  301. # define VTABLE_PTR_AUTH ""
  302. # define VTABLE_ENTRY_AUTH(x) ""
  303. #endif
  304. #if __LP64__
  305. # define PTR ".quad "
  306. # define TWOPTRSIZE "16"
  307. #else
  308. # define PTR ".long "
  309. # define TWOPTRSIZE "8"
  310. #endif
  311. // Hand-built vtable for objc exception typeinfo.
  312. // "OLD" is GNU libcpp, "NEW" is libc++abi.
  313. asm(
  314. "\n .cstring"
  315. "\n l_.id_str: .asciz \"id\""
  316. "\n .section __DATA,__const"
  317. "\n .globl _OBJC_EHTYPE_id"
  318. "\n .globl _objc_ehtype_vtable"
  319. "\n .p2align 4"
  320. "\n _OBJC_EHTYPE_id:"
  321. "\n " PTR "(_objc_ehtype_vtable+" TWOPTRSIZE ") " VTABLE_PTR_AUTH
  322. "\n " PTR "l_.id_str"
  323. "\n " PTR "0"
  324. "\n _objc_ehtype_vtable:"
  325. "\n " PTR "0"
  326. // typeinfo's typeinfo - fixme hack
  327. "\n " PTR "_OBJC_EHTYPE_id"
  328. // destructor and in-place destructor
  329. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(52634)
  330. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(10344)
  331. // OLD __is_pointer_p
  332. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(6889)
  333. // OLD __is_function_p
  334. "\n " PTR "__objc_exception_noop" VTABLE_ENTRY_AUTH(23080)
  335. // OLD __do_catch, NEW can_catch
  336. "\n " PTR "__objc_exception_do_catch" VTABLE_ENTRY_AUTH(27434)
  337. // OLD __do_upcast, NEW search_above_dst
  338. "\n " PTR "__objc_exception_false" VTABLE_ENTRY_AUTH(48481)
  339. // NEW search_below_dst
  340. "\n " PTR "__objc_exception_false" VTABLE_ENTRY_AUTH(41165)
  341. // NEW has_unambiguous_public_base (fixme need this?)
  342. "\n " PTR "__objc_exception_abort1" VTABLE_ENTRY_AUTH(14357)
  343. // paranoia: die if libcxxabi adds anything else
  344. "\n " PTR "__objc_exception_abort2"
  345. "\n " PTR "__objc_exception_abort3"
  346. "\n " PTR "__objc_exception_abort4"
  347. );
  348. /***********************************************************************
  349. * Foundation customization
  350. **********************************************************************/
  351. /***********************************************************************
  352. * _objc_default_exception_preprocessor
  353. * Default exception preprocessor. Expected to be overridden by Foundation.
  354. **********************************************************************/
  355. static id _objc_default_exception_preprocessor(id exception)
  356. {
  357. return exception;
  358. }
  359. static objc_exception_preprocessor exception_preprocessor = _objc_default_exception_preprocessor;
  360. /***********************************************************************
  361. * _objc_default_exception_matcher
  362. * Default exception matcher. Expected to be overridden by Foundation.
  363. **********************************************************************/
  364. static int _objc_default_exception_matcher(Class catch_cls, id exception)
  365. {
  366. Class cls;
  367. for (cls = exception->getIsa();
  368. cls != nil;
  369. cls = cls->superclass)
  370. {
  371. if (cls == catch_cls) return 1;
  372. }
  373. return 0;
  374. }
  375. static objc_exception_matcher exception_matcher = _objc_default_exception_matcher;
  376. /***********************************************************************
  377. * _objc_default_uncaught_exception_handler
  378. * Default uncaught exception handler. Expected to be overridden by Foundation.
  379. **********************************************************************/
  380. static void _objc_default_uncaught_exception_handler(id exception)
  381. {
  382. }
  383. static objc_uncaught_exception_handler uncaught_handler = _objc_default_uncaught_exception_handler;
  384. /***********************************************************************
  385. * objc_setExceptionPreprocessor
  386. * Set a handler for preprocessing Objective-C exceptions.
  387. * Returns the previous handler.
  388. **********************************************************************/
  389. objc_exception_preprocessor
  390. objc_setExceptionPreprocessor(objc_exception_preprocessor fn)
  391. {
  392. objc_exception_preprocessor result = exception_preprocessor;
  393. exception_preprocessor = fn;
  394. return result;
  395. }
  396. /***********************************************************************
  397. * objc_setExceptionMatcher
  398. * Set a handler for matching Objective-C exceptions.
  399. * Returns the previous handler.
  400. **********************************************************************/
  401. objc_exception_matcher
  402. objc_setExceptionMatcher(objc_exception_matcher fn)
  403. {
  404. objc_exception_matcher result = exception_matcher;
  405. exception_matcher = fn;
  406. return result;
  407. }
  408. /***********************************************************************
  409. * objc_setUncaughtExceptionHandler
  410. * Set a handler for uncaught Objective-C exceptions.
  411. * Returns the previous handler.
  412. **********************************************************************/
  413. objc_uncaught_exception_handler
  414. objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler fn)
  415. {
  416. objc_uncaught_exception_handler result = uncaught_handler;
  417. uncaught_handler = fn;
  418. return result;
  419. }
  420. /***********************************************************************
  421. * Exception personality
  422. **********************************************************************/
  423. static void call_alt_handlers(struct _Unwind_Context *ctx);
  424. _Unwind_Reason_Code
  425. __objc_personality_v0(int version,
  426. _Unwind_Action actions,
  427. uint64_t exceptionClass,
  428. struct _Unwind_Exception *exceptionObject,
  429. struct _Unwind_Context *context)
  430. {
  431. bool unwinding = ((actions & _UA_CLEANUP_PHASE) ||
  432. (actions & _UA_FORCE_UNWIND));
  433. if (PrintExceptions) {
  434. _objc_inform("EXCEPTIONS: %s through frame [ip=%p sp=%p] "
  435. "for exception %p",
  436. unwinding ? "unwinding" : "searching",
  437. (void*)(_Unwind_GetIP(context)-1),
  438. (void*)_Unwind_GetCFA(context), exceptionObject);
  439. }
  440. // If we're executing the unwind, call this frame's alt handlers, if any.
  441. if (unwinding) {
  442. call_alt_handlers(context);
  443. }
  444. // Let C++ handle the unwind itself.
  445. return CXX_PERSONALITY(version, actions, exceptionClass,
  446. exceptionObject, context);
  447. }
  448. /***********************************************************************
  449. * Compiler ABI
  450. **********************************************************************/
  451. static void _objc_exception_destructor(void *exc_gen)
  452. {
  453. // Release the retain from objc_exception_throw().
  454. struct objc_exception *exc = (struct objc_exception *)exc_gen;
  455. id obj = exc->obj;
  456. if (PrintExceptions) {
  457. _objc_inform("EXCEPTIONS: releasing completed exception %p (object %p, a %s)",
  458. exc, obj, object_getClassName(obj));
  459. }
  460. [obj release];
  461. }
  462. void objc_exception_throw(id obj)
  463. {
  464. struct objc_exception *exc = (struct objc_exception *)
  465. __cxa_allocate_exception(sizeof(struct objc_exception));
  466. obj = (*exception_preprocessor)(obj);
  467. // Retain the exception object during unwinding
  468. // because otherwise an autorelease pool pop can cause a crash
  469. [obj retain];
  470. exc->obj = obj;
  471. exc->tinfo.vtable = objc_ehtype_vtable+2;
  472. exc->tinfo.name = object_getClassName(obj);
  473. exc->tinfo.cls_unremapped = obj ? obj->getIsa() : Nil;
  474. if (PrintExceptions) {
  475. _objc_inform("EXCEPTIONS: throwing %p (object %p, a %s)",
  476. exc, (void*)obj, object_getClassName(obj));
  477. }
  478. if (PrintExceptionThrow) {
  479. if (!PrintExceptions)
  480. _objc_inform("EXCEPTIONS: throwing %p (object %p, a %s)",
  481. exc, (void*)obj, object_getClassName(obj));
  482. void* callstack[500];
  483. int frameCount = backtrace(callstack, 500);
  484. backtrace_symbols_fd(callstack, frameCount, fileno(stderr));
  485. }
  486. OBJC_RUNTIME_OBJC_EXCEPTION_THROW(obj); // dtrace probe to log throw activity
  487. __cxa_throw(exc, &exc->tinfo, &_objc_exception_destructor);
  488. __builtin_trap();
  489. }
  490. void objc_exception_rethrow(void)
  491. {
  492. // exception_preprocessor doesn't get another bite of the apple
  493. if (PrintExceptions) {
  494. _objc_inform("EXCEPTIONS: rethrowing current exception");
  495. }
  496. OBJC_RUNTIME_OBJC_EXCEPTION_RETHROW(); // dtrace probe to log throw activity.
  497. __cxa_rethrow();
  498. __builtin_trap();
  499. }
  500. id objc_begin_catch(void *exc_gen)
  501. {
  502. if (PrintExceptions) {
  503. _objc_inform("EXCEPTIONS: handling exception %p at %p",
  504. exc_gen, __builtin_return_address(0));
  505. }
  506. // NOT actually an id in the catch(...) case!
  507. return (id)__cxa_begin_catch(exc_gen);
  508. }
  509. void objc_end_catch(void)
  510. {
  511. if (PrintExceptions) {
  512. _objc_inform("EXCEPTIONS: finishing handler");
  513. }
  514. __cxa_end_catch();
  515. }
  516. // `outer` is not passed by the new libcxxabi
  517. bool _objc_exception_do_catch(struct objc_typeinfo *catch_tinfo,
  518. struct objc_typeinfo *throw_tinfo,
  519. void **throw_obj_p,
  520. unsigned outer UNAVAILABLE_ATTRIBUTE)
  521. {
  522. id exception;
  523. if (throw_tinfo->vtable != objc_ehtype_vtable+2) {
  524. // Only objc types can be caught here.
  525. if (PrintExceptions) _objc_inform("EXCEPTIONS: skipping catch(?)");
  526. return false;
  527. }
  528. // Adjust exception pointer.
  529. // Old libcppabi: we lied about __is_pointer_p() so we have to do it here
  530. // New libcxxabi: we have to do it here regardless
  531. *throw_obj_p = **(void***)throw_obj_p;
  532. // `catch (id)` always catches objc types.
  533. if (catch_tinfo == &OBJC_EHTYPE_id) {
  534. if (PrintExceptions) _objc_inform("EXCEPTIONS: catch(id)");
  535. return true;
  536. }
  537. exception = *(id *)throw_obj_p;
  538. Class handler_cls = _class_remap(catch_tinfo->cls_unremapped);
  539. if (!handler_cls) {
  540. // catch handler's class is weak-linked and missing. Not a match.
  541. }
  542. else if ((*exception_matcher)(handler_cls, exception)) {
  543. if (PrintExceptions) _objc_inform("EXCEPTIONS: catch(%s)",
  544. handler_cls->nameForLogging());
  545. return true;
  546. }
  547. if (PrintExceptions) _objc_inform("EXCEPTIONS: skipping catch(%s)",
  548. handler_cls->nameForLogging());
  549. return false;
  550. }
  551. /***********************************************************************
  552. * _objc_terminate
  553. * Custom std::terminate handler.
  554. *
  555. * The uncaught exception callback is implemented as a std::terminate handler.
  556. * 1. Check if there's an active exception
  557. * 2. If so, check if it's an Objective-C exception
  558. * 3. If so, call our registered callback with the object.
  559. * 4. Finally, call the previous terminate handler.
  560. **********************************************************************/
  561. static void (*old_terminate)(void) = nil;
  562. static void _objc_terminate(void)
  563. {
  564. if (PrintExceptions) {
  565. _objc_inform("EXCEPTIONS: terminating");
  566. }
  567. if (! __cxa_current_exception_type()) {
  568. // No current exception.
  569. (*old_terminate)();
  570. }
  571. else {
  572. // There is a current exception. Check if it's an objc exception.
  573. @try {
  574. __cxa_rethrow();
  575. } @catch (id e) {
  576. // It's an objc object. Call Foundation's handler, if any.
  577. (*uncaught_handler)((id)e);
  578. (*old_terminate)();
  579. } @catch (...) {
  580. // It's not an objc object. Continue to C++ terminate.
  581. (*old_terminate)();
  582. }
  583. }
  584. }
  585. /***********************************************************************
  586. * objc_terminate
  587. * Calls std::terminate for clients who don't link to C++ themselves.
  588. * Called by the compiler if an exception is thrown
  589. * from a context where exceptions may not be thrown.
  590. **********************************************************************/
  591. void objc_terminate(void)
  592. {
  593. std::terminate();
  594. }
  595. /***********************************************************************
  596. * alt handler support - zerocost implementation only
  597. **********************************************************************/
  598. #if !SUPPORT_ALT_HANDLERS
  599. void _destroyAltHandlerList(struct alt_handler_list *list)
  600. {
  601. }
  602. static void call_alt_handlers(struct _Unwind_Context *ctx)
  603. {
  604. // unsupported in sjlj environments
  605. }
  606. #else
  607. #include <libunwind.h>
  608. #include <execinfo.h>
  609. #include <dispatch/dispatch.h>
  610. // Dwarf eh data encodings
  611. #define DW_EH_PE_omit 0xff // no data follows
  612. #define DW_EH_PE_absptr 0x00
  613. #define DW_EH_PE_uleb128 0x01
  614. #define DW_EH_PE_udata2 0x02
  615. #define DW_EH_PE_udata4 0x03
  616. #define DW_EH_PE_udata8 0x04
  617. #define DW_EH_PE_sleb128 0x09
  618. #define DW_EH_PE_sdata2 0x0A
  619. #define DW_EH_PE_sdata4 0x0B
  620. #define DW_EH_PE_sdata8 0x0C
  621. #define DW_EH_PE_pcrel 0x10
  622. #define DW_EH_PE_textrel 0x20
  623. #define DW_EH_PE_datarel 0x30
  624. #define DW_EH_PE_funcrel 0x40
  625. #define DW_EH_PE_aligned 0x50 // fixme
  626. #define DW_EH_PE_indirect 0x80 // gcc extension
  627. /***********************************************************************
  628. * read_uleb
  629. * Read a LEB-encoded unsigned integer from the address stored in *pp.
  630. * Increments *pp past the bytes read.
  631. * Adapted from DWARF Debugging Information Format 1.1, appendix 4
  632. **********************************************************************/
  633. static uintptr_t read_uleb(uintptr_t *pp)
  634. {
  635. uintptr_t result = 0;
  636. uintptr_t shift = 0;
  637. unsigned char byte;
  638. do {
  639. byte = *(const unsigned char *)(*pp)++;
  640. result |= (byte & 0x7f) << shift;
  641. shift += 7;
  642. } while (byte & 0x80);
  643. return result;
  644. }
  645. /***********************************************************************
  646. * read_sleb
  647. * Read a LEB-encoded signed integer from the address stored in *pp.
  648. * Increments *pp past the bytes read.
  649. * Adapted from DWARF Debugging Information Format 1.1, appendix 4
  650. **********************************************************************/
  651. static intptr_t read_sleb(uintptr_t *pp)
  652. {
  653. uintptr_t result = 0;
  654. uintptr_t shift = 0;
  655. unsigned char byte;
  656. do {
  657. byte = *(const unsigned char *)(*pp)++;
  658. result |= (byte & 0x7f) << shift;
  659. shift += 7;
  660. } while (byte & 0x80);
  661. if ((shift < 8*sizeof(intptr_t)) && (byte & 0x40)) {
  662. result |= ((intptr_t)-1) << shift;
  663. }
  664. return result;
  665. }
  666. /***********************************************************************
  667. * read_address
  668. * Reads an encoded address from the address stored in *pp.
  669. * Increments *pp past the bytes read.
  670. * The data is interpreted according to the given dwarf encoding
  671. * and base addresses.
  672. **********************************************************************/
  673. static uintptr_t read_address(uintptr_t *pp,
  674. const struct dwarf_eh_bases *bases,
  675. unsigned char encoding)
  676. {
  677. uintptr_t result = 0;
  678. uintptr_t oldp = *pp;
  679. // fixme need DW_EH_PE_aligned?
  680. #define READ(type) \
  681. result = *(type *)(*pp); \
  682. *pp += sizeof(type);
  683. if (encoding == DW_EH_PE_omit) return 0;
  684. switch (encoding & 0x0f) {
  685. case DW_EH_PE_absptr:
  686. READ(uintptr_t);
  687. break;
  688. case DW_EH_PE_uleb128:
  689. result = read_uleb(pp);
  690. break;
  691. case DW_EH_PE_udata2:
  692. READ(uint16_t);
  693. break;
  694. case DW_EH_PE_udata4:
  695. READ(uint32_t);
  696. break;
  697. #if __LP64__
  698. case DW_EH_PE_udata8:
  699. READ(uint64_t);
  700. break;
  701. #endif
  702. case DW_EH_PE_sleb128:
  703. result = read_sleb(pp);
  704. break;
  705. case DW_EH_PE_sdata2:
  706. READ(int16_t);
  707. break;
  708. case DW_EH_PE_sdata4:
  709. READ(int32_t);
  710. break;
  711. #if __LP64__
  712. case DW_EH_PE_sdata8:
  713. READ(int64_t);
  714. break;
  715. #endif
  716. default:
  717. _objc_inform("unknown DWARF EH encoding 0x%x at %p",
  718. encoding, (void *)*pp);
  719. break;
  720. }
  721. #undef READ
  722. if (result) {
  723. switch (encoding & 0x70) {
  724. case DW_EH_PE_pcrel:
  725. // fixme correct?
  726. result += (uintptr_t)oldp;
  727. break;
  728. case DW_EH_PE_textrel:
  729. result += bases->tbase;
  730. break;
  731. case DW_EH_PE_datarel:
  732. result += bases->dbase;
  733. break;
  734. case DW_EH_PE_funcrel:
  735. result += bases->func;
  736. break;
  737. case DW_EH_PE_aligned:
  738. _objc_inform("unknown DWARF EH encoding 0x%x at %p",
  739. encoding, (void *)*pp);
  740. break;
  741. default:
  742. // no adjustment
  743. break;
  744. }
  745. if (encoding & DW_EH_PE_indirect) {
  746. result = *(uintptr_t *)result;
  747. }
  748. }
  749. return (uintptr_t)result;
  750. }
  751. struct frame_ips {
  752. uintptr_t start;
  753. uintptr_t end;
  754. };
  755. struct frame_range {
  756. uintptr_t ip_start;
  757. uintptr_t ip_end;
  758. uintptr_t cfa;
  759. // precise ranges within ip_start..ip_end; nil or {0,0} terminated
  760. frame_ips *ips;
  761. };
  762. static bool isObjCExceptionCatcher(uintptr_t lsda, uintptr_t ip,
  763. const struct dwarf_eh_bases* bases,
  764. struct frame_range *frame)
  765. {
  766. unsigned char LPStart_enc = *(const unsigned char *)lsda++;
  767. if (LPStart_enc != DW_EH_PE_omit) {
  768. read_address(&lsda, bases, LPStart_enc); // LPStart
  769. }
  770. unsigned char TType_enc = *(const unsigned char *)lsda++;
  771. if (TType_enc != DW_EH_PE_omit) {
  772. read_uleb(&lsda); // TType
  773. }
  774. unsigned char call_site_enc = *(const unsigned char *)lsda++;
  775. uintptr_t length = read_uleb(&lsda);
  776. uintptr_t call_site_table = lsda;
  777. uintptr_t call_site_table_end = call_site_table + length;
  778. uintptr_t action_record_table = call_site_table_end;
  779. uintptr_t action_record = 0;
  780. uintptr_t p = call_site_table;
  781. uintptr_t try_start;
  782. uintptr_t try_end;
  783. uintptr_t try_landing_pad;
  784. while (p < call_site_table_end) {
  785. uintptr_t start = read_address(&p, bases, call_site_enc)+bases->func;
  786. uintptr_t len = read_address(&p, bases, call_site_enc);
  787. uintptr_t pad = read_address(&p, bases, call_site_enc);
  788. uintptr_t action = read_uleb(&p);
  789. if (ip < start) {
  790. // no more source ranges
  791. return false;
  792. }
  793. else if (ip < start + len) {
  794. // found the range
  795. if (!pad) return false; // ...but it has no landing pad
  796. // found the landing pad
  797. action_record = action ? action_record_table + action - 1 : 0;
  798. try_start = start;
  799. try_end = start + len;
  800. try_landing_pad = pad;
  801. break;
  802. }
  803. }
  804. if (!action_record) return false; // no catch handlers
  805. // has handlers, destructors, and/or throws specifications
  806. // Use this frame if it has any handlers
  807. bool has_handler = false;
  808. p = action_record;
  809. intptr_t offset;
  810. do {
  811. intptr_t filter = read_sleb(&p);
  812. uintptr_t temp = p;
  813. offset = read_sleb(&temp);
  814. p += offset;
  815. if (filter < 0) {
  816. // throws specification - ignore
  817. } else if (filter == 0) {
  818. // destructor - ignore
  819. } else /* filter >= 0 */ {
  820. // catch handler - use this frame
  821. has_handler = true;
  822. break;
  823. }
  824. } while (offset);
  825. if (!has_handler) return false;
  826. // Count the number of source ranges with the same landing pad as our match
  827. unsigned int range_count = 0;
  828. p = call_site_table;
  829. while (p < call_site_table_end) {
  830. /*start*/ read_address(&p, bases, call_site_enc)/*+bases->func*/;
  831. /*len*/ read_address(&p, bases, call_site_enc);
  832. uintptr_t pad = read_address(&p, bases, call_site_enc);
  833. /*action*/ read_uleb(&p);
  834. if (pad == try_landing_pad) {
  835. range_count++;
  836. }
  837. }
  838. if (range_count == 1) {
  839. // No other source ranges with the same landing pad. We're done here.
  840. frame->ips = nil;
  841. }
  842. else {
  843. // Record all ranges with the same landing pad as our match.
  844. frame->ips = (frame_ips *)
  845. malloc((range_count + 1) * sizeof(frame->ips[0]));
  846. unsigned int r = 0;
  847. p = call_site_table;
  848. while (p < call_site_table_end) {
  849. uintptr_t start = read_address(&p, bases, call_site_enc)+bases->func;
  850. uintptr_t len = read_address(&p, bases, call_site_enc);
  851. uintptr_t pad = read_address(&p, bases, call_site_enc);
  852. /*action*/ read_uleb(&p);
  853. if (pad == try_landing_pad) {
  854. if (start < try_start) try_start = start;
  855. if (start+len > try_end) try_end = start+len;
  856. frame->ips[r].start = start;
  857. frame->ips[r].end = start+len;
  858. r++;
  859. }
  860. }
  861. frame->ips[r].start = 0;
  862. frame->ips[r].end = 0;
  863. }
  864. frame->ip_start = try_start;
  865. frame->ip_end = try_end;
  866. return true;
  867. }
  868. static struct frame_range findHandler(void)
  869. {
  870. // walk stack looking for frame with objc catch handler
  871. unw_context_t uc;
  872. unw_cursor_t cursor;
  873. unw_proc_info_t info;
  874. unw_getcontext(&uc);
  875. unw_init_local(&cursor, &uc);
  876. while ( (unw_step(&cursor) > 0) && (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS) ) {
  877. // must use objc personality handler
  878. if ( info.handler != (uintptr_t)__objc_personality_v0 )
  879. continue;
  880. // must have landing pad
  881. if ( info.lsda == 0 )
  882. continue;
  883. // must have landing pad that catches objc exceptions
  884. struct dwarf_eh_bases bases;
  885. bases.tbase = 0; // from unwind-dw2-fde-darwin.c:examine_objects()
  886. bases.dbase = 0; // from unwind-dw2-fde-darwin.c:examine_objects()
  887. bases.func = info.start_ip;
  888. unw_word_t ip;
  889. unw_get_reg(&cursor, UNW_REG_IP, &ip);
  890. ip -= 1;
  891. struct frame_range try_range = {0, 0, 0, 0};
  892. if ( isObjCExceptionCatcher(info.lsda, ip, &bases, &try_range) ) {
  893. unw_word_t cfa;
  894. unw_get_reg(&cursor, UNW_REG_SP, &cfa);
  895. try_range.cfa = cfa;
  896. return try_range;
  897. }
  898. }
  899. return (struct frame_range){0, 0, 0, 0};
  900. }
  901. // This data structure assumes the number of
  902. // active alt handlers per frame is small.
  903. // for OBJC_DEBUG_ALT_HANDLERS, record the call to objc_addExceptionHandler.
  904. #define BACKTRACE_COUNT 46
  905. #define THREADNAME_COUNT 64
  906. struct alt_handler_debug {
  907. uintptr_t token;
  908. int backtraceSize;
  909. void *backtrace[BACKTRACE_COUNT];
  910. char thread[THREADNAME_COUNT];
  911. char queue[THREADNAME_COUNT];
  912. };
  913. struct alt_handler_data {
  914. struct frame_range frame;
  915. objc_exception_handler fn;
  916. void *context;
  917. struct alt_handler_debug *debug;
  918. };
  919. struct alt_handler_list {
  920. unsigned int allocated;
  921. unsigned int used;
  922. struct alt_handler_data *handlers;
  923. struct alt_handler_list *next_DEBUGONLY;
  924. };
  925. static struct alt_handler_list *DebugLists;
  926. static uintptr_t DebugCounter;
  927. __attribute__((noinline, noreturn))
  928. void alt_handler_error(uintptr_t token);
  929. static struct alt_handler_list *
  930. fetch_handler_list(bool create)
  931. {
  932. _objc_pthread_data *data = _objc_fetch_pthread_data(create);
  933. if (!data) return nil;
  934. struct alt_handler_list *list = data->handlerList;
  935. if (!list) {
  936. if (!create) return nil;
  937. list = (struct alt_handler_list *)calloc(1, sizeof(*list));
  938. data->handlerList = list;
  939. if (DebugAltHandlers) {
  940. // Save this list so the debug code can find it from other threads
  941. mutex_locker_t lock(AltHandlerDebugLock);
  942. list->next_DEBUGONLY = DebugLists;
  943. DebugLists = list;
  944. }
  945. }
  946. return list;
  947. }
  948. void _destroyAltHandlerList(struct alt_handler_list *list)
  949. {
  950. if (list) {
  951. if (DebugAltHandlers) {
  952. // Detach from the list-of-lists.
  953. mutex_locker_t lock(AltHandlerDebugLock);
  954. struct alt_handler_list **listp = &DebugLists;
  955. while (*listp && *listp != list) listp = &(*listp)->next_DEBUGONLY;
  956. if (*listp) *listp = (*listp)->next_DEBUGONLY;
  957. }
  958. if (list->handlers) {
  959. for (unsigned int i = 0; i < list->allocated; i++) {
  960. if (list->handlers[i].frame.ips) {
  961. free(list->handlers[i].frame.ips);
  962. }
  963. }
  964. free(list->handlers);
  965. }
  966. free(list);
  967. }
  968. }
  969. uintptr_t objc_addExceptionHandler(objc_exception_handler fn, void *context)
  970. {
  971. // Find the closest enclosing frame with objc catch handlers
  972. struct frame_range target_frame = findHandler();
  973. if (!target_frame.ip_start) {
  974. // No suitable enclosing handler found.
  975. return 0;
  976. }
  977. // Record this alt handler for the discovered frame.
  978. struct alt_handler_list *list = fetch_handler_list(YES);
  979. unsigned int i = 0;
  980. if (list->used == list->allocated) {
  981. list->allocated = list->allocated*2 ?: 4;
  982. list->handlers = (struct alt_handler_data *)
  983. realloc(list->handlers,
  984. list->allocated * sizeof(list->handlers[0]));
  985. bzero(&list->handlers[list->used], (list->allocated - list->used) * sizeof(list->handlers[0]));
  986. i = list->used;
  987. }
  988. else {
  989. for (i = 0; i < list->allocated; i++) {
  990. if (list->handlers[i].frame.ip_start == 0 &&
  991. list->handlers[i].frame.ip_end == 0 &&
  992. list->handlers[i].frame.cfa == 0)
  993. {
  994. break;
  995. }
  996. }
  997. if (i == list->allocated) {
  998. _objc_fatal("alt handlers in objc runtime are buggy!");
  999. }
  1000. }
  1001. struct alt_handler_data *data = &list->handlers[i];
  1002. data->frame = target_frame;
  1003. data->fn = fn;
  1004. data->context = context;
  1005. list->used++;
  1006. uintptr_t token = i+1;
  1007. if (DebugAltHandlers) {
  1008. // Record backtrace in case this handler is misused later.
  1009. mutex_locker_t lock(AltHandlerDebugLock);
  1010. token = DebugCounter++;
  1011. if (token == 0) token = DebugCounter++;
  1012. if (!data->debug) {
  1013. data->debug = (struct alt_handler_debug *)
  1014. calloc(sizeof(*data->debug), 1);
  1015. } else {
  1016. bzero(data->debug, sizeof(*data->debug));
  1017. }
  1018. pthread_getname_np(objc_thread_self(), data->debug->thread, THREADNAME_COUNT);
  1019. strlcpy(data->debug->queue,
  1020. dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL),
  1021. THREADNAME_COUNT);
  1022. data->debug->backtraceSize =
  1023. backtrace(data->debug->backtrace, BACKTRACE_COUNT);
  1024. data->debug->token = token;
  1025. }
  1026. if (PrintAltHandlers) {
  1027. _objc_inform("ALT HANDLERS: installing alt handler #%lu %p(%p) on "
  1028. "frame [ip=%p..%p sp=%p]", (unsigned long)token,
  1029. data->fn, data->context, (void *)data->frame.ip_start,
  1030. (void *)data->frame.ip_end, (void *)data->frame.cfa);
  1031. if (data->frame.ips) {
  1032. unsigned int r = 0;
  1033. while (1) {
  1034. uintptr_t start = data->frame.ips[r].start;
  1035. uintptr_t end = data->frame.ips[r].end;
  1036. r++;
  1037. if (start == 0 && end == 0) break;
  1038. _objc_inform("ALT HANDLERS: ip=%p..%p",
  1039. (void*)start, (void*)end);
  1040. }
  1041. }
  1042. }
  1043. if (list->used > 1000) {
  1044. static int warned = 0;
  1045. if (!warned) {
  1046. _objc_inform("ALT HANDLERS: *** over 1000 alt handlers installed; "
  1047. "this is probably a bug");
  1048. warned = 1;
  1049. }
  1050. }
  1051. return token;
  1052. }
  1053. void objc_removeExceptionHandler(uintptr_t token)
  1054. {
  1055. if (!token) {
  1056. // objc_addExceptionHandler failed
  1057. return;
  1058. }
  1059. struct alt_handler_list *list = fetch_handler_list(NO);
  1060. if (!list || !list->handlers) {
  1061. // no alt handlers active
  1062. alt_handler_error(token);
  1063. }
  1064. uintptr_t i = token-1;
  1065. if (DebugAltHandlers) {
  1066. // search for the token instead of using token-1
  1067. for (i = 0; i < list->allocated; i++) {
  1068. struct alt_handler_data *data = &list->handlers[i];
  1069. if (data->debug && data->debug->token == token) break;
  1070. }
  1071. }
  1072. if (i >= list->allocated) {
  1073. // token out of range
  1074. alt_handler_error(token);
  1075. }
  1076. struct alt_handler_data *data = &list->handlers[i];
  1077. if (data->frame.ip_start == 0 && data->frame.ip_end == 0 && data->frame.cfa == 0) {
  1078. // token in range, but invalid
  1079. alt_handler_error(token);
  1080. }
  1081. if (PrintAltHandlers) {
  1082. _objc_inform("ALT HANDLERS: removing alt handler #%lu %p(%p) on "
  1083. "frame [ip=%p..%p sp=%p]", (unsigned long)token,
  1084. data->fn, data->context, (void *)data->frame.ip_start,
  1085. (void *)data->frame.ip_end, (void *)data->frame.cfa);
  1086. }
  1087. if (data->debug) free(data->debug);
  1088. if (data->frame.ips) free(data->frame.ips);
  1089. bzero(data, sizeof(*data));
  1090. list->used--;
  1091. }
  1092. BREAKPOINT_FUNCTION(
  1093. void objc_alt_handler_error(void));
  1094. __attribute__((noinline, noreturn))
  1095. void alt_handler_error(uintptr_t token)
  1096. {
  1097. _objc_inform
  1098. ("objc_removeExceptionHandler() called with unknown alt handler; "
  1099. "this is probably a bug in multithreaded AppKit use. "
  1100. "Set environment variable OBJC_DEBUG_ALT_HANDLERS=YES "
  1101. "or break in objc_alt_handler_error() to debug.");
  1102. if (DebugAltHandlers) {
  1103. AltHandlerDebugLock.lock();
  1104. // Search other threads' alt handler lists for this handler.
  1105. struct alt_handler_list *list;
  1106. for (list = DebugLists; list; list = list->next_DEBUGONLY) {
  1107. unsigned h;
  1108. for (h = 0; h < list->allocated; h++) {
  1109. struct alt_handler_data *data = &list->handlers[h];
  1110. if (data->debug && data->debug->token == token) {
  1111. // found it
  1112. int i;
  1113. // Build a string from the recorded backtrace
  1114. char *symbolString;
  1115. char **symbols =
  1116. backtrace_symbols(data->debug->backtrace,
  1117. data->debug->backtraceSize);
  1118. size_t len = 1;
  1119. for (i = 0; i < data->debug->backtraceSize; i++){
  1120. len += 4 + strlen(symbols[i]) + 1;
  1121. }
  1122. symbolString = (char *)calloc(len, 1);
  1123. for (i = 0; i < data->debug->backtraceSize; i++){
  1124. strcat(symbolString, " ");
  1125. strcat(symbolString, symbols[i]);
  1126. strcat(symbolString, "\n");
  1127. }
  1128. free(symbols);
  1129. _objc_inform_now_and_on_crash
  1130. ("The matching objc_addExceptionHandler() was called "
  1131. "by:\nThread '%s': Dispatch queue: '%s': \n%s",
  1132. data->debug->thread, data->debug->queue, symbolString);
  1133. goto done;
  1134. }
  1135. }
  1136. }
  1137. done:
  1138. AltHandlerDebugLock.unlock();
  1139. }
  1140. objc_alt_handler_error();
  1141. _objc_fatal
  1142. ("objc_removeExceptionHandler() called with unknown alt handler; "
  1143. "this is probably a bug in multithreaded AppKit use. ");
  1144. }
  1145. // called in order registered, to match 32-bit _NSAddAltHandler2
  1146. // fixme reverse registration order matches c++ destructors better
  1147. static void call_alt_handlers(struct _Unwind_Context *ctx)
  1148. {
  1149. uintptr_t ip = _Unwind_GetIP(ctx) - 1;
  1150. uintptr_t cfa = _Unwind_GetCFA(ctx);
  1151. unsigned int i;
  1152. struct alt_handler_list *list = fetch_handler_list(NO);
  1153. if (!list || list->used == 0) return;
  1154. for (i = 0; i < list->allocated; i++) {
  1155. struct alt_handler_data *data = &list->handlers[i];
  1156. if (ip >= data->frame.ip_start && ip < data->frame.ip_end && data->frame.cfa == cfa)
  1157. {
  1158. if (data->frame.ips) {
  1159. unsigned int r = 0;
  1160. bool found;
  1161. while (1) {
  1162. uintptr_t start = data->frame.ips[r].start;
  1163. uintptr_t end = data->frame.ips[r].end;
  1164. r++;
  1165. if (start == 0 && end == 0) {
  1166. found = false;
  1167. break;
  1168. }
  1169. if (ip >= start && ip < end) {
  1170. found = true;
  1171. break;
  1172. }
  1173. }
  1174. if (!found) continue;
  1175. }
  1176. // Copy and clear before the callback, in case the
  1177. // callback manipulates the alt handler list.
  1178. struct alt_handler_data copy = *data;
  1179. bzero(data, sizeof(*data));
  1180. list->used--;
  1181. if (PrintExceptions || PrintAltHandlers) {
  1182. _objc_inform("EXCEPTIONS: calling alt handler %p(%p) from "
  1183. "frame [ip=%p..%p sp=%p]", copy.fn, copy.context,
  1184. (void *)copy.frame.ip_start,
  1185. (void *)copy.frame.ip_end,
  1186. (void *)copy.frame.cfa);
  1187. }
  1188. if (copy.fn) (*copy.fn)(nil, copy.context);
  1189. if (copy.frame.ips) free(copy.frame.ips);
  1190. }
  1191. }
  1192. }
  1193. // SUPPORT_ALT_HANDLERS
  1194. #endif
  1195. /***********************************************************************
  1196. * exception_init
  1197. * Initialize libobjc's exception handling system.
  1198. * Called by map_images().
  1199. **********************************************************************/
  1200. void exception_init(void)
  1201. {
  1202. old_terminate = std::set_terminate(&_objc_terminate);
  1203. }
  1204. // __OBJC2__
  1205. #endif
  1206. // Define this everywhere even if it isn't used, to simplify fork() safety code
  1207. mutex_t AltHandlerDebugLock;