[PR86379] do not use TREE_TYPE for USING_DECL_SCOPE
[official-gcc.git] / libgo / runtime / go-unwind.c
blob158cbd07968efa01d6504b1c2fa96226421dba23
1 /* go-unwind.c -- unwind the stack for panic/recover.
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. */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <unistd.h>
12 #include "unwind.h"
14 #include "runtime.h"
16 /* These constants are documented here:
17 https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/dwarfext.html
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
37 /* The code for a Go exception. */
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
54 /* Rethrow an exception. */
56 void rethrowException (void) __asm__(GOSYM_PREFIX "runtime.rethrowException");
58 void
59 rethrowException ()
61 struct _Unwind_Exception *hdr;
63 hdr = (struct _Unwind_Exception *) runtime_g()->exception;
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
75 /* Rethrowing the exception should not return. */
76 abort();
79 /* Return the size of the type that holds an exception header, so that
80 it can be allocated by Go code. */
82 uintptr unwindExceptionSize(void)
83 __asm__ (GOSYM_PREFIX "runtime.unwindExceptionSize");
85 uintptr
86 unwindExceptionSize ()
88 uintptr ret, align;
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;
98 /* Throw an exception. This is called with g->exception pointing to
99 an uninitialized _Unwind_Exception instance. */
101 void throwException (void) __asm__(GOSYM_PREFIX "runtime.throwException");
103 void
104 throwException ()
106 struct _Unwind_Exception *hdr;
107 uintptr align;
109 hdr = (struct _Unwind_Exception *)runtime_g ()->exception;
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)));
117 __builtin_memcpy (&hdr->exception_class, &__go_exception_class,
118 sizeof hdr->exception_class);
119 hdr->exception_cleanup = NULL;
121 #ifdef __USING_SJLJ_EXCEPTIONS__
122 _Unwind_SjLj_RaiseException (hdr);
123 #else
124 _Unwind_RaiseException (hdr);
125 #endif
127 /* Raising an exception should not return. */
128 abort ();
131 static inline _Unwind_Ptr
132 encoded_value_base (uint8_t encoding, struct _Unwind_Context *context)
134 if (encoding == DW_EH_PE_omit)
135 return 0;
136 switch (encoding & 0x70)
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);
149 abort ();
152 /* Read an unsigned leb128 value. */
154 static inline const uint8_t *
155 read_uleb128 (const uint8_t *p, _uleb128_t *val)
157 unsigned int shift = 0;
158 _uleb128_t result = 0;
159 uint8_t byte;
163 byte = *p++;
164 result |= ((_uleb128_t)byte & 0x7f) << shift;
165 shift += 7;
167 while (byte & 0x80);
169 *val = result;
170 return p;
173 /* Similar, but read a signed leb128 value. */
175 static inline const uint8_t *
176 read_sleb128 (const uint8_t *p, _sleb128_t *val)
178 unsigned int shift = 0;
179 _uleb128_t result = 0;
180 uint8_t byte;
184 byte = *p++;
185 result |= ((_uleb128_t)byte & 0x7f) << shift;
186 shift += 7;
188 while (byte & 0x80);
190 /* sign extension */
191 if (shift < (8 * sizeof(result)) && (byte & 0x40) != 0)
192 result |= (((_uleb128_t)~0) << shift);
194 *val = (_sleb128_t)result;
195 return p;
198 #define ROUND_UP_TO_PVB(x) (x + sizeof(void *) - 1) &- sizeof(void *)
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)
204 _Unwind_Ptr base = encoded_value_base (encoding, context);
205 _Unwind_Internal_Ptr decoded = 0;
206 const uint8_t *origp = p;
208 if (encoding == DW_EH_PE_aligned)
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 *));
215 else
217 switch (encoding & 0x0f)
219 case DW_EH_PE_sdata2:
221 int16_t result;
222 __builtin_memcpy (&result, p, sizeof(int16_t));
223 decoded = result;
224 p += sizeof(int16_t);
225 break;
227 case DW_EH_PE_udata2:
229 uint16_t result;
230 __builtin_memcpy (&result, p, sizeof(uint16_t));
231 decoded = result;
232 p += sizeof(uint16_t);
233 break;
235 case DW_EH_PE_sdata4:
237 int32_t result;
238 __builtin_memcpy (&result, p, sizeof(int32_t));
239 decoded = result;
240 p += sizeof(int32_t);
241 break;
243 case DW_EH_PE_udata4:
245 uint32_t result;
246 __builtin_memcpy (&result, p, sizeof(uint32_t));
247 decoded = result;
248 p += sizeof(uint32_t);
249 break;
251 case DW_EH_PE_sdata8:
253 int64_t result;
254 __builtin_memcpy (&result, p, sizeof(int64_t));
255 decoded = result;
256 p += sizeof(int64_t);
257 break;
259 case DW_EH_PE_udata8:
261 uint64_t result;
262 __builtin_memcpy (&result, p, sizeof(uint64_t));
263 decoded = result;
264 p += sizeof(uint64_t);
265 break;
267 case DW_EH_PE_uleb128:
269 _uleb128_t value;
270 p = read_uleb128 (p, &value);
271 decoded = (_Unwind_Internal_Ptr)value;
272 break;
274 case DW_EH_PE_sleb128:
276 _sleb128_t value;
277 p = read_sleb128 (p, &value);
278 decoded = (_Unwind_Internal_Ptr)value;
279 break;
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 ();
289 if (decoded == 0)
291 *val = decoded;
292 return p;
295 if ((encoding & 0x70) == DW_EH_PE_pcrel)
296 decoded += ((_Unwind_Internal_Ptr)origp);
297 else
298 decoded += base;
300 if ((encoding & DW_EH_PE_indirect) != 0)
301 decoded = *(_Unwind_Internal_Ptr *)decoded;
303 *val = decoded;
304 return p;
307 static inline int
308 value_size (uint8_t encoding)
310 switch (encoding & 0x0f)
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;
326 abort ();
329 /* The rest of this code is really similar to gcc/unwind-c.c and
330 libjava/exception.cc. */
332 typedef struct
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;
343 static const unsigned char *
344 parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
345 lsda_header_info *info)
347 _uleb128_t tmp;
348 unsigned char lpstart_encoding;
350 info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
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;
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)
363 p = read_uleb128 (p, &tmp);
364 info->TType = p + tmp;
366 else
367 info->TType = 0;
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;
375 return p;
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. */
383 #ifdef __ARM_EABI_UNWINDER__
384 /* ARM EABI personality routines must also unwind the stack. */
385 #define CONTINUE_UNWINDING \
386 do \
388 if (__gnu_unwind_frame (ue_header, context) != _URC_OK) \
389 return _URC_FAILURE; \
390 return _URC_CONTINUE_UNWIND; \
392 while (0)
393 #else
394 #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
395 #endif
397 #ifdef __ARM_EABI_UNWINDER__
398 #define STOP_UNWINDING _URC_FAILURE
399 #else
400 #define STOP_UNWINDING _URC_NORMAL_STOP
401 #endif
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
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));
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));
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
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;
441 #ifdef __ARM_EABI_UNWINDER__
442 _Unwind_Action actions;
444 switch (state & _US_ACTION_MASK)
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;
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;
460 case _US_UNWIND_FRAME_RESUME:
461 CONTINUE_UNWINDING;
462 break;
464 default:
465 abort();
467 actions |= state & _US_FORCE_UNWIND;
469 is_foreign = 0;
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;
481 is_foreign = exception_class != __go_exception_class;
482 #endif
484 language_specific_data = (const unsigned char *)
485 _Unwind_GetLanguageSpecificData (context);
487 /* If no LSDA, then there are no handlers or cleanups. */
488 if (! language_specific_data)
489 CONTINUE_UNWINDING;
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;
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
512 _uleb128_t cs_lp, cs_action;
515 p = read_uleb128 (p, &cs_lp);
516 p = read_uleb128 (p, &cs_action);
518 while (--ip);
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;
527 #else
528 /* Search the call-site table for the action associated with this IP. */
529 while (p < info.action_table)
531 _Unwind_Ptr cs_start, cs_len, cs_lp;
532 _uleb128_t cs_action;
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);
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)
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;
552 #endif
554 /* IP is not in table. No associated cleanups. */
555 CONTINUE_UNWINDING;
557 found_something:
558 if (landing_pad == 0)
560 /* IP is present, but has a null landing pad.
561 No handler to be run. */
562 CONTINUE_UNWINDING;
565 if (actions & _UA_SEARCH_PHASE)
567 if (action_record == 0)
569 /* This indicates a cleanup rather than an exception
570 handler. */
571 CONTINUE_UNWINDING;
574 return _URC_HANDLER_FOUND;
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)
582 if (!is_foreign)
583 abort ();
585 else
587 g->exception = ue_header;
588 g->isforeign = is_foreign;
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;
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));
606 _Unwind_Reason_Code
607 __gccgo_personality_dummy (int version __attribute__ ((unused)),
608 _Unwind_Action actions __attribute__ ((unused)),
609 _Unwind_Exception_Class exception_class __attribute__ ((unused)),
610 struct _Unwind_Exception *ue_header __attribute__ ((unused)),
611 struct _Unwind_Context *context __attribute__ ((unused)))
613 CONTINUE_UNWINDING;
616 // A sentinel value for Go functions.
617 // A function is a Go function if it has LSDA, which has type info,
618 // and the first (dummy) landing pad's type info is a pointer to
619 // this value.
620 #define GO_FUNC_SENTINEL ((uint64)'G' | ((uint64)'O'<<8) | \
621 ((uint64)'.'<<16) | ((uint64)'.'<<24) | \
622 ((uint64)'F'<<32) | ((uint64)'U'<<40) | \
623 ((uint64)'N'<<48) | ((uint64)'C'<<56))
625 struct _stackmap {
626 uint32 len;
627 uint8 data[1]; // variabe length
630 extern void
631 runtime_scanstackblockwithmap (uintptr ip, uintptr sp, uintptr size, uint8 *ptrmask, void* gcw)
632 __asm__ (GOSYM_PREFIX "runtime.scanstackblockwithmap");
634 #define FOUND 0
635 #define NOTFOUND_OK 1
636 #define NOTFOUND_BAD 2
638 // Helper function to search for stack maps in the unwinding records of a frame.
639 // If found, populate ip, sp, and stackmap. Returns the #define'd values above.
640 static int
641 findstackmaps (struct _Unwind_Context *context, _Unwind_Ptr *ip, _Unwind_Ptr *sp, struct _stackmap **stackmap)
643 lsda_header_info info;
644 const unsigned char *language_specific_data, *p, *action_record;
645 bool first;
646 struct _stackmap *stackmap1;
647 _Unwind_Ptr ip1;
648 int ip_before_insn = 0;
649 _sleb128_t index;
650 int size;
652 #ifdef __ARM_EABI_UNWINDER__
654 _Unwind_Control_Block *ucbp;
655 ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, 12);
656 if (*ucbp->pr_cache.ehtp & (1u << 31))
657 // The "compact" model is used, with one of the predefined
658 // personality functions. It doesn't have standard LSDA.
659 return NOTFOUND_OK;
661 #endif
663 language_specific_data = (const unsigned char *)
664 _Unwind_GetLanguageSpecificData (context);
666 /* If no LSDA, then there is no stack maps. */
667 if (! language_specific_data)
668 return NOTFOUND_OK;
670 p = parse_lsda_header (context, language_specific_data, &info);
672 if (info.TType == NULL)
673 return NOTFOUND_OK;
675 #ifdef HAVE_GETIPINFO
676 ip1 = _Unwind_GetIPInfo (context, &ip_before_insn);
677 #else
678 ip1 = _Unwind_GetIP (context);
679 #endif
680 if (! ip_before_insn)
681 --ip1;
683 size = value_size (info.ttype_encoding);
685 action_record = NULL;
686 first = true;
688 /* Search the call-site table for the action associated with this IP. */
689 while (p < info.action_table)
691 _Unwind_Ptr cs_start, cs_len, cs_lp;
692 _uleb128_t cs_action;
694 /* Note that all call-site encodings are "absolute" displacements. */
695 p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
696 p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
697 p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
698 p = read_uleb128 (p, &cs_action);
700 if (first)
702 // For a Go function, the first entry points to the sentinel value.
703 // Check this here.
704 const unsigned char *p1, *action1;
705 uint64 *x;
707 if (!cs_action)
708 return NOTFOUND_OK;
710 action1 = info.action_table + cs_action - 1;
711 read_sleb128 (action1, &index);
712 p1 = info.TType - index*size;
713 read_encoded_value (context, info.ttype_encoding, p1, (_Unwind_Ptr*)&x);
714 if (x == NULL || *x != GO_FUNC_SENTINEL)
715 return NOTFOUND_OK;
717 first = false;
718 continue;
721 /* The table is sorted, so if we've passed the ip, stop. */
722 if (ip1 < info.Start + cs_start)
723 return NOTFOUND_BAD;
724 else if (ip1 < info.Start + cs_start + cs_len)
726 if (cs_action)
727 action_record = info.action_table + cs_action - 1;
728 break;
732 if (action_record == NULL)
733 return NOTFOUND_BAD;
735 read_sleb128 (action_record, &index);
736 p = info.TType - index*size;
737 read_encoded_value (context, info.ttype_encoding, p, (_Unwind_Ptr*)&stackmap1);
738 if (stackmap1 == NULL)
739 return NOTFOUND_BAD;
741 if (ip != NULL)
742 *ip = ip1;
743 if (sp != NULL)
744 *sp = _Unwind_GetCFA (context);
745 if (stackmap != NULL)
746 *stackmap = stackmap1;
747 return FOUND;
750 // Callback function to scan a stack frame with stack maps.
751 // It skips non-Go functions.
752 static _Unwind_Reason_Code
753 scanstackwithmap_callback (struct _Unwind_Context *context, void *arg)
755 struct _stackmap *stackmap;
756 _Unwind_Ptr ip, sp;
757 G* gp;
758 void *gcw = arg;
760 switch (findstackmaps (context, &ip, &sp, &stackmap))
762 case NOTFOUND_OK:
763 // Not a Go function. Skip this frame.
764 return _URC_NO_REASON;
765 case NOTFOUND_BAD:
767 // No stack map found.
768 // If we're scanning from the signal stack, the goroutine
769 // may be not stopped at a safepoint. Allow this case.
770 gp = runtime_g ();
771 if (gp != gp->m->gsignal)
773 // TODO: print gp, pc, sp
774 runtime_throw ("no stack map");
776 return STOP_UNWINDING;
778 case FOUND:
779 break;
780 default:
781 abort ();
784 runtime_scanstackblockwithmap (ip, sp, (uintptr)(stackmap->len) * sizeof(uintptr), stackmap->data, gcw);
786 return _URC_NO_REASON;
789 // Scan the stack with stack maps. Return whether the scan
790 // succeeded.
791 bool
792 scanstackwithmap (void *gcw)
794 _Unwind_Reason_Code code;
795 runtime_xadd (&__go_runtime_in_callers, 1);
796 code = _Unwind_Backtrace (scanstackwithmap_callback, gcw);
797 runtime_xadd (&__go_runtime_in_callers, -1);
798 return code == _URC_END_OF_STACK;
801 // Returns whether stack map is enabled.
802 bool
803 usestackmaps ()
805 return runtime_usestackmaps;
808 // Callback function to probe if a stack frame has stack maps.
809 static _Unwind_Reason_Code
810 probestackmaps_callback (struct _Unwind_Context *context,
811 void *arg __attribute__ ((unused)))
813 switch (findstackmaps (context, NULL, NULL, NULL))
815 case NOTFOUND_OK:
816 case NOTFOUND_BAD:
817 return _URC_NO_REASON;
818 case FOUND:
819 break;
820 default:
821 abort ();
824 // Found a stack map. No need to keep unwinding.
825 runtime_usestackmaps = true;
826 return STOP_UNWINDING;
829 // Try to find a stack map, store the result in global variable runtime_usestackmaps.
830 // Called in start-up time from Go code, so there is a Go frame on the stack.
831 bool
832 probestackmaps ()
834 runtime_usestackmaps = false;
835 _Unwind_Backtrace (probestackmaps_callback, NULL);
836 return runtime_usestackmaps;