00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 #include "comma/runtime/commart.h"
00013 
00014 #include <assert.h>
00015 #include <stddef.h>
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 
00020 #define __STDC_FORMAT_MACROS
00021 #include <inttypes.h>
00022 
00023 
00024 
00025 
00026 
00027 struct _Unwind_Exception;
00028 struct _Unwind_Context;
00029 
00030 
00031 
00032 
00033 typedef enum {
00034     _URC_NO_REASON = 0,
00035     _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
00036     _URC_FATAL_PHASE2_ERROR = 2,
00037     _URC_FATAL_PHASE1_ERROR = 3,
00038     _URC_NORMAL_STOP = 4,
00039     _URC_END_OF_STACK = 5,
00040     _URC_HANDLER_FOUND = 6,
00041     _URC_INSTALL_CONTEXT = 7,
00042     _URC_CONTINUE_UNWIND = 8
00043 } _Unwind_Reason_Code;
00044 
00045 
00046 
00047 
00048 
00049 typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code reason,
00050                                               struct _Unwind_Exception *exc);
00051 
00052 
00053 
00054 
00055 extern _Unwind_Reason_Code
00056 _Unwind_RaiseException(struct _Unwind_Exception *exception_object);
00057 
00058 
00059 
00060 
00061 
00062 extern void _Unwind_Resume(struct _Unwind_Exception *exception_object);
00063 
00064 
00065 
00066 
00067 extern uintptr_t
00068 _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
00069 
00070 
00071 
00072 
00073 extern uintptr_t
00074 _Unwind_GetRegionStart(struct _Unwind_Context *context);
00075 
00076 
00077 
00078 
00079 
00080 extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
00081 
00082 
00083 
00084 
00085 extern void _Unwind_SetGR(struct _Unwind_Context *context,
00086                           int reg, uintptr_t value);
00087 
00088 
00089 
00090 
00091 extern void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t IP);
00092 
00093 
00094 
00095 
00096 struct _Unwind_Exception {
00097     uint64_t                     exception_class;
00098     _Unwind_Exception_Cleanup_Fn exception_cleanup;
00099     uint64_t                     private_1;
00100     uint64_t                     private_2;
00101 };
00102 
00103 
00104 
00105 
00106 typedef int _Unwind_Action;
00107 static const _Unwind_Action _UA_SEARCH_PHASE  = 1;
00108 static const _Unwind_Action _UA_CLEANUP_PHASE = 2;
00109 static const _Unwind_Action _UA_HANDLER_FRAME = 4;
00110 static const _Unwind_Action _UA_FORCE_UNWIND  = 8;
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 typedef enum {
00128     DW_EH_PE_omit    = 0xFF, 
00129     DW_EH_PE_uleb128 = 0x01, 
00130     DW_EH_PE_udata2  = 0x02, 
00131     DW_EH_PE_udata4  = 0x03, 
00132     DW_EH_PE_udata8  = 0x04, 
00133     DW_EH_PE_sleb128 = 0x09, 
00134     DW_EH_PE_sdata2  = 0x0A, 
00135     DW_EH_PE_sdata4  = 0x0B, 
00136     DW_EH_PE_sdata8  = 0x0C, 
00137 } Dwarf_Encoding;
00138 
00139 typedef enum {
00140     DW_EH_PE_absptr  = 0x00, 
00141     DW_EH_PE_pcrel   = 0x10, 
00142     DW_EH_PE_datarel = 0x30, 
00143 } Dwarf_Application;
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 static unsigned char *parse_uleb128(unsigned char *start, uint64_t *value)
00160 {
00161     uint64_t res = 0;
00162     unsigned bits = 0;
00163 
00164     
00165 
00166 
00167 
00168     while (*start & 0x80) {
00169         res |= (((uint64_t)*start) & 0x7F) << bits;
00170         bits += 7;
00171         ++start;
00172     }
00173 
00174     
00175 
00176 
00177     res |= (((uint64_t)*start) & 0x7F) << bits;
00178 
00179     *value = res;
00180     return ++start;
00181 }
00182 
00183 static unsigned char *parse_sleb128(unsigned char *start, int64_t *value)
00184 {
00185     uint64_t res = 0;
00186     unsigned bits = 0;
00187 
00188     
00189 
00190 
00191 
00192     while (*start & 0x80) {
00193         res |= (((uint64_t)*start) & 0x7F) << bits;
00194         bits += 7;
00195         ++start;
00196     }
00197 
00198     
00199 
00200 
00201     res |= (((uint64_t)*start) & 0x7F) << bits;
00202 
00203     if (*start & 0x40) {
00204         bits += 7;
00205         res |= ~((uint64_t)0) << bits;
00206     }
00207 
00208     *value = (int64_t)res;
00209     return ++start;
00210 }
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 static unsigned char *
00227 parse_dwarf_value(Dwarf_Encoding ID, unsigned char *start, uint64_t *value)
00228 {
00229     switch (ID) {
00230 
00231     default:
00232         assert(0 && "Invalid DWARF encoding!");
00233         return start;
00234 
00235     case DW_EH_PE_omit:
00236         return start;
00237 
00238     case DW_EH_PE_uleb128:
00239         return parse_uleb128(start, value);
00240 
00241     case DW_EH_PE_udata2: {
00242         uint8_t dst;
00243         memcpy(&dst, start, 2);
00244         *value = (uint64_t)dst;
00245         return start + 2;
00246     }
00247 
00248     case DW_EH_PE_udata4: {
00249         uint16_t dst;
00250         memcpy(&dst, start, 4);
00251         *value = (uint64_t)dst;
00252         return start + 4;
00253     }
00254 
00255     case DW_EH_PE_udata8:
00256         memcpy(value, start, 8);
00257         return start + 8;
00258 
00259     case DW_EH_PE_sleb128:
00260         return parse_sleb128(start, (int64_t*)value);
00261 
00262     case DW_EH_PE_sdata2: {
00263         int8_t dst;
00264         memcpy(&dst, start, 2);
00265         *value = (int64_t)dst;
00266         return start + 2;
00267     }
00268 
00269     case DW_EH_PE_sdata4: {
00270         int16_t dst;
00271         memcpy(&dst, start, 4);
00272         *value = (int64_t)dst;
00273         return start + 4;
00274     }
00275 
00276     case DW_EH_PE_sdata8:
00277         memcpy(value, start, 8);
00278         return start + 8;
00279     }
00280 }
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 struct LSDA_Header;
00406 struct Call_Site;
00407 struct Action_Record;
00408 
00409 
00410 
00411 
00412 struct LSDA_Header {
00413     
00414 
00415 
00416     unsigned char *lsda_start;
00417 
00418     
00419 
00420 
00421     intptr_t lpstart;
00422 
00423     
00424 
00425 
00426     unsigned char type_table_format;
00427 
00428     
00429 
00430 
00431     unsigned char *type_table;
00432 
00433     
00434 
00435 
00436     Dwarf_Encoding call_site_format;
00437 
00438     
00439 
00440 
00441     uint64_t call_table_size;
00442 
00443     
00444 
00445 
00446     unsigned char *call_sites;
00447 
00448     
00449 
00450 
00451     unsigned char *actions;
00452 };
00453 
00454 
00455 
00456 
00457 struct Call_Site {
00458     
00459 
00460 
00461     int64_t region_start;
00462 
00463     
00464 
00465 
00466     uint64_t region_length;
00467 
00468     
00469 
00470 
00471     int64_t landing_pad;
00472 
00473     
00474 
00475 
00476     uint64_t action_index;
00477 };
00478 
00479 
00480 
00481 
00482 struct Action_Record {
00483     
00484 
00485 
00486     uint64_t info_index;
00487 
00488     
00489 
00490 
00491     uint64_t next_action;
00492 };
00493 
00494 
00495 
00496 
00497 
00498 
00499 
00500 
00501 static void fatal_error(const char *message)
00502 {
00503     fprintf(stderr, "EXCEPTION ERROR : %s\n", message);
00504     abort();
00505 }
00506 
00507 
00508 
00509 
00510 
00511 
00512 typedef enum {
00513     COMMA_DYN_MESSAGE = 1 << 0
00514 } comma_exception_flag;
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 struct comma_exception {
00524     comma_exinfo_t id;
00525     const char *file_name;
00526     uint32_t line_number;
00527     char *message;
00528     uint32_t flags;
00529     struct _Unwind_Exception header;
00530 };
00531 
00532 
00533 
00534 
00535 struct comma_exception *
00536 to_comma_exception(struct _Unwind_Exception *header)
00537 {
00538     char *ptr = (char *)header;
00539     ptr -= offsetof(struct comma_exception, header);
00540     return (struct comma_exception *)ptr;
00541 }
00542 
00543 struct _Unwind_Exception *
00544 to_Unwind_Exception(struct comma_exception *exception)
00545 {
00546     return &exception->header;
00547 }
00548 
00549 
00550 
00551 
00552 
00553 static int parse_LSDA(struct _Unwind_Context *context, struct LSDA_Header *lsda)
00554 {
00555     unsigned char *ptr;
00556     uint64_t tmp;
00557 
00558     lsda->lsda_start =
00559         (unsigned char *)_Unwind_GetLanguageSpecificData(context);
00560 
00561     if (!lsda->lsda_start)
00562         return 1;
00563     else
00564         ptr = lsda->lsda_start;
00565 
00566     
00567 
00568 
00569 
00570 
00571 
00572 
00573     if (*ptr == DW_EH_PE_omit) {
00574         lsda->lpstart = _Unwind_GetRegionStart(context);
00575         ++ptr;
00576     }
00577     else
00578         fatal_error("Unexpected DWARF value for @LPStart!");
00579 
00580     
00581 
00582 
00583 
00584 
00585     lsda->type_table_format = *ptr;
00586     ++ptr;
00587     if (lsda->type_table_format != DW_EH_PE_absptr)
00588         fatal_error("Unexpected type table format!");
00589 
00590     
00591 
00592 
00593     ptr = parse_uleb128(ptr, &tmp);
00594     lsda->type_table = ptr + tmp;
00595 
00596     
00597 
00598 
00599 
00600     lsda->call_site_format = *ptr;
00601     ++ptr;
00602 
00603     
00604 
00605 
00606     ptr = parse_uleb128(ptr, &lsda->call_table_size);
00607 
00608     
00609 
00610 
00611     lsda->call_sites = ptr;
00612 
00613     
00614 
00615 
00616     lsda->actions = lsda->call_sites + lsda->call_table_size;
00617 
00618     return 0;
00619 }
00620 
00621 
00622 
00623 
00624 
00625 static void dump_LSDA(struct LSDA_Header *lsda)
00626 {
00627 #ifdef COMMA_EH_DEBUG
00628     fputs("LSDA_Header  :\n", stderr);
00629     fprintf(stderr, " lsda_start  : %" PRIXPTR "\n",
00630             (uintptr_t)lsda->lsda_start);
00631     fprintf(stderr, " lpstart     : %" PRIXPTR "\n",
00632             lsda->lpstart);
00633     fprintf(stderr, " tt format   : %u\n",
00634             (unsigned)lsda->type_table_format);
00635     fprintf(stderr, " type_table  : %" PRIXPTR "\n",
00636             (uintptr_t)lsda->type_table);
00637     fprintf(stderr, " call format : %u\n",
00638             (unsigned)lsda->call_site_format);
00639     fprintf(stderr, " call size   : %" PRIu64 "\n",
00640             lsda->call_table_size);
00641     fprintf(stderr, " call sites  : %" PRIXPTR "\n",
00642             (uintptr_t)lsda->call_sites);
00643     fprintf(stderr, " actions     : %" PRIXPTR "\n",
00644             (uintptr_t)lsda->actions);
00645 #endif
00646 }
00647 
00648 
00649 
00650 
00651 
00652 
00653 static unsigned char *
00654 parse_Call_Site(struct LSDA_Header *lsda,
00655                 unsigned char *ptr, struct Call_Site *dst)
00656 {
00657     
00658 
00659 
00660 
00661     if (ptr >= (lsda->call_sites + lsda->call_table_size))
00662         return 0;
00663 
00664     
00665 
00666 
00667 
00668     ptr = parse_dwarf_value(lsda->call_site_format,
00669                             ptr, (uint64_t*)&dst->region_start);
00670     ptr = parse_dwarf_value(lsda->call_site_format,
00671                             ptr, &dst->region_length);
00672     ptr = parse_dwarf_value(lsda->call_site_format,
00673                             ptr, (uint64_t*)&dst->landing_pad);
00674 
00675     
00676 
00677 
00678     ptr = parse_uleb128(ptr, &dst->action_index);
00679     return ptr;
00680 }
00681 
00682 
00683 
00684 
00685 
00686 static void dump_Call_Site(struct Call_Site *site)
00687 {
00688 #ifdef COMMA_EH_DEBUG
00689     fputs("Call_Site      :\n", stderr);
00690     fprintf(stderr, " region_start  : %" PRIx64 "\n", site->region_start);
00691     fprintf(stderr, " region_length : %" PRIu64 "\n", site->region_length);
00692     fprintf(stderr, " landing_pad   : %" PRIx64 "\n", site->landing_pad);
00693     fprintf(stderr, " action_index  : %" PRIu64 "\n", site->action_index);
00694 #endif
00695 }
00696 
00697 
00698 
00699 
00700 
00701 static unsigned char *
00702 parse_Action_Record(unsigned char *ptr, struct Action_Record *dst)
00703 {
00704     unsigned char *start;
00705 
00706     
00707 
00708 
00709 
00710     ptr = parse_sleb128(ptr, (int64_t*)&dst->info_index);
00711 
00712     
00713 
00714 
00715 
00716     start = ptr;
00717     parse_sleb128(ptr, (int64_t*)&dst->next_action);
00718 
00719     
00720 
00721 
00722 
00723     if (dst->next_action)
00724         return start + dst->next_action;
00725     else
00726         return 0;
00727 }
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 static int
00736 find_applicable_call_site(struct LSDA_Header *lsda,
00737                           struct _Unwind_Context *context,
00738                           struct Call_Site *dst)
00739 {
00740     
00741 
00742 
00743 
00744     unsigned char *IP = (unsigned char *)_Unwind_GetIP(context) - 1;
00745 
00746     
00747 
00748 
00749     unsigned char *ptr = lsda->call_sites;
00750 
00751     
00752 
00753 
00754 
00755     unsigned char *region =
00756         (unsigned char *)_Unwind_GetRegionStart(context);
00757 
00758     
00759 
00760 
00761     while ((ptr = parse_Call_Site(lsda, ptr, dst))) {
00762 
00763         
00764 
00765 
00766 
00767         unsigned char *region_start = region + dst->region_start;
00768         if (IP < region_start)
00769             return 1;
00770 
00771         
00772 
00773 
00774 
00775         if (IP < region_start + dst->region_length)
00776             return 0;
00777     }
00778 
00779     
00780 
00781 
00782 
00783     fatal_error("IP out of bounds for call site table!");
00784     return 1;
00785 }
00786 
00787 
00788 
00789 
00790 
00791 
00792 
00793 static int
00794 match_exception(struct LSDA_Header *lsda,
00795                 struct _Unwind_Exception *exceptionObject,
00796                 uint64_t action_index, uint64_t *dst)
00797 {
00798     struct Action_Record action;
00799     unsigned char *ptr;
00800 
00801     
00802 
00803 
00804     struct comma_exception *exception = to_comma_exception(exceptionObject);
00805 
00806     
00807 
00808 
00809 
00810     if (action_index == 0) {
00811         fatal_error("Invalid action index!");
00812         return 1;
00813     }
00814     else {
00815         action_index -= 1;
00816         ptr = lsda->actions + action_index;
00817     }
00818 
00819     
00820 
00821 
00822     do {
00823         ptr = parse_Action_Record(ptr, &action);
00824 
00825         if (action.info_index > 0) {
00826             
00827 
00828 
00829 
00830 
00831 
00832 
00833 
00834 
00835 
00836 
00837 
00838 
00839 
00840 
00841             comma_exinfo_t *info;
00842             info = (comma_exinfo_t *)lsda->type_table;
00843             info -= action.info_index;
00844 
00845             
00846 
00847 
00848 
00849 
00850             if ((*info == 0) || (exception->id == *info)) {
00851                 *dst = action.info_index;
00852                 return 0;
00853             }
00854         }
00855         else {
00856             
00857 
00858 
00859 
00860             if (action.info_index < 0) {
00861                 fatal_error("Filter action detected!");
00862                 return 1;
00863             }
00864         }
00865     } while (ptr);
00866 
00867     
00868 
00869 
00870     return 1;
00871 }
00872 
00873 static void
00874 install_handler(struct _Unwind_Context *context,
00875                 struct _Unwind_Exception *exceptionObject,
00876                 int64_t landing_pad, uintptr_t id)
00877 {
00878     
00879 
00880 
00881 
00882     struct comma_exception *exception = to_comma_exception(exceptionObject);
00883 
00884     
00885 
00886 
00887     _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
00888                   (uintptr_t)exception);
00889 
00890     
00891 
00892 
00893 
00894     _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), id);
00895 
00896     
00897 
00898 
00899     _Unwind_SetIP(context, (uintptr_t)landing_pad);
00900 }
00901 
00902 
00903 
00904 
00905 
00906 
00907 static const uint64_t Comma_Exception_Class_ID = 0x534D570434D410Ull;
00908 
00909 
00910 
00911 
00912 static void _comma_cleanup_exception(_Unwind_Reason_Code reason,
00913                                      struct _Unwind_Exception *exc)
00914 {
00915     struct comma_exception *exception = to_comma_exception(exc);
00916     if (exception->flags & COMMA_DYN_MESSAGE)
00917         free(exception->message);
00918     free(exception);
00919 }
00920 
00921 
00922 
00923 
00924 
00925 void _comma_raise_exception(comma_exinfo_t info,
00926                             const char *file_name, uint32_t line_number,
00927                             const char *message)
00928 {
00929     struct comma_exception *exception;
00930     struct _Unwind_Exception *exception_object;
00931 
00932     
00933 
00934 
00935     exception = malloc(sizeof(struct comma_exception));
00936     exception->id = info;
00937     exception->file_name = file_name;
00938     exception->line_number = line_number;
00939     exception->message = (char*)message;
00940     exception->flags = 0;
00941 
00942     
00943 
00944 
00945 
00946 
00947     exception->header.exception_class = Comma_Exception_Class_ID;
00948     exception->header.exception_cleanup = _comma_cleanup_exception;
00949 
00950     
00951 
00952 
00953     exception_object = to_Unwind_Exception(exception);
00954     _Unwind_RaiseException(exception_object);
00955 }
00956 
00957 
00958 
00959 
00960 
00961 void _comma_raise_nexception(comma_exinfo_t info,
00962                              const char *file_name, uint32_t line_number,
00963                              const char *message, uint32_t length)
00964 {
00965     struct comma_exception *exception;
00966     struct _Unwind_Exception *exception_object;
00967 
00968     
00969 
00970 
00971     exception = malloc(sizeof(struct comma_exception));
00972     exception->id = info;
00973     exception->file_name = file_name;
00974     exception->line_number = line_number;
00975 
00976     if (message) {
00977         exception->message = malloc(length + 1);
00978         exception->message = memcpy(exception->message, message, length);
00979         exception->message[length] = 0;
00980         exception->flags = COMMA_DYN_MESSAGE;
00981     }
00982     else {
00983         exception->message = 0;
00984         exception->flags = 0;
00985     }
00986 
00987     
00988 
00989 
00990 
00991 
00992     exception->header.exception_class = Comma_Exception_Class_ID;
00993     exception->header.exception_cleanup = _comma_cleanup_exception;
00994 
00995     
00996 
00997 
00998     exception_object = to_Unwind_Exception(exception);
00999     _Unwind_RaiseException(exception_object);
01000 }
01001 
01002 
01003 
01004 
01005 void _comma_reraise_exception(struct comma_exception *exception)
01006 {
01007     struct _Unwind_Exception *exception_object = to_Unwind_Exception(exception);
01008     _Unwind_RaiseException(exception_object);
01009 }
01010 
01011 
01012 
01013 
01014 void _comma_raise_system(uint32_t id,
01015                          const char *file_name, uint32_t line_number,
01016                          const char *message)
01017 {
01018     comma_exinfo_t info = _comma_get_exception(id);
01019     _comma_raise_exception(info, file_name, line_number, message);
01020 }
01021 
01022 
01023 
01024 
01025 _Unwind_Reason_Code
01026 _comma_eh_personality(int version,
01027                       _Unwind_Action actions,
01028                       uint64_t exceptionClass,
01029                       struct _Unwind_Exception *exceptionObject,
01030                       struct _Unwind_Context *context)
01031 {
01032     struct LSDA_Header lsda;
01033     struct Call_Site site;
01034     uint64_t id;
01035     intptr_t handler;
01036 
01037     
01038 
01039 
01040 
01041     if (version != 1) {
01042         return _URC_FATAL_PHASE1_ERROR;
01043     }
01044 
01045     
01046 
01047 
01048 
01049 
01050     if (exceptionClass != Comma_Exception_Class_ID) {
01051         return _URC_FATAL_PHASE1_ERROR;
01052     }
01053 
01054     
01055 
01056 
01057     if (parse_LSDA(context, &lsda))
01058         return _URC_CONTINUE_UNWIND;
01059     dump_LSDA(&lsda);
01060 
01061     
01062 
01063 
01064     if (find_applicable_call_site(&lsda, context, &site))
01065         return _URC_CONTINUE_UNWIND;
01066     dump_Call_Site(&site);
01067 
01068     
01069 
01070 
01071 
01072     if (!site.landing_pad)
01073         return _URC_CONTINUE_UNWIND;
01074 
01075     
01076 
01077 
01078 
01079     if (!site.action_index) {
01080         fatal_error("Cleanups are not supported!");
01081         return _URC_FATAL_PHASE1_ERROR;
01082     }
01083 
01084     
01085 
01086 
01087 
01088     if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
01089         return _URC_CONTINUE_UNWIND;
01090 
01091     
01092 
01093 
01094 
01095 
01096     if (match_exception(&lsda, exceptionObject, site.action_index, &id))
01097         return _URC_CONTINUE_UNWIND;
01098 
01099     
01100 
01101 
01102     if (actions & _UA_SEARCH_PHASE)
01103         return _URC_HANDLER_FOUND;
01104 
01105     
01106 
01107 
01108     if (!(actions & _UA_HANDLER_FRAME))
01109         return _URC_CONTINUE_UNWIND;
01110 
01111     
01112 
01113 
01114 
01115     handler = lsda.lpstart + site.landing_pad;
01116     install_handler(context, exceptionObject, handler, id);
01117     return _URC_INSTALL_CONTEXT;
01118 }
01119 
01120 
01121 
01122 
01123 
01124 void _comma_unhandled_exception(struct comma_exception *exception)
01125 {
01126     const char *message = exception->message;
01127 
01128     if (message)
01129         fprintf(stderr, "Unhandled exception: %s:%d: %s: %s\n",
01130                 exception->file_name, exception->line_number,
01131                 *exception->id, message);
01132     else
01133         fprintf(stderr, "Unhandled exception: %s:%d: %s\n",
01134                 exception->file_name, exception->line_number,
01135                 *exception->id);
01136 
01137     abort();
01138 }
01139 
01140 
01141 
01142 
01143 
01144 char *_comma_exinfo_program_error = "PROGRAM_ERROR";
01145 char *_comma_exinfo_constraint_error = "CONSTRAINT_ERROR";
01146 char *_comma_exinfo_assertion_error = "ASSERTION_ERROR";
01147 
01148 
01149 
01150 
01151 comma_exinfo_t _comma_get_exception(comma_exception_id id)
01152 {
01153     comma_exinfo_t info = 0;
01154     switch (id) {
01155     default:
01156         fatal_error("Invalid exception ID!");
01157         break;
01158 
01159     case COMMA_CONSTRAINT_ERROR_E:
01160         info = &_comma_exinfo_constraint_error;
01161         break;
01162 
01163     case COMMA_PROGRAM_ERROR_E:
01164         info = &_comma_exinfo_program_error;
01165         break;
01166 
01167     case COMMA_ASSERTION_ERROR_E:
01168         info = &_comma_exinfo_assertion_error;
01169         break;
01170     }
01171     return info;
01172 }