Changeset 9cb89b87
- Timestamp:
- Mar 26, 2020, 10:56:38 AM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 68887f9
- Parents:
- 2a3b019
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/exception.c
r2a3b019 r9cb89b87 58 58 exception_t * current_exception; 59 59 int current_handler_index; 60 } s hared_stack = {NULL, NULL, 0, 0};60 } static shared_stack = {NULL, NULL, NULL, 0}; 61 61 62 62 // Get the current exception context. 63 63 // There can be a single global until multithreading occurs, then each stack 64 64 // needs its own. It will have to be updated to handle that. 65 inline staticstruct exception_context_t * this_exception_context() {65 struct exception_context_t * this_exception_context() { 66 66 return &shared_stack; 67 67 } … … 162 162 node = EXCEPT_TO_NODE(context->current_exception); 163 163 // It may always be in the first or second position. 164 while ( to_free != node->next ) {164 while ( to_free != node->next ) { 165 165 node = node->next; 166 166 } … … 191 191 struct _Unwind_Context * unwind_context, 192 192 void * stop_param) { 193 if ( actions & _UA_END_OF_STACK ) exit(1);194 if ( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON;193 if ( actions & _UA_END_OF_STACK ) exit(1); 194 if ( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON; 195 195 196 196 return _URC_FATAL_PHASE2_ERROR; … … 215 215 // the whole stack. 216 216 217 if ( ret == _URC_END_OF_STACK ) {217 if ( ret == _URC_END_OF_STACK ) { 218 218 // No proper handler was found. This can be handled in many ways, C++ calls std::terminate. 219 219 // Here we force unwind the stack, basically raising a cancellation. … … 257 257 258 258 // If we've reached the end of the stack then there is nothing much we can do... 259 if ( actions & _UA_END_OF_STACK) return _URC_END_OF_STACK;259 if (actions & _UA_END_OF_STACK) return _URC_END_OF_STACK; 260 260 261 261 if (actions & _UA_SEARCH_PHASE) { … … 272 272 273 273 // Get a pointer to the language specific data from which we will read what we need 274 const unsigned char * lsd = (const unsigned char*)_Unwind_GetLanguageSpecificData( unwind_context );275 276 if ( !lsd ) { //Nothing to do, keep unwinding274 const unsigned char * lsd = _Unwind_GetLanguageSpecificData( unwind_context ); 275 276 if ( !lsd ) { //Nothing to do, keep unwinding 277 277 printf(" no LSD"); 278 278 goto UNWIND; … … 287 287 288 288 // Linearly search the table for stuff to do 289 while ( cur_ptr < lsd_info.action_table ) {289 while ( cur_ptr < lsd_info.action_table ) { 290 290 _Unwind_Ptr callsite_start; 291 291 _Unwind_Ptr callsite_len; … … 300 300 301 301 // Have we reach the correct frame info yet? 302 if ( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) {302 if ( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) { 303 303 #ifdef __CFA_DEBUG_PRINT__ 304 304 void * ls = (void*)lsd_info.Start; … … 315 315 316 316 // Have we gone too far? 317 if ( lsd_info.Start + callsite_start > instruction_ptr ) {317 if ( lsd_info.Start + callsite_start > instruction_ptr ) { 318 318 printf(" gone too far"); 319 319 break; 320 320 } 321 321 322 // Something to do?322 // Check for what we must do: 323 323 if ( 0 == callsite_landing_pad ) { 324 324 // Nothing to do, move along 325 325 __cfaabi_dbg_print_safe(" no landing pad"); 326 } else { 327 // Which phase are we in 328 if (actions & _UA_SEARCH_PHASE) { 329 // In search phase, these means we found a potential handler we must check. 330 331 // We have arbitrarily decided that 0 means nothing to do and 1 means there is 332 // a potential handler. This doesn't seem to conflict the gcc default behavior. 333 if (callsite_action != 0) { 334 // Now we want to run some code to see if the handler matches 335 // This is the tricky part where we want to the power to run arbitrary code 336 // However, generating a new exception table entry and try routine every time 337 // is way more expansive than we might like 338 // The information we have is : 339 // - The GR (Series of registers) 340 // GR1=GP Global Pointer of frame ref by context 341 // - The instruction pointer 342 // - The instruction pointer info (???) 343 // - The CFA (Canonical Frame Address) 344 // - The BSP (Probably the base stack pointer) 345 346 347 // The current apprach uses one exception table entry per try block 348 _uleb128_t imatcher; 349 // Get the relative offset to the {...}? 350 cur_ptr = read_uleb128(cur_ptr, &imatcher); 351 352 # if defined( __x86_64 ) 353 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 8; 354 # elif defined( __i386 ) 355 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 24; 356 # endif 357 int (*matcher)(exception_t *) = *(int(**)(exception_t *))match_pos; 358 359 int index = matcher(context->current_exception); 360 _Unwind_Reason_Code ret = (0 == index) 361 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 362 context->current_handler_index = index; 363 364 // Based on the return value, check if we matched the exception 365 if( ret == _URC_HANDLER_FOUND) { 366 __cfaabi_dbg_print_safe(" handler found\n"); 367 } else { 368 __cfaabi_dbg_print_safe(" no handler\n"); 369 } 370 return ret; 326 } else if (actions & _UA_SEARCH_PHASE) { 327 // In search phase, these means we found a potential handler we must check. 328 329 // We have arbitrarily decided that 0 means nothing to do and 1 means there is 330 // a potential handler. This doesn't seem to conflict the gcc default behavior. 331 if (callsite_action != 0) { 332 // Now we want to run some code to see if the handler matches 333 // This is the tricky part where we want to the power to run arbitrary code 334 // However, generating a new exception table entry and try routine every time 335 // is way more expansive than we might like 336 // The information we have is : 337 // - The GR (Series of registers) 338 // GR1=GP Global Pointer of frame ref by context 339 // - The instruction pointer 340 // - The instruction pointer info (???) 341 // - The CFA (Canonical Frame Address) 342 // - The BSP (Probably the base stack pointer) 343 344 345 // The current apprach uses one exception table entry per try block 346 _uleb128_t imatcher; 347 // Get the relative offset to the {...}? 348 cur_ptr = read_uleb128(cur_ptr, &imatcher); 349 350 # if defined( __x86_64 ) 351 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 8; 352 # elif defined( __i386 ) 353 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 24; 354 # endif 355 int (*matcher)(exception_t *) = *(int(**)(exception_t *))match_pos; 356 357 int index = matcher(context->current_exception); 358 _Unwind_Reason_Code ret = (0 == index) 359 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 360 context->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"); 371 367 } 372 373 // This is only a cleanup handler, ignore it 374 __cfaabi_dbg_print_safe(" no action"); 368 return ret; 375 369 } 376 else if (actions & _UA_CLEANUP_PHASE) { 377 378 if( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){ 379 // If this is a potential exception handler 380 // but not the one that matched the exception in the seach phase, 381 // just ignore it 382 goto UNWIND; 383 } 384 385 // We need to run some clean-up or a handler 386 // These statment do the right thing but I don't know any specifics at all 387 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(0), 388 (_Unwind_Ptr)unwind_exception ); 389 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(1), 0 ); 390 391 // I assume this sets the instruction pointer to the adress of the landing pad 392 // It doesn't actually set it, it only state the value that needs to be set once we return _URC_INSTALL_CONTEXT 393 _Unwind_SetIP( unwind_context, ((lsd_info.LPStart) + (callsite_landing_pad)) ); 394 395 __cfaabi_dbg_print_safe(" action\n"); 396 397 // Return have some action to run 398 return _URC_INSTALL_CONTEXT; 370 371 // This is only a cleanup handler, ignore it 372 __cfaabi_dbg_print_safe(" no action"); 373 } else if (actions & _UA_CLEANUP_PHASE) { 374 // In clean-up phase, no destructors here but this could be the handler. 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; 399 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( unwind_context, __builtin_eh_return_data_regno(0), 386 (_Unwind_Ptr)unwind_exception ); 387 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(1), 0 ); 388 389 // I assume this sets the instruction pointer to the adress of the landing pad 390 // It doesn't actually set it, it only state the value that needs to be set once we 391 // return _URC_INSTALL_CONTEXT 392 _Unwind_SetIP( unwind_context, ((lsd_info.LPStart) + (callsite_landing_pad)) ); 393 394 __cfaabi_dbg_print_safe(" action\n"); 395 396 // Return have some action to run 397 return _URC_INSTALL_CONTEXT; 400 398 } 401 399 } … … 422 420 //! printf("%p %p %p %p\n", &try_block, &catch_block, &match_block, &xy); 423 421 424 // Setup statments: These 2 statments won't actually result in any code, they only setup global tables.425 // However, they clobber gcc cancellation support from gcc. We can replace the personality routine but426 // replacing the exception table gcc generates is not really doable, it generates labels based on how the427 // assembly works.428 429 422 // Setup the personality routine and exception table. 423 // Unforturnately these clobber gcc cancellation support which means we can't get access to 424 // the attribute cleanup tables at the same time. We would have to inspect the assembly to 425 // create a new set ourselves. 430 426 #ifdef __PIC__ 431 427 asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0"); … … 452 448 // Label which defines the end of the area for which the handler is setup. 453 449 asm volatile (".TRYEND:"); 454 // Label which defines the start of the exception landing pad. Basically what is called when the exception is455 // caught. Note, if multiple handlers are given, the multiplexing should be done by the generated code, not the456 // exception runtime.450 // Label which defines the start of the exception landing pad. Basically what is called when 451 // the exception is caught. Note, if multiple handlers are given, the multiplexing should be 452 // done by the generated code, not the exception runtime. 457 453 asm volatile (".CATCH:"); 458 454
Note: See TracChangeset
for help on using the changeset viewer.