github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/runtime/go-unwind.c (about) 1 /* go-unwind.c -- unwind the stack for panic/recover. 2 3 Copyright 2010 The Go Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style 5 license that can be found in the LICENSE file. */ 6 7 #include "config.h" 8 9 #include <stdlib.h> 10 #include <unistd.h> 11 12 #include "unwind.h" 13 14 #include "runtime.h" 15 16 /* These constants are documented here: 17 https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/dwarfext.html 18 */ 19 20 #define DW_EH_PE_omit 0xff 21 #define DW_EH_PE_absptr 0x00 22 #define DW_EH_PE_uleb128 0x01 23 #define DW_EH_PE_udata2 0x02 24 #define DW_EH_PE_udata4 0x03 25 #define DW_EH_PE_udata8 0x04 26 #define DW_EH_PE_sleb128 0x09 27 #define DW_EH_PE_sdata2 0x0A 28 #define DW_EH_PE_sdata4 0x0B 29 #define DW_EH_PE_sdata8 0x0C 30 #define DW_EH_PE_pcrel 0x10 31 #define DW_EH_PE_textrel 0x20 32 #define DW_EH_PE_datarel 0x30 33 #define DW_EH_PE_funcrel 0x40 34 #define DW_EH_PE_aligned 0x50 35 #define DW_EH_PE_indirect 0x80 36 37 /* The code for a Go exception. */ 38 39 #ifdef __ARM_EABI_UNWINDER__ 40 static const _Unwind_Exception_Class __go_exception_class = 41 { 'G', 'N', 'U', 'C', 'G', 'O', '\0', '\0' }; 42 #else 43 static const _Unwind_Exception_Class __go_exception_class = 44 ((((((((_Unwind_Exception_Class) 'G' 45 << 8 | (_Unwind_Exception_Class) 'N') 46 << 8 | (_Unwind_Exception_Class) 'U') 47 << 8 | (_Unwind_Exception_Class) 'C') 48 << 8 | (_Unwind_Exception_Class) 'G') 49 << 8 | (_Unwind_Exception_Class) 'O') 50 << 8 | (_Unwind_Exception_Class) '\0') 51 << 8 | (_Unwind_Exception_Class) '\0'); 52 #endif 53 54 /* Rethrow an exception. */ 55 56 void rethrowException (void) __asm__(GOSYM_PREFIX "runtime.rethrowException"); 57 58 void 59 rethrowException () 60 { 61 struct _Unwind_Exception *hdr; 62 63 hdr = (struct _Unwind_Exception *) runtime_g()->exception; 64 65 #ifdef __USING_SJLJ_EXCEPTIONS__ 66 _Unwind_SjLj_Resume_or_Rethrow (hdr); 67 #else 68 #if defined(_LIBUNWIND_STD_ABI) 69 _Unwind_RaiseException (hdr); 70 #else 71 _Unwind_Resume_or_Rethrow (hdr); 72 #endif 73 #endif 74 75 /* Rethrowing the exception should not return. */ 76 abort(); 77 } 78 79 /* Return the size of the type that holds an exception header, so that 80 it can be allocated by Go code. */ 81 82 uintptr unwindExceptionSize(void) 83 __asm__ (GOSYM_PREFIX "runtime.unwindExceptionSize"); 84 85 uintptr 86 unwindExceptionSize () 87 { 88 uintptr ret, align; 89 90 ret = sizeof (struct _Unwind_Exception); 91 /* Adjust the size fo make sure that we can get an aligned value. */ 92 align = __alignof__ (struct _Unwind_Exception); 93 if (align > __alignof__ (uintptr)) 94 ret += align - __alignof__ (uintptr); 95 return ret; 96 } 97 98 /* Throw an exception. This is called with g->exception pointing to 99 an uninitialized _Unwind_Exception instance. */ 100 101 void throwException (void) __asm__(GOSYM_PREFIX "runtime.throwException"); 102 103 void 104 throwException () 105 { 106 struct _Unwind_Exception *hdr; 107 uintptr align; 108 109 hdr = (struct _Unwind_Exception *)runtime_g ()->exception; 110 111 /* Make sure the value is correctly aligned. It will be large 112 enough, because of unwindExceptionSize. */ 113 align = __alignof__ (struct _Unwind_Exception); 114 hdr = ((struct _Unwind_Exception *) 115 (((uintptr) hdr + align - 1) &~ (align - 1))); 116 117 __builtin_memcpy (&hdr->exception_class, &__go_exception_class, 118 sizeof hdr->exception_class); 119 hdr->exception_cleanup = NULL; 120 121 #ifdef __USING_SJLJ_EXCEPTIONS__ 122 _Unwind_SjLj_RaiseException (hdr); 123 #else 124 _Unwind_RaiseException (hdr); 125 #endif 126 127 /* Raising an exception should not return. */ 128 abort (); 129 } 130 131 static inline _Unwind_Ptr 132 encoded_value_base (uint8_t encoding, struct _Unwind_Context *context) 133 { 134 if (encoding == DW_EH_PE_omit) 135 return 0; 136 switch (encoding & 0x70) 137 { 138 case DW_EH_PE_absptr: 139 case DW_EH_PE_pcrel: 140 case DW_EH_PE_aligned: 141 return 0; 142 case DW_EH_PE_textrel: 143 return _Unwind_GetTextRelBase(context); 144 case DW_EH_PE_datarel: 145 return _Unwind_GetDataRelBase(context); 146 case DW_EH_PE_funcrel: 147 return _Unwind_GetRegionStart(context); 148 } 149 abort (); 150 } 151 152 /* Read an unsigned leb128 value. */ 153 154 static inline const uint8_t * 155 read_uleb128 (const uint8_t *p, _uleb128_t *val) 156 { 157 unsigned int shift = 0; 158 _uleb128_t result = 0; 159 uint8_t byte; 160 161 do 162 { 163 byte = *p++; 164 result |= ((_uleb128_t)byte & 0x7f) << shift; 165 shift += 7; 166 } 167 while (byte & 0x80); 168 169 *val = result; 170 return p; 171 } 172 173 /* Similar, but read a signed leb128 value. */ 174 175 static inline const uint8_t * 176 read_sleb128 (const uint8_t *p, _sleb128_t *val) 177 { 178 unsigned int shift = 0; 179 _uleb128_t result = 0; 180 uint8_t byte; 181 182 do 183 { 184 byte = *p++; 185 result |= ((_uleb128_t)byte & 0x7f) << shift; 186 shift += 7; 187 } 188 while (byte & 0x80); 189 190 /* sign extension */ 191 if (shift < (8 * sizeof(result)) && (byte & 0x40) != 0) 192 result |= (((_uleb128_t)~0) << shift); 193 194 *val = (_sleb128_t)result; 195 return p; 196 } 197 198 #define ROUND_UP_TO_PVB(x) (x + sizeof(void *) - 1) &- sizeof(void *) 199 200 static inline const uint8_t * 201 read_encoded_value (struct _Unwind_Context *context, uint8_t encoding, 202 const uint8_t *p, _Unwind_Ptr *val) 203 { 204 _Unwind_Ptr base = encoded_value_base (encoding, context); 205 _Unwind_Internal_Ptr decoded = 0; 206 const uint8_t *origp = p; 207 208 if (encoding == DW_EH_PE_aligned) 209 { 210 _Unwind_Internal_Ptr uip = (_Unwind_Internal_Ptr)p; 211 uip = ROUND_UP_TO_PVB (uip); 212 decoded = *(_Unwind_Internal_Ptr *)uip; 213 p = (const uint8_t *)(uip + sizeof(void *)); 214 } 215 else 216 { 217 switch (encoding & 0x0f) 218 { 219 case DW_EH_PE_sdata2: 220 { 221 int16_t result; 222 __builtin_memcpy (&result, p, sizeof(int16_t)); 223 decoded = result; 224 p += sizeof(int16_t); 225 break; 226 } 227 case DW_EH_PE_udata2: 228 { 229 uint16_t result; 230 __builtin_memcpy (&result, p, sizeof(uint16_t)); 231 decoded = result; 232 p += sizeof(uint16_t); 233 break; 234 } 235 case DW_EH_PE_sdata4: 236 { 237 int32_t result; 238 __builtin_memcpy (&result, p, sizeof(int32_t)); 239 decoded = result; 240 p += sizeof(int32_t); 241 break; 242 } 243 case DW_EH_PE_udata4: 244 { 245 uint32_t result; 246 __builtin_memcpy (&result, p, sizeof(uint32_t)); 247 decoded = result; 248 p += sizeof(uint32_t); 249 break; 250 } 251 case DW_EH_PE_sdata8: 252 { 253 int64_t result; 254 __builtin_memcpy (&result, p, sizeof(int64_t)); 255 decoded = result; 256 p += sizeof(int64_t); 257 break; 258 } 259 case DW_EH_PE_udata8: 260 { 261 uint64_t result; 262 __builtin_memcpy (&result, p, sizeof(uint64_t)); 263 decoded = result; 264 p += sizeof(uint64_t); 265 break; 266 } 267 case DW_EH_PE_uleb128: 268 { 269 _uleb128_t value; 270 p = read_uleb128 (p, &value); 271 decoded = (_Unwind_Internal_Ptr)value; 272 break; 273 } 274 case DW_EH_PE_sleb128: 275 { 276 _sleb128_t value; 277 p = read_sleb128 (p, &value); 278 decoded = (_Unwind_Internal_Ptr)value; 279 break; 280 } 281 case DW_EH_PE_absptr: 282 __builtin_memcpy (&decoded, (const void *)p, sizeof(const void*)); 283 p += sizeof(void *); 284 break; 285 default: 286 abort (); 287 } 288 289 if (decoded == 0) 290 { 291 *val = decoded; 292 return p; 293 } 294 295 if ((encoding & 0x70) == DW_EH_PE_pcrel) 296 decoded += ((_Unwind_Internal_Ptr)origp); 297 else 298 decoded += base; 299 300 if ((encoding & DW_EH_PE_indirect) != 0) 301 decoded = *(_Unwind_Internal_Ptr *)decoded; 302 } 303 *val = decoded; 304 return p; 305 } 306 307 static inline int 308 value_size (uint8_t encoding) 309 { 310 switch (encoding & 0x0f) 311 { 312 case DW_EH_PE_sdata2: 313 case DW_EH_PE_udata2: 314 return 2; 315 case DW_EH_PE_sdata4: 316 case DW_EH_PE_udata4: 317 return 4; 318 case DW_EH_PE_sdata8: 319 case DW_EH_PE_udata8: 320 return 8; 321 case DW_EH_PE_absptr: 322 return sizeof(uintptr); 323 default: 324 break; 325 } 326 abort (); 327 } 328 329 /* The rest of this code is really similar to gcc/unwind-c.c and 330 libjava/exception.cc. */ 331 332 typedef struct 333 { 334 _Unwind_Ptr Start; 335 _Unwind_Ptr LPStart; 336 _Unwind_Ptr ttype_base; 337 const unsigned char *TType; 338 const unsigned char *action_table; 339 unsigned char ttype_encoding; 340 unsigned char call_site_encoding; 341 } lsda_header_info; 342 343 static const unsigned char * 344 parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p, 345 lsda_header_info *info) 346 { 347 _uleb128_t tmp; 348 unsigned char lpstart_encoding; 349 350 info->Start = (context ? _Unwind_GetRegionStart (context) : 0); 351 352 /* Find @LPStart, the base to which landing pad offsets are relative. */ 353 lpstart_encoding = *p++; 354 if (lpstart_encoding != DW_EH_PE_omit) 355 p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart); 356 else 357 info->LPStart = info->Start; 358 359 /* Find @TType, the base of the handler and exception spec type data. */ 360 info->ttype_encoding = *p++; 361 if (info->ttype_encoding != DW_EH_PE_omit) 362 { 363 p = read_uleb128 (p, &tmp); 364 info->TType = p + tmp; 365 } 366 else 367 info->TType = 0; 368 369 /* The encoding and length of the call-site table; the action table 370 immediately follows. */ 371 info->call_site_encoding = *p++; 372 p = read_uleb128 (p, &tmp); 373 info->action_table = p + tmp; 374 375 return p; 376 } 377 378 /* The personality function is invoked when unwinding the stack due to 379 a panic. Its job is to find the cleanup and exception handlers to 380 run. We can't split the stack here, because we won't be able to 381 unwind from that split. */ 382 383 #ifdef __ARM_EABI_UNWINDER__ 384 /* ARM EABI personality routines must also unwind the stack. */ 385 #define CONTINUE_UNWINDING \ 386 do \ 387 { \ 388 if (__gnu_unwind_frame (ue_header, context) != _URC_OK) \ 389 return _URC_FAILURE; \ 390 return _URC_CONTINUE_UNWIND; \ 391 } \ 392 while (0) 393 #else 394 #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND 395 #endif 396 397 #ifdef __ARM_EABI_UNWINDER__ 398 #define STOP_UNWINDING _URC_FAILURE 399 #else 400 #define STOP_UNWINDING _URC_NORMAL_STOP 401 #endif 402 403 #ifdef __USING_SJLJ_EXCEPTIONS__ 404 #define PERSONALITY_FUNCTION __gccgo_personality_sj0 405 #define __builtin_eh_return_data_regno(x) x 406 #else 407 #define PERSONALITY_FUNCTION __gccgo_personality_v0 408 #endif 409 410 #ifdef __ARM_EABI_UNWINDER__ 411 _Unwind_Reason_Code 412 PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *, 413 struct _Unwind_Context *) 414 __attribute__ ((no_split_stack, flatten, target ("general-regs-only"))); 415 416 _Unwind_Reason_Code 417 PERSONALITY_FUNCTION (_Unwind_State state, 418 struct _Unwind_Exception * ue_header, 419 struct _Unwind_Context * context) 420 #else 421 _Unwind_Reason_Code 422 PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class, 423 struct _Unwind_Exception *, struct _Unwind_Context *) 424 __attribute__ ((no_split_stack, flatten)); 425 426 _Unwind_Reason_Code 427 PERSONALITY_FUNCTION (int version, 428 _Unwind_Action actions, 429 _Unwind_Exception_Class exception_class, 430 struct _Unwind_Exception *ue_header, 431 struct _Unwind_Context *context) 432 #endif 433 { 434 lsda_header_info info; 435 const unsigned char *language_specific_data, *p, *action_record; 436 _Unwind_Ptr landing_pad, ip; 437 int ip_before_insn = 0; 438 _Bool is_foreign; 439 G *g; 440 441 #ifdef __ARM_EABI_UNWINDER__ 442 _Unwind_Action actions; 443 444 switch (state & _US_ACTION_MASK) 445 { 446 case _US_VIRTUAL_UNWIND_FRAME: 447 if (state & _UA_FORCE_UNWIND) 448 /* We are called from _Unwind_Backtrace. No handler to run. */ 449 CONTINUE_UNWINDING; 450 actions = _UA_SEARCH_PHASE; 451 break; 452 453 case _US_UNWIND_FRAME_STARTING: 454 actions = _UA_CLEANUP_PHASE; 455 if (!(state & _US_FORCE_UNWIND) 456 && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13)) 457 actions |= _UA_HANDLER_FRAME; 458 break; 459 460 case _US_UNWIND_FRAME_RESUME: 461 CONTINUE_UNWINDING; 462 break; 463 464 default: 465 abort(); 466 } 467 actions |= state & _US_FORCE_UNWIND; 468 469 is_foreign = 0; 470 471 /* The dwarf unwinder assumes the context structure holds things like the 472 function and LSDA pointers. The ARM implementation caches these in 473 the exception header (UCB). To avoid rewriting everything we make the 474 virtual IP register point at the UCB. */ 475 ip = (_Unwind_Ptr) ue_header; 476 _Unwind_SetGR (context, 12, ip); 477 #else 478 if (version != 1) 479 return _URC_FATAL_PHASE1_ERROR; 480 481 is_foreign = exception_class != __go_exception_class; 482 #endif 483 484 language_specific_data = (const unsigned char *) 485 _Unwind_GetLanguageSpecificData (context); 486 487 /* If no LSDA, then there are no handlers or cleanups. */ 488 if (! language_specific_data) 489 CONTINUE_UNWINDING; 490 491 /* Parse the LSDA header. */ 492 p = parse_lsda_header (context, language_specific_data, &info); 493 #ifdef HAVE_GETIPINFO 494 ip = _Unwind_GetIPInfo (context, &ip_before_insn); 495 #else 496 ip = _Unwind_GetIP (context); 497 #endif 498 if (! ip_before_insn) 499 --ip; 500 landing_pad = 0; 501 action_record = NULL; 502 503 #ifdef __USING_SJLJ_EXCEPTIONS__ 504 /* The given "IP" is an index into the call-site table, with two 505 exceptions -- -1 means no-action, and 0 means terminate. But 506 since we're using uleb128 values, we've not got random access 507 to the array. */ 508 if ((int) ip <= 0) 509 return _URC_CONTINUE_UNWIND; 510 else 511 { 512 _uleb128_t cs_lp, cs_action; 513 do 514 { 515 p = read_uleb128 (p, &cs_lp); 516 p = read_uleb128 (p, &cs_action); 517 } 518 while (--ip); 519 520 /* Can never have null landing pad for sjlj -- that would have 521 been indicated by a -1 call site index. */ 522 landing_pad = (_Unwind_Ptr)cs_lp + 1; 523 if (cs_action) 524 action_record = info.action_table + cs_action - 1; 525 goto found_something; 526 } 527 #else 528 /* Search the call-site table for the action associated with this IP. */ 529 while (p < info.action_table) 530 { 531 _Unwind_Ptr cs_start, cs_len, cs_lp; 532 _uleb128_t cs_action; 533 534 /* Note that all call-site encodings are "absolute" displacements. */ 535 p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); 536 p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); 537 p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); 538 p = read_uleb128 (p, &cs_action); 539 540 /* The table is sorted, so if we've passed the ip, stop. */ 541 if (ip < info.Start + cs_start) 542 p = info.action_table; 543 else if (ip < info.Start + cs_start + cs_len) 544 { 545 if (cs_lp) 546 landing_pad = info.LPStart + cs_lp; 547 if (cs_action) 548 action_record = info.action_table + cs_action - 1; 549 goto found_something; 550 } 551 } 552 #endif 553 554 /* IP is not in table. No associated cleanups. */ 555 CONTINUE_UNWINDING; 556 557 found_something: 558 if (landing_pad == 0) 559 { 560 /* IP is present, but has a null landing pad. 561 No handler to be run. */ 562 CONTINUE_UNWINDING; 563 } 564 565 if (actions & _UA_SEARCH_PHASE) 566 { 567 if (action_record == 0) 568 { 569 /* This indicates a cleanup rather than an exception 570 handler. */ 571 CONTINUE_UNWINDING; 572 } 573 574 return _URC_HANDLER_FOUND; 575 } 576 577 /* It's possible for g to be NULL here for an exception thrown by a 578 language other than Go. */ 579 g = runtime_g (); 580 if (g == NULL) 581 { 582 if (!is_foreign) 583 abort (); 584 } 585 else 586 { 587 g->exception = ue_header; 588 g->isforeign = is_foreign; 589 } 590 591 _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), 592 (_Unwind_Ptr) ue_header); 593 _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0); 594 _Unwind_SetIP (context, landing_pad); 595 return _URC_INSTALL_CONTEXT; 596 } 597 598 // A dummy personality function, which doesn't capture any exception 599 // and simply passes by. This is used for functions that don't 600 // capture exceptions but need LSDA for stack maps. 601 _Unwind_Reason_Code 602 __gccgo_personality_dummy (int, _Unwind_Action, _Unwind_Exception_Class, 603 struct _Unwind_Exception *, struct _Unwind_Context *) 604 __attribute__ ((no_split_stack)); 605 606 _Unwind_Reason_Code 607 #ifdef __ARM_EABI_UNWINDER__ 608 __attribute__ ((target ("general-regs-only"))) 609 #endif 610 __gccgo_personality_dummy (int version __attribute__ ((unused)), 611 _Unwind_Action actions __attribute__ ((unused)), 612 _Unwind_Exception_Class exception_class __attribute__ ((unused)), 613 struct _Unwind_Exception *ue_header __attribute__ ((unused)), 614 struct _Unwind_Context *context __attribute__ ((unused))) 615 { 616 CONTINUE_UNWINDING; 617 } 618 619 // A sentinel value for Go functions. 620 // A function is a Go function if it has LSDA, which has type info, 621 // and the first (dummy) landing pad's type info is a pointer to 622 // this value. 623 #define GO_FUNC_SENTINEL ((uint64)'G' | ((uint64)'O'<<8) | \ 624 ((uint64)'.'<<16) | ((uint64)'.'<<24) | \ 625 ((uint64)'F'<<32) | ((uint64)'U'<<40) | \ 626 ((uint64)'N'<<48) | ((uint64)'C'<<56)) 627 628 struct _stackmap { 629 uint32 len; 630 uint8 data[1]; // variabe length 631 }; 632 633 extern void 634 runtime_scanstackblockwithmap (uintptr ip, uintptr sp, uintptr size, uint8 *ptrmask, void* gcw) 635 __asm__ (GOSYM_PREFIX "runtime.scanstackblockwithmap"); 636 637 #define FOUND 0 638 #define NOTFOUND_OK 1 639 #define NOTFOUND_BAD 2 640 641 // Helper function to search for stack maps in the unwinding records of a frame. 642 // If found, populate ip, sp, and stackmap. Returns the #define'd values above. 643 static int 644 findstackmaps (struct _Unwind_Context *context, _Unwind_Ptr *ip, _Unwind_Ptr *sp, struct _stackmap **stackmap) 645 { 646 lsda_header_info info; 647 const unsigned char *language_specific_data, *p, *action_record; 648 bool first; 649 struct _stackmap *stackmap1; 650 _Unwind_Ptr ip1; 651 int ip_before_insn = 0; 652 _sleb128_t index; 653 int size; 654 655 #ifdef HAVE_GETIPINFO 656 ip1 = _Unwind_GetIPInfo (context, &ip_before_insn); 657 #else 658 ip1 = _Unwind_GetIP (context); 659 #endif 660 if (! ip_before_insn) 661 --ip1; 662 663 if (ip != NULL) 664 *ip = ip1; 665 if (sp != NULL) 666 *sp = _Unwind_GetCFA (context); 667 668 #ifdef __ARM_EABI_UNWINDER__ 669 { 670 _Unwind_Control_Block *ucbp; 671 ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, 12); 672 if (*ucbp->pr_cache.ehtp & (1u << 31)) 673 // The "compact" model is used, with one of the predefined 674 // personality functions. It doesn't have standard LSDA. 675 return NOTFOUND_OK; 676 } 677 #endif 678 679 language_specific_data = (const unsigned char *) 680 _Unwind_GetLanguageSpecificData (context); 681 682 /* If no LSDA, then there is no stack maps. */ 683 if (! language_specific_data) 684 return NOTFOUND_OK; 685 686 p = parse_lsda_header (context, language_specific_data, &info); 687 688 if (info.TType == NULL) 689 return NOTFOUND_OK; 690 691 size = value_size (info.ttype_encoding); 692 693 action_record = NULL; 694 first = true; 695 696 /* Search the call-site table for the action associated with this IP. */ 697 while (p < info.action_table) 698 { 699 _Unwind_Ptr cs_start, cs_len, cs_lp; 700 _uleb128_t cs_action; 701 702 /* Note that all call-site encodings are "absolute" displacements. */ 703 p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); 704 p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); 705 p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); 706 p = read_uleb128 (p, &cs_action); 707 708 if (first) 709 { 710 // For a Go function, the first entry points to the sentinel value. 711 // Check this here. 712 const unsigned char *p1, *action1; 713 uint64 *x; 714 715 if (!cs_action) 716 return NOTFOUND_OK; 717 718 action1 = info.action_table + cs_action - 1; 719 read_sleb128 (action1, &index); 720 p1 = info.TType - index*size; 721 read_encoded_value (context, info.ttype_encoding, p1, (_Unwind_Ptr*)&x); 722 if (x == NULL || *x != GO_FUNC_SENTINEL) 723 return NOTFOUND_OK; 724 725 first = false; 726 continue; 727 } 728 729 /* The table is sorted, so if we've passed the ip, stop. */ 730 if (ip1 < info.Start + cs_start) 731 return NOTFOUND_BAD; 732 else if (ip1 < info.Start + cs_start + cs_len) 733 { 734 if (cs_action) 735 action_record = info.action_table + cs_action - 1; 736 break; 737 } 738 } 739 740 if (action_record == NULL) 741 return NOTFOUND_BAD; 742 743 read_sleb128 (action_record, &index); 744 p = info.TType - index*size; 745 read_encoded_value (context, info.ttype_encoding, p, (_Unwind_Ptr*)&stackmap1); 746 if (stackmap1 == NULL) 747 return NOTFOUND_BAD; 748 749 if (stackmap != NULL) 750 *stackmap = stackmap1; 751 return FOUND; 752 } 753 754 struct scanstate { 755 void* gcw; // the GC worker, passed into scanstackwithmap_callback 756 uintptr lastsp; // the last (outermost) SP of Go function seen in a traceback, set by the callback 757 }; 758 759 // Callback function to scan a stack frame with stack maps. 760 // It skips non-Go functions. 761 static _Unwind_Reason_Code 762 scanstackwithmap_callback (struct _Unwind_Context *context, void *arg) 763 { 764 struct _stackmap *stackmap; 765 _Unwind_Ptr ip, sp; 766 G* gp; 767 struct scanstate* state = (struct scanstate*) arg; 768 void *gcw; 769 770 gp = runtime_g (); 771 gcw = state->gcw; 772 773 switch (findstackmaps (context, &ip, &sp, &stackmap)) 774 { 775 case NOTFOUND_OK: 776 // Not a Go function. Skip this frame. 777 return _URC_NO_REASON; 778 case NOTFOUND_BAD: 779 { 780 // No stack map found. 781 // If we're scanning from the signal stack, the goroutine 782 // may be not stopped at a safepoint. Allow this case. 783 if (gp != gp->m->gsignal) 784 { 785 // TODO: print gp, pc, sp 786 runtime_throw ("no stack map"); 787 } 788 return STOP_UNWINDING; 789 } 790 case FOUND: 791 break; 792 default: 793 abort (); 794 } 795 796 state->lastsp = sp; 797 runtime_scanstackblockwithmap (ip, sp, (uintptr)(stackmap->len) * sizeof(uintptr), stackmap->data, gcw); 798 799 return _URC_NO_REASON; 800 } 801 802 // Scan the stack with stack maps. Return whether the scan 803 // succeeded. 804 bool 805 scanstackwithmap (void *gcw) 806 { 807 _Unwind_Reason_Code code; 808 bool ret; 809 struct scanstate state; 810 G* gp; 811 G* curg; 812 813 state.gcw = gcw; 814 state.lastsp = 0; 815 gp = runtime_g (); 816 curg = gp->m->curg; 817 818 runtime_xadd (&__go_runtime_in_callers, 1); 819 code = _Unwind_Backtrace (scanstackwithmap_callback, (void*)&state); 820 runtime_xadd (&__go_runtime_in_callers, -1); 821 ret = (code == _URC_END_OF_STACK); 822 if (ret && gp == gp->m->gsignal) 823 { 824 // For signal-triggered scan, the unwinder may not be able to unwind 825 // the whole stack while it still reports _URC_END_OF_STACK (e.g. 826 // signal is delivered in vdso). Check that we actually reached the 827 // the end of the stack, that is, the SP on entry. 828 if (state.lastsp != curg->entrysp) 829 ret = false; 830 } 831 return ret; 832 } 833 834 // Returns whether stack map is enabled. 835 bool 836 usestackmaps () 837 { 838 return runtime_usestackmaps; 839 } 840 841 // Callback function to probe if a stack frame has stack maps. 842 static _Unwind_Reason_Code 843 probestackmaps_callback (struct _Unwind_Context *context, 844 void *arg __attribute__ ((unused))) 845 { 846 switch (findstackmaps (context, NULL, NULL, NULL)) 847 { 848 case NOTFOUND_OK: 849 case NOTFOUND_BAD: 850 return _URC_NO_REASON; 851 case FOUND: 852 break; 853 default: 854 abort (); 855 } 856 857 // Found a stack map. No need to keep unwinding. 858 runtime_usestackmaps = true; 859 return STOP_UNWINDING; 860 } 861 862 // Try to find a stack map, store the result in global variable runtime_usestackmaps. 863 // Called in start-up time from Go code, so there is a Go frame on the stack. 864 bool 865 probestackmaps () 866 { 867 runtime_usestackmaps = false; 868 _Unwind_Backtrace (probestackmaps_callback, NULL); 869 return runtime_usestackmaps; 870 }