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