Overview
Comment: | Add exception handling for ARM. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e47640dd96964f19b34b3f9d64747db4 |
User & Date: | js on 2012-07-19 01:45:25 |
Other Links: | manifest | tags |
Context
2012-07-19
| ||
01:56 | Only use rev(16) when __ARM_ARCH_6__ is defined. check-in: db8a3bb7ac user: js tags: trunk | |
01:45 | Add exception handling for ARM. check-in: e47640dd96 user: js tags: trunk | |
2012-07-18
| ||
23:55 | Add PPC/ELF assembly lookup implementation. check-in: 301fee913d user: js tags: trunk | |
Changes
Modified src/runtime/exception.m from [93064c290f] to [cd4964c00b].
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #include <stdlib.h> #import "runtime.h" static const uint64_t objc_exception_class = 0x474E55434F424A43; /* GNUCOBJC */ #define _UA_SEARCH_PHASE 0x01 #define _UA_CLEANUP_PHASE 0x02 | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #include <stdlib.h> #include <string.h> #import "runtime.h" static const uint64_t objc_exception_class = 0x474E55434F424A43; /* GNUCOBJC */ #define _UA_SEARCH_PHASE 0x01 #define _UA_CLEANUP_PHASE 0x02 |
︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 | #define CLEANUP_FOUND 0x01 #define HANDLER_FOUND 0x02 struct _Unwind_Context; typedef enum { _URC_FATAL_PHASE1_ERROR = 3, _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | #define CLEANUP_FOUND 0x01 #define HANDLER_FOUND 0x02 struct _Unwind_Context; typedef enum { _URC_OK = 0, _URC_FATAL_PHASE1_ERROR = 3, _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8, _URC_FAILURE = 9 } _Unwind_Reason_Code; struct objc_exception { struct _Unwind_Exception { uint64_t class; void (*cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception*); #if defined(__arm__) || defined(__ARM__) /* From "Exception Handling ABI for the ARM(R) Architecture" */ struct { uint32_t reserved1, reserved2, reserved3, reserved4; uint32_t reserved; } unwinder_cache; struct { uint32_t sp; uint32_t bitpattern[5]; } barrier_cache; struct { uint32_t bitpattern[4]; } cleanup_cache; struct { uint32_t fnstart; uint32_t *ehtp; uint32_t additional; uint32_t reserved1; } pr_cache; long long int : 0; #else /* * The Itanium Exception ABI says to have those and never touch * them. */ uintptr_t private1, private2; #endif } exception; id object; #if !defined(__arm__) && !defined(__ARM__) uintptr_t landingpad; intptr_t filter; #endif }; struct lsda { uintptr_t region_start, landingpads_start; uint8_t typestable_enc; const uint8_t *typestable; uintptr_t typestable_base; uint8_t callsites_enc; const uint8_t *callsites, *actiontable; }; extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception*); extern void* _Unwind_GetLanguageSpecificData(struct _Unwind_Context*); extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context*); extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context*); extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context*); #if defined(__arm__) || defined(__ARM__) extern _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*, struct _Unwind_Context*); extern int _Unwind_VRS_Get(struct _Unwind_Context*, int, uint32_t, int, void*); extern int _Unwind_VRS_Set(struct _Unwind_Context*, int, uint32_t, int, void*); # define CONTINUE_UNWIND \ { \ if (__gnu_unwind_frame(ex, ctx) != _URC_OK) \ return _URC_FAILURE; \ \ return _URC_CONTINUE_UNWIND; \ } static inline uintptr_t _Unwind_GetGR(struct _Unwind_Context *ctx, int regno) { uintptr_t value; _Unwind_VRS_Get(ctx, 0, regno, 0, &value); return value; } static inline uintptr_t _Unwind_GetIP(struct _Unwind_Context *ctx) { return _Unwind_GetGR(ctx, 15) & ~1; } static inline void _Unwind_SetGR(struct _Unwind_Context *ctx, int regno, uintptr_t value) { _Unwind_VRS_Set(ctx, 0, regno, 0, &value); } static inline void _Unwind_SetIP(struct _Unwind_Context *ctx, uintptr_t value) { uintptr_t thumb = _Unwind_GetGR(ctx, 15) & 1; _Unwind_SetGR(ctx, 15, (value | thumb)); } #else # define CONTINUE_UNWIND return _URC_CONTINUE_UNWIND extern uintptr_t _Unwind_GetIP(struct _Unwind_Context*); extern void _Unwind_SetIP(struct _Unwind_Context*, uintptr_t); extern void _Unwind_SetGR(struct _Unwind_Context*, int, uintptr_t); #endif static objc_uncaught_exception_handler uncaught_exception_handler; static uint64_t read_uleb128(const uint8_t **ptr) { uint64_t value = 0; |
︙ | ︙ | |||
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | } #undef READ_TYPE return value; } static uint64_t resolve_value(uint64_t value, uint8_t enc, const uint8_t *start, uint64_t base) { if (value == 0) return 0; value += ((enc & 0x70) == DW_EH_PE_pcrel ? (uintptr_t)start : base); if (enc & DW_EH_PE_indirect) value = *(uint64_t*)(uintptr_t)value; return value; } static void read_lsda(struct _Unwind_Context *ctx, const uint8_t *ptr, struct lsda *lsda) { uint8_t landingpads_start_enc; uintptr_t callsites_size; | > > | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | } #undef READ_TYPE return value; } #if !defined(__arm__) && !defined(__ARM__) static uint64_t resolve_value(uint64_t value, uint8_t enc, const uint8_t *start, uint64_t base) { if (value == 0) return 0; value += ((enc & 0x70) == DW_EH_PE_pcrel ? (uintptr_t)start : base); if (enc & DW_EH_PE_indirect) value = *(uint64_t*)(uintptr_t)value; return value; } #endif static void read_lsda(struct _Unwind_Context *ctx, const uint8_t *ptr, struct lsda *lsda) { uint8_t landingpads_start_enc; uintptr_t callsites_size; |
︙ | ︙ | |||
339 340 341 342 343 344 345 | */ actionrecords = ptr; displacement = (intptr_t)read_sleb128(&ptr); actionrecords += displacement; if (filter > 0 && !(actions & _UA_FORCE_UNWIND) && !foreign) { Class class; | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | */ actionrecords = ptr; displacement = (intptr_t)read_sleb128(&ptr); actionrecords += displacement; if (filter > 0 && !(actions & _UA_FORCE_UNWIND) && !foreign) { Class class; uintptr_t c; const uint8_t *tmp; #if defined(__arm__) || defined(__ARM__) tmp = lsda->typestable - (filter * 4); c = *(uintptr_t*)tmp; if (c != 0) { c += (uintptr_t)tmp; c = *(uintptr_t*)c; } #else uintptr_t i; i = filter * size_for_encoding(lsda->typestable_enc); tmp = lsda->typestable - i; c = (uintptr_t)read_value(lsda->typestable_enc, &tmp); c = (uintptr_t)resolve_value(c, lsda->typestable_enc, lsda->typestable - i, lsda->typestable_base); #endif class = (c != 0 ? objc_get_class((const char*)c) : Nil); if (class_matches(class, e->object)) { *filtervalue = filter; return (found | HANDLER_FOUND); } } else if (filter == 0) found |= CLEANUP_FOUND; else abort(); } while (displacement != 0); return found; } #if defined(__arm__) || defined(__ARM__) _Unwind_Reason_Code __gnu_objc_personality_v0(uint32_t state, struct _Unwind_Exception *ex, struct _Unwind_Context *ctx) { int version = 1; uint64_t ex_class = ex->class; int actions; switch (state) { case 0: /* _US_VIRTUAL_UNWIND_FRAME */ actions = _UA_SEARCH_PHASE; break; case 1: /* _US_UNWIND_FRAME_STARTING */ actions = _UA_CLEANUP_PHASE; if ((ex->barrier_cache.sp == _Unwind_GetGR(ctx, 13)) != 0) actions |= _UA_HANDLER_FRAME; break; case 2: /* _US_UNWIND_FRAME_RESUME */ CONTINUE_UNWIND; default: return _URC_FAILURE; } _Unwind_SetGR(ctx, 12, (uintptr_t)ex); #else _Unwind_Reason_Code __gnu_objc_personality_v0(int version, int actions, uint64_t ex_class, struct _Unwind_Exception *ex, struct _Unwind_Context *ctx) { #endif struct objc_exception *e = (struct objc_exception*)ex; BOOL foreign = (ex_class != objc_exception_class); const uint8_t *lsda_addr, *actionrecords; struct lsda lsda; uintptr_t landingpad = 0; uint8_t found = 0; intptr_t filter = 0; |
︙ | ︙ | |||
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | if (actions & _UA_HANDLER_FRAME && !foreign) { /* * For handlers, reg #0 must be the exception's object and reg * #1 the filter. */ _Unwind_SetGR(ctx, __builtin_eh_return_data_regno(0), (uintptr_t)e->object); _Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1), e->filter); _Unwind_SetIP(ctx, e->landingpad); free(ex); return _URC_INSTALL_CONTEXT; } /* No LSDA -> nothing to handle */ if ((lsda_addr = _Unwind_GetLanguageSpecificData(ctx)) == NULL) | > > > > > > | | | | > > > > > > | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 | if (actions & _UA_HANDLER_FRAME && !foreign) { /* * For handlers, reg #0 must be the exception's object and reg * #1 the filter. */ _Unwind_SetGR(ctx, __builtin_eh_return_data_regno(0), (uintptr_t)e->object); #if defined(__arm__) || defined(__ARM__) _Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1), ex->barrier_cache.bitpattern[1]); _Unwind_SetIP(ctx, ex->barrier_cache.bitpattern[3]); #else _Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1), e->filter); _Unwind_SetIP(ctx, e->landingpad); #endif free(ex); return _URC_INSTALL_CONTEXT; } /* No LSDA -> nothing to handle */ if ((lsda_addr = _Unwind_GetLanguageSpecificData(ctx)) == NULL) CONTINUE_UNWIND; read_lsda(ctx, lsda_addr, &lsda); if (!find_callsite(ctx, &lsda, &landingpad, &actionrecords)) CONTINUE_UNWIND; if (landingpad != 0 && actionrecords == NULL) found = CLEANUP_FOUND; else if (landingpad != 0) found = find_actionrecord(actionrecords, &lsda, actions, foreign, e, &filter); if (!found) CONTINUE_UNWIND; if (actions & _UA_SEARCH_PHASE) { if (!(found & HANDLER_FOUND)) CONTINUE_UNWIND; /* Cache it so we don't have to search it again in phase 2 */ if (!foreign) { #if defined(__arm__) || defined(__ARM__) ex->barrier_cache.sp = _Unwind_GetGR(ctx, 13); ex->barrier_cache.bitpattern[1] = filter; ex->barrier_cache.bitpattern[3] = landingpad; #else e->landingpad = landingpad; e->filter = filter; #endif } return _URC_HANDLER_FOUND; } else if (actions & _UA_CLEANUP_PHASE) { /* For cleanup, reg #0 must be the exception and reg #1 zero */ _Unwind_SetGR(ctx, __builtin_eh_return_data_regno(0), (uintptr_t)e); |
︙ | ︙ | |||
457 458 459 460 461 462 463 464 465 | objc_exception_throw(id object) { struct objc_exception *e; if ((e = malloc(sizeof(*e))) == NULL) abort(); e->exception.class = objc_exception_class; e->exception.cleanup = cleanup; | > < | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | objc_exception_throw(id object) { struct objc_exception *e; if ((e = malloc(sizeof(*e))) == NULL) abort(); memset(e, 0, sizeof(*e)); e->exception.class = objc_exception_class; e->exception.cleanup = cleanup; e->object = object; if (_Unwind_RaiseException(&e->exception) == _URC_END_OF_STACK && uncaught_exception_handler != NULL) uncaught_exception_handler(object); abort(); |
︙ | ︙ |