Changes in libcfa/src/exception.c [3b9c674:851fd92]
- File:
-
- 1 edited
-
libcfa/src/exception.c (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/exception.c
r3b9c674 r851fd92 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T hu Feb 22 18:17:34 201813 // Update Count : 1 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 14 12:01:00 2020 13 // Update Count : 18 14 14 // 15 15 16 // Normally we would get this from the CFA prelude. 16 17 #include <stddef.h> // for size_t 17 18 18 19 #include "exception.h" 19 20 20 // Implementation of the secret header. 21 // Implementation of the secret header is hardware dependent. 22 #if !( defined( __x86_64 ) || defined( __i386 ) ) 23 #error Exception Handling: No known architecture detected. 24 #endif 21 25 22 26 #include <stdlib.h> … … 24 28 #include <unwind.h> 25 29 #include <bits/debug.hfa> 30 #include "stdhdr/assert.h" 26 31 27 32 // FIX ME: temporary hack to keep ARM build working 28 33 #ifndef _URC_FATAL_PHASE1_ERROR 29 #define _URC_FATAL_PHASE1_ERROR 234 #define _URC_FATAL_PHASE1_ERROR 3 30 35 #endif // ! _URC_FATAL_PHASE1_ERROR 31 36 #ifndef _URC_FATAL_PHASE2_ERROR … … 35 40 #include "lsda.h" 36 41 42 /* The exception class for our exceptions. Because of the vendor component 43 * its value would not be standard. 44 * Vendor: UWPL 45 * Language: CFA\0 46 */ 47 const _Unwind_Exception_Class __cfaehm_exception_class = 0x4c50575500414643; 37 48 38 49 // Base exception vtable is abstract, you should not have base exceptions. 39 struct __cfa abi_ehm__base_exception_t_vtable40 ___cfa abi_ehm__base_exception_t_vtable_instance = {50 struct __cfaehm_base_exception_t_vtable 51 ___cfaehm_base_exception_t_vtable_instance = { 41 52 .parent = NULL, 42 53 .size = 0, … … 49 60 // Temperary global exception context. Does not work with concurency. 50 61 struct exception_context_t { 51 struct __cfaabi_ehm__try_resume_node * top_resume; 52 struct __cfaabi_ehm__try_resume_node * current_resume; 53 54 exception_t * current_exception; 55 int current_handler_index; 56 } shared_stack = {NULL, NULL, 0, 0}; 62 struct __cfaehm_try_resume_node * top_resume; 63 64 exception_t * current_exception; 65 int current_handler_index; 66 } static shared_stack = {NULL, NULL, 0}; 57 67 58 68 // Get the current exception context. … … 62 72 return &shared_stack; 63 73 } 64 //#define SAVE_EXCEPTION_CONTEXT(to_name)65 //struct exception_context_t * to_name = this_exception_context();66 //exception * this_exception() {67 // return this_exception_context()->current_exception;68 //}69 70 71 // This macro should be the only thing that needs to change across machines.72 // Used in the personality function, way down in termination.73 // struct _Unwind_Context * -> _Unwind_Reason_Code(*)(exception_t *)74 #define MATCHER_FROM_CONTEXT(ptr_to_context) \75 (*(_Unwind_Reason_Code(**)(exception_t *))(_Unwind_GetCFA(ptr_to_context) + 8))76 74 77 75 78 76 // RESUMPTION ================================================================ 79 77 80 void __cfaabi_ehm__throw_resume(exception_t * except) { 81 82 __cfaabi_dbg_print_safe("Throwing resumption exception\n"); 83 84 struct __cfaabi_ehm__try_resume_node * original_head = shared_stack.current_resume; 85 struct __cfaabi_ehm__try_resume_node * current = 86 (original_head) ? original_head->next : shared_stack.top_resume; 78 static void reset_top_resume(struct __cfaehm_try_resume_node ** store) { 79 this_exception_context()->top_resume = *store; 80 } 81 82 void __cfaehm_throw_resume(exception_t * except) { 83 struct exception_context_t * context = this_exception_context(); 84 85 __cfadbg_print_safe(exception, "Throwing resumption exception\n"); 86 87 __attribute__((cleanup(reset_top_resume))) 88 struct __cfaehm_try_resume_node * original_head = context->top_resume; 89 struct __cfaehm_try_resume_node * current = context->top_resume; 87 90 88 91 for ( ; current ; current = current->next) { 89 shared_stack.current_resume = current;92 context->top_resume = current->next; 90 93 if (current->handler(except)) { 91 shared_stack.current_resume = original_head;92 94 return; 93 95 } 94 96 } 95 97 96 __cfaabi_dbg_print_safe("Unhandled exception\n"); 97 shared_stack.current_resume = original_head; 98 __cfadbg_print_safe(exception, "Unhandled exception\n"); 98 99 99 100 // Fall back to termination: 100 __cfa abi_ehm__throw_terminate(except);101 __cfaehm_throw_terminate(except); 101 102 // TODO: Default handler for resumption. 102 103 } … … 106 107 // be added after the node is built but before it is made the top node. 107 108 108 void __cfa abi_ehm__try_resume_setup(struct __cfaabi_ehm__try_resume_node * node,109 void __cfaehm_try_resume_setup(struct __cfaehm_try_resume_node * node, 109 110 _Bool (*handler)(exception_t * except)) { 110 node->next = shared_stack.top_resume; 111 struct exception_context_t * context = this_exception_context(); 112 node->next = context->top_resume; 111 113 node->handler = handler; 112 shared_stack.top_resume = node; 113 } 114 115 void __cfaabi_ehm__try_resume_cleanup(struct __cfaabi_ehm__try_resume_node * node) { 116 shared_stack.top_resume = node->next; 114 context->top_resume = node; 115 } 116 117 void __cfaehm_try_resume_cleanup(struct __cfaehm_try_resume_node * node) { 118 struct exception_context_t * context = this_exception_context(); 119 context->top_resume = node->next; 117 120 } 118 121 … … 123 126 // May have to move to cfa for constructors and destructors (references). 124 127 125 struct __cfaabi_ehm__node { 126 struct __cfaabi_ehm__node * next; 128 // How to clean up an exception in various situations. 129 static void __cfaehm_exception_cleanup( 130 _Unwind_Reason_Code reason, 131 struct _Unwind_Exception * exception) { 132 switch (reason) { 133 case _URC_FOREIGN_EXCEPTION_CAUGHT: 134 // This one we could clean-up to allow cross-language exceptions. 135 case _URC_FATAL_PHASE1_ERROR: 136 case _URC_FATAL_PHASE2_ERROR: 137 default: 138 abort(); 139 } 140 } 141 142 // We need a piece of storage to raise the exception, for now its a single 143 // piece. 144 static struct _Unwind_Exception this_exception_storage; 145 146 struct __cfaehm_node { 147 struct __cfaehm_node * next; 127 148 }; 128 149 129 150 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node))) 130 #define EXCEPT_TO_NODE(except) ((struct __cfa abi_ehm__node *)(except) - 1)151 #define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1) 131 152 132 153 // Creates a copy of the indicated exception and sets current_exception to it. 133 static void __cfa abi_ehm__allocate_exception( exception_t * except ) {154 static void __cfaehm_allocate_exception( exception_t * except ) { 134 155 struct exception_context_t * context = this_exception_context(); 135 156 136 157 // Allocate memory for the exception. 137 struct __cfa abi_ehm__node * store = malloc(138 sizeof( struct __cfa abi_ehm__node ) + except->virtual_table->size );158 struct __cfaehm_node * store = malloc( 159 sizeof( struct __cfaehm_node ) + except->virtual_table->size ); 139 160 140 161 if ( ! store ) { … … 149 170 // Copy the exception to storage. 150 171 except->virtual_table->copy( context->current_exception, except ); 172 173 // Set up the exception storage. 174 this_exception_storage.exception_class = __cfaehm_exception_class; 175 this_exception_storage.exception_cleanup = __cfaehm_exception_cleanup; 151 176 } 152 177 153 178 // Delete the provided exception, unsetting current_exception if relivant. 154 static void __cfa abi_ehm__delete_exception( exception_t * except ) {179 static void __cfaehm_delete_exception( exception_t * except ) { 155 180 struct exception_context_t * context = this_exception_context(); 156 181 157 __cfa abi_dbg_print_safe("Deleting Exception\n");182 __cfadbg_print_safe(exception, "Deleting Exception\n"); 158 183 159 184 // Remove the exception from the list. 160 struct __cfa abi_ehm__node * to_free = EXCEPT_TO_NODE(except);161 struct __cfa abi_ehm__node * node;185 struct __cfaehm_node * to_free = EXCEPT_TO_NODE(except); 186 struct __cfaehm_node * node; 162 187 163 188 if ( context->current_exception == except ) { … … 167 192 node = EXCEPT_TO_NODE(context->current_exception); 168 193 // It may always be in the first or second position. 169 while ( to_free != node->next ) {194 while ( to_free != node->next ) { 170 195 node = node->next; 171 196 } … … 179 204 180 205 // If this isn't a rethrow (*except==0), delete the provided exception. 181 void __cfaabi_ehm__cleanup_terminate( void * except ) { 182 if ( *(void**)except ) __cfaabi_ehm__delete_exception( *(exception_t **)except ); 183 } 184 185 186 // We need a piece of storage to raise the exception 187 struct _Unwind_Exception this_exception_storage; 206 void __cfaehm_cleanup_terminate( void * except ) { 207 if ( *(void**)except ) __cfaehm_delete_exception( *(exception_t **)except ); 208 } 188 209 189 210 // Function needed by force unwind … … 192 213 int version, 193 214 _Unwind_Action actions, 194 _Unwind_Exception_Class exception Class,215 _Unwind_Exception_Class exception_class, 195 216 struct _Unwind_Exception * unwind_exception, 196 struct _Unwind_Context * context, 197 void * some_param) { 198 if( actions & _UA_END_OF_STACK ) exit(1); 199 if( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON; 200 201 return _URC_FATAL_PHASE2_ERROR; 217 struct _Unwind_Context * unwind_context, 218 void * stop_param) { 219 // Verify actions follow the rules we expect. 220 verify((actions & _UA_CLEANUP_PHASE) && (actions & _UA_FORCE_UNWIND)); 221 verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDER_FRAME))); 222 223 if ( actions & _UA_END_OF_STACK ) { 224 exit(1); 225 } else { 226 return _URC_NO_REASON; 227 } 202 228 } 203 229 204 230 // The exception that is being thrown must already be stored. 205 __attribute__((noreturn)) void __cfaabi_ehm__begin_unwind(void) {231 static __attribute__((noreturn)) void __cfaehm_begin_unwind(void) { 206 232 if ( ! this_exception_context()->current_exception ) { 207 233 printf("UNWIND ERROR missing exception in begin unwind\n"); 208 234 abort(); 209 235 } 210 211 236 212 237 // Call stdlibc to raise the exception … … 220 245 // the whole stack. 221 246 222 if ( ret == _URC_END_OF_STACK ) {247 if ( ret == _URC_END_OF_STACK ) { 223 248 // No proper handler was found. This can be handled in many ways, C++ calls std::terminate. 224 249 // Here we force unwind the stack, basically raising a cancellation. … … 235 260 } 236 261 237 void __cfaabi_ehm__throw_terminate( exception_t * val ) { 238 __cfaabi_dbg_print_safe("Throwing termination exception\n"); 239 240 __cfaabi_ehm__allocate_exception( val ); 241 __cfaabi_ehm__begin_unwind(); 242 } 243 244 void __cfaabi_ehm__rethrow_terminate(void) { 245 __cfaabi_dbg_print_safe("Rethrowing termination exception\n"); 246 247 __cfaabi_ehm__begin_unwind(); 248 } 249 250 #pragma GCC push_options 251 #pragma GCC optimize("O0") 262 void __cfaehm_throw_terminate( exception_t * val ) { 263 __cfadbg_print_safe(exception, "Throwing termination exception\n"); 264 265 __cfaehm_allocate_exception( val ); 266 __cfaehm_begin_unwind(); 267 } 268 269 void __cfaehm_rethrow_terminate(void) { 270 __cfadbg_print_safe(exception, "Rethrowing termination exception\n"); 271 272 __cfaehm_begin_unwind(); 273 } 252 274 253 275 // This is our personality routine. For every stack frame annotated with 254 276 // ".cfi_personality 0x3,__gcfa_personality_v0" this function will be called twice when unwinding. 255 277 // Once in the search phase and once in the cleanup phase. 256 _Unwind_Reason_Code __gcfa_personality_v0 ( 257 int version, _Unwind_Action actions, unsigned long long exceptionClass, 258 struct _Unwind_Exception* unwind_exception, 259 struct _Unwind_Context* context) 278 _Unwind_Reason_Code __gcfa_personality_v0( 279 int version, 280 _Unwind_Action actions, 281 unsigned long long exception_class, 282 struct _Unwind_Exception * unwind_exception, 283 struct _Unwind_Context * unwind_context) 260 284 { 261 285 262 //__cfaabi_dbg_print_safe("CFA: 0x%lx\n", _Unwind_GetCFA(context)); 263 __cfaabi_dbg_print_safe("Personality function (%d, %x, %llu, %p, %p):", 264 version, actions, exceptionClass, unwind_exception, context); 265 266 // If we've reached the end of the stack then there is nothing much we can do... 267 if( actions & _UA_END_OF_STACK ) return _URC_END_OF_STACK; 268 286 //__cfadbg_print_safe(exception, "CFA: 0x%lx\n", _Unwind_GetCFA(context)); 287 __cfadbg_print_safe(exception, "Personality function (%d, %x, %llu, %p, %p):", 288 version, actions, exception_class, unwind_exception, unwind_context); 289 290 // Verify that actions follow the rules we expect. 291 // This function should never be called at the end of the stack. 292 verify(!(actions & _UA_END_OF_STACK)); 293 // Either only the search phase flag is set or... 269 294 if (actions & _UA_SEARCH_PHASE) { 270 __cfaabi_dbg_print_safe(" lookup phase"); 271 } 272 else if (actions & _UA_CLEANUP_PHASE) { 273 __cfaabi_dbg_print_safe(" cleanup phase"); 274 } 275 // Just in case, probably can't actually happen 276 else { 277 printf(" error\n"); 278 return _URC_FATAL_PHASE1_ERROR; 295 verify(actions == _UA_SEARCH_PHASE); 296 __cfadbg_print_safe(exception, " lookup phase"); 297 // ... we are in clean-up phase. 298 } else { 299 verify(actions & _UA_CLEANUP_PHASE); 300 __cfadbg_print_safe(exception, " cleanup phase"); 301 // We shouldn't be the handler frame during forced unwind. 302 if (actions & _UA_HANDLER_FRAME) { 303 verify(!(actions & _UA_FORCE_UNWIND)); 304 __cfadbg_print_safe(exception, " (handler frame)"); 305 } else if (actions & _UA_FORCE_UNWIND) { 306 __cfadbg_print_safe(exception, " (force unwind)"); 307 } 279 308 } 280 309 281 310 // Get a pointer to the language specific data from which we will read what we need 282 const unsigned char * lsd = (const unsigned char*) _Unwind_GetLanguageSpecificData(context );283 284 if ( !lsd ) { //Nothing to do, keep unwinding311 const unsigned char * lsd = _Unwind_GetLanguageSpecificData( unwind_context ); 312 313 if ( !lsd ) { //Nothing to do, keep unwinding 285 314 printf(" no LSD"); 286 315 goto UNWIND; … … 289 318 // Get the instuction pointer and a reading pointer into the exception table 290 319 lsda_header_info lsd_info; 291 const unsigned char * cur_ptr = parse_lsda_header(context, lsd, &lsd_info); 292 _Unwind_Ptr instruction_ptr = _Unwind_GetIP( context ); 320 const unsigned char * cur_ptr = parse_lsda_header(unwind_context, lsd, &lsd_info); 321 _Unwind_Ptr instruction_ptr = _Unwind_GetIP(unwind_context); 322 323 struct exception_context_t * context = this_exception_context(); 293 324 294 325 // Linearly search the table for stuff to do 295 while ( cur_ptr < lsd_info.action_table ) {326 while ( cur_ptr < lsd_info.action_table ) { 296 327 _Unwind_Ptr callsite_start; 297 328 _Unwind_Ptr callsite_len; … … 306 337 307 338 // Have we reach the correct frame info yet? 308 if ( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) {339 if ( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) { 309 340 #ifdef __CFA_DEBUG_PRINT__ 310 341 void * ls = (void*)lsd_info.Start; … … 314 345 void * ep = (void*)lsd_info.Start + callsite_start + callsite_len; 315 346 void * ip = (void*)instruction_ptr; 316 __cfa abi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n",347 __cfadbg_print_safe(exception, "\nfound %p - %p (%p, %p, %p), looking for %p\n", 317 348 bp, ep, ls, cs, cl, ip); 318 349 #endif // __CFA_DEBUG_PRINT__ … … 321 352 322 353 // Have we gone too far? 323 if ( lsd_info.Start + callsite_start > instruction_ptr ) {354 if ( lsd_info.Start + callsite_start > instruction_ptr ) { 324 355 printf(" gone too far"); 325 356 break; 326 357 } 327 358 328 // Something to do? 329 if( callsite_landing_pad ) { 330 // Which phase are we in 331 if (actions & _UA_SEARCH_PHASE) { 332 // In search phase, these means we found a potential handler we must check. 333 334 // We have arbitrarily decided that 0 means nothing to do and 1 means there is 335 // a potential handler. This doesn't seem to conflict the gcc default behavior. 336 if (callsite_action != 0) { 337 // Now we want to run some code to see if the handler matches 338 // This is the tricky part where we want to the power to run arbitrary code 339 // However, generating a new exception table entry and try routine every time 340 // is way more expansive than we might like 341 // The information we have is : 342 // - The GR (Series of registers) 343 // GR1=GP Global Pointer of frame ref by context 344 // - The instruction pointer 345 // - The instruction pointer info (???) 346 // - The CFA (Canonical Frame Address) 347 // - The BSP (Probably the base stack pointer) 348 349 350 // The current apprach uses one exception table entry per try block 351 _uleb128_t imatcher; 352 // Get the relative offset to the {...}? 353 cur_ptr = read_uleb128(cur_ptr, &imatcher); 354 355 _Unwind_Reason_Code (*matcher)(exception_t *) = 356 MATCHER_FROM_CONTEXT(context); 357 int index = matcher(shared_stack.current_exception); 358 _Unwind_Reason_Code ret = (0 == index) 359 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 360 shared_stack.current_handler_index = index; 361 362 // Based on the return value, check if we matched the exception 363 if( ret == _URC_HANDLER_FOUND) { 364 __cfaabi_dbg_print_safe(" handler found\n"); 365 } else { 366 __cfaabi_dbg_print_safe(" no handler\n"); 367 } 368 return ret; 359 // Check for what we must do: 360 if ( 0 == callsite_landing_pad ) { 361 // Nothing to do, move along 362 __cfadbg_print_safe(exception, " no landing pad"); 363 } else if (actions & _UA_SEARCH_PHASE) { 364 // In search phase, these means we found a potential handler we must check. 365 366 // We have arbitrarily decided that 0 means nothing to do and 1 means there is 367 // a potential handler. This doesn't seem to conflict the gcc default behavior. 368 if (callsite_action != 0) { 369 // Now we want to run some code to see if the handler matches 370 // This is the tricky part where we want to the power to run arbitrary code 371 // However, generating a new exception table entry and try routine every time 372 // is way more expansive than we might like 373 // The information we have is : 374 // - The GR (Series of registers) 375 // GR1=GP Global Pointer of frame ref by context 376 // - The instruction pointer 377 // - The instruction pointer info (???) 378 // - The CFA (Canonical Frame Address) 379 // - The BSP (Probably the base stack pointer) 380 381 // The current apprach uses one exception table entry per try block 382 _uleb128_t imatcher; 383 // Get the relative offset to the {...}? 384 cur_ptr = read_uleb128(cur_ptr, &imatcher); 385 386 # if defined( __x86_64 ) 387 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 8; 388 # elif defined( __i386 ) 389 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 24; 390 # endif 391 int (*matcher)(exception_t *) = *(int(**)(exception_t *))match_pos; 392 393 int index = matcher(context->current_exception); 394 _Unwind_Reason_Code ret = (0 == index) 395 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 396 context->current_handler_index = index; 397 398 // Based on the return value, check if we matched the exception 399 if (ret == _URC_HANDLER_FOUND) { 400 __cfadbg_print_safe(exception, " handler found\n"); 401 } else { 402 __cfadbg_print_safe(exception, " no handler\n"); 369 403 } 370 371 // This is only a cleanup handler, ignore it 372 __cfaabi_dbg_print_safe(" no action"); 404 return ret; 373 405 } 374 else if (actions & _UA_CLEANUP_PHASE) { 375 376 if( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){ 377 // If this is a potential exception handler 378 // but not the one that matched the exception in the seach phase, 379 // just ignore it 380 goto UNWIND; 381 } 382 383 // We need to run some clean-up or a handler 384 // These statment do the right thing but I don't know any specifics at all 385 _Unwind_SetGR( context, __builtin_eh_return_data_regno(0), (_Unwind_Ptr) unwind_exception ); 386 _Unwind_SetGR( context, __builtin_eh_return_data_regno(1), 0 ); 387 388 // I assume this sets the instruction pointer to the adress of the landing pad 389 // It doesn't actually set it, it only state the value that needs to be set once we return _URC_INSTALL_CONTEXT 390 _Unwind_SetIP( context, ((lsd_info.LPStart) + (callsite_landing_pad)) ); 391 392 __cfaabi_dbg_print_safe(" action\n"); 393 394 // Return have some action to run 395 return _URC_INSTALL_CONTEXT; 406 407 // This is only a cleanup handler, ignore it 408 __cfadbg_print_safe(exception, " no action"); 409 } else { 410 // In clean-up phase, no destructors here but this could be the handler. 411 412 if ( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){ 413 // If this is a potential exception handler 414 // but not the one that matched the exception in the seach phase, 415 // just ignore it 416 goto UNWIND; 396 417 } 418 419 // We need to run some clean-up or a handler 420 // These statment do the right thing but I don't know any specifics at all 421 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(0), 422 (_Unwind_Ptr)unwind_exception ); 423 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(1), 0 ); 424 425 // I assume this sets the instruction pointer to the adress of the landing pad 426 // It doesn't actually set it, it only state the value that needs to be set once we 427 // return _URC_INSTALL_CONTEXT 428 _Unwind_SetIP( unwind_context, ((lsd_info.LPStart) + (callsite_landing_pad)) ); 429 430 __cfadbg_print_safe(exception, " action\n"); 431 432 // Return have some action to run 433 return _URC_INSTALL_CONTEXT; 397 434 } 398 399 // Nothing to do, move along400 __cfaabi_dbg_print_safe(" no landing pad");401 435 } 402 436 // No handling found 403 __cfa abi_dbg_print_safe(" table end reached\n");437 __cfadbg_print_safe(exception, " table end reached"); 404 438 405 439 UNWIND: 406 __cfa abi_dbg_print_safe(" unwind\n");440 __cfadbg_print_safe(exception, " unwind\n"); 407 441 408 442 // Keep unwinding the stack 409 443 return _URC_CONTINUE_UNWIND; 410 444 } 445 446 #pragma GCC push_options 447 #pragma GCC optimize(0) 411 448 412 449 // Try statements are hoisted out see comments for details. While this could probably be unique 413 450 // and simply linked from libcfa but there is one problem left, see the exception table for details 414 451 __attribute__((noinline)) 415 void __cfa abi_ehm__try_terminate(void (*try_block)(),452 void __cfaehm_try_terminate(void (*try_block)(), 416 453 void (*catch_block)(int index, exception_t * except), 417 454 __attribute__((unused)) int (*match_block)(exception_t * except)) { … … 419 456 //! printf("%p %p %p %p\n", &try_block, &catch_block, &match_block, &xy); 420 457 421 // Setup statments: These 2 statments won't actually result in any code, they only setup global tables.422 // However, they clobber gcc cancellation support from gcc. We can replace the personality routine but423 // replacing the exception table gcc generates is not really doable, it generates labels based on how the424 // assembly works.425 426 458 // Setup the personality routine and exception table. 459 // Unforturnately these clobber gcc cancellation support which means we can't get access to 460 // the attribute cleanup tables at the same time. We would have to inspect the assembly to 461 // create a new set ourselves. 427 462 #ifdef __PIC__ 428 463 asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0"); … … 449 484 // Label which defines the end of the area for which the handler is setup. 450 485 asm volatile (".TRYEND:"); 451 // Label which defines the start of the exception landing pad. Basically what is called when the exception is452 // caught. Note, if multiple handlers are given, the multiplexing should be done by the generated code, not the453 // exception runtime.486 // Label which defines the start of the exception landing pad. Basically what is called when 487 // the exception is caught. Note, if multiple handlers are given, the multiplexing should be 488 // done by the generated code, not the exception runtime. 454 489 asm volatile (".CATCH:"); 455 490 456 491 // Exception handler 457 catch_block( shared_stack.current_handler_index, 458 shared_stack.current_exception ); 492 // Note: Saving the exception context on the stack breaks termination exceptions. 493 catch_block( this_exception_context()->current_handler_index, 494 this_exception_context()->current_exception ); 459 495 } 460 496 … … 464 500 465 501 #ifdef __PIC__ 466 #if defined( __i386 ) || defined( __x86_64 )467 502 asm ( 468 503 // HEADER … … 481 516 // handler landing pad offset and 1 (action code, gcc seems to use 0). 482 517 ".LLSDACSBCFA2:\n" 483 " .uleb128 .TRYSTART-__cfa abi_ehm__try_terminate\n"518 " .uleb128 .TRYSTART-__cfaehm_try_terminate\n" 484 519 " .uleb128 .TRYEND-.TRYSTART\n" 485 " .uleb128 .CATCH-__cfa abi_ehm__try_terminate\n"520 " .uleb128 .CATCH-__cfaehm_try_terminate\n" 486 521 " .uleb128 1\n" 487 522 ".LLSDACSECFA2:\n" 488 523 // TABLE FOOTER 489 524 " .text\n" 490 " .size __cfa abi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n"525 " .size __cfaehm_try_terminate, .-__cfaehm_try_terminate\n" 491 526 ); 492 527 … … 507 542 " .quad __gcfa_personality_v0\n" 508 543 #else // then __i386 509 " .long __gcfa_personality_v0\n"544 " .long __gcfa_personality_v0\n" 510 545 #endif 511 546 ); 512 #else513 #error Exception Handling: unknown architecture for position independent code.514 #endif // __i386 || __x86_64515 547 #else // __PIC__ 516 #if defined( __i386 ) || defined( __x86_64 )517 548 asm ( 518 549 // HEADER … … 529 560 ".LLSDACSBCFA2:\n" 530 561 // Handled area start (relative to start of function) 531 " .uleb128 .TRYSTART-__cfa abi_ehm__try_terminate\n"562 " .uleb128 .TRYSTART-__cfaehm_try_terminate\n" 532 563 // Handled area length 533 564 " .uleb128 .TRYEND-.TRYSTART\n" 534 565 // Handler landing pad address (relative to start of function) 535 " .uleb128 .CATCH-__cfa abi_ehm__try_terminate\n"566 " .uleb128 .CATCH-__cfaehm_try_terminate\n" 536 567 // Action code, gcc seems to always use 0. 537 568 " .uleb128 1\n" … … 539 570 ".LLSDACSECFA2:\n" 540 571 " .text\n" 541 " .size __cfa abi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n"572 " .size __cfaehm_try_terminate, .-__cfaehm_try_terminate\n" 542 573 " .ident \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n" 543 574 " .section .note.GNU-stack,\"x\",@progbits\n" 544 575 ); 545 #else546 #error Exception Handling: unknown architecture for position dependent code.547 #endif // __i386 || __x86_64548 576 #endif // __PIC__ 549 577
Note:
See TracChangeset
for help on using the changeset viewer.