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. */
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' };
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');
54 /* Rethrow an exception. */
56 void rethrowException (void) __asm__(GOSYM_PREFIX
"runtime.rethrowException");
61 struct _Unwind_Exception
*hdr
;
62 _Unwind_Reason_Code reason
;
64 hdr
= (struct _Unwind_Exception
*) runtime_g()->exception
;
66 #ifdef __USING_SJLJ_EXCEPTIONS__
67 reason
= _Unwind_SjLj_Resume_or_Rethrow (hdr
);
69 #if defined(_LIBUNWIND_STD_ABI)
70 reason
= _Unwind_RaiseException (hdr
);
72 reason
= _Unwind_Resume_or_Rethrow (hdr
);
76 /* Rethrowing the exception should not return. */
77 runtime_printf ("failed to rethrow unwind exception (reason=%d)\n", reason
);
81 /* Return the size of the type that holds an exception header, so that
82 it can be allocated by Go code. */
84 uintptr
unwindExceptionSize(void)
85 __asm__ (GOSYM_PREFIX
"runtime.unwindExceptionSize");
88 unwindExceptionSize ()
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
);
100 /* Throw an exception. This is called with g->exception pointing to
101 an uninitialized _Unwind_Exception instance. */
103 void throwException (void) __asm__(GOSYM_PREFIX
"runtime.throwException");
108 struct _Unwind_Exception
*hdr
;
110 _Unwind_Reason_Code reason
;
112 hdr
= (struct _Unwind_Exception
*)runtime_g ()->exception
;
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)));
120 __builtin_memcpy (&hdr
->exception_class
, &__go_exception_class
,
121 sizeof hdr
->exception_class
);
122 hdr
->exception_cleanup
= NULL
;
124 #ifdef __USING_SJLJ_EXCEPTIONS__
125 reason
= _Unwind_SjLj_RaiseException (hdr
);
127 reason
= _Unwind_RaiseException (hdr
);
130 /* Raising an exception should not return. */
131 runtime_printf ("failed to throw unwind exception (reason=%d)\n", reason
);
135 static inline _Unwind_Ptr
136 encoded_value_base (uint8_t encoding
, struct _Unwind_Context
*context
)
138 if (encoding
== DW_EH_PE_omit
)
140 switch (encoding
& 0x70)
142 case DW_EH_PE_absptr
:
144 case DW_EH_PE_aligned
:
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
);
156 /* Read an unsigned leb128 value. */
158 static inline const uint8_t *
159 read_uleb128 (const uint8_t *p
, _uleb128_t
*val
)
161 unsigned int shift
= 0;
162 _uleb128_t result
= 0;
168 result
|= ((_uleb128_t
)byte
& 0x7f) << shift
;
177 /* Similar, but read a signed leb128 value. */
179 static inline const uint8_t *
180 read_sleb128 (const uint8_t *p
, _sleb128_t
*val
)
182 unsigned int shift
= 0;
183 _uleb128_t result
= 0;
189 result
|= ((_uleb128_t
)byte
& 0x7f) << shift
;
195 if (shift
< (8 * sizeof(result
)) && (byte
& 0x40) != 0)
196 result
|= (((_uleb128_t
)~0) << shift
);
198 *val
= (_sleb128_t
)result
;
202 #define ROUND_UP_TO_PVB(x) (x + sizeof(void *) - 1) &- sizeof(void *)
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
)
208 _Unwind_Ptr base
= encoded_value_base (encoding
, context
);
209 _Unwind_Internal_Ptr decoded
= 0;
210 const uint8_t *origp
= p
;
212 if (encoding
== DW_EH_PE_aligned
)
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 *));
221 switch (encoding
& 0x0f)
223 case DW_EH_PE_sdata2
:
226 __builtin_memcpy (&result
, p
, sizeof(int16_t));
228 p
+= sizeof(int16_t);
231 case DW_EH_PE_udata2
:
234 __builtin_memcpy (&result
, p
, sizeof(uint16_t));
236 p
+= sizeof(uint16_t);
239 case DW_EH_PE_sdata4
:
242 __builtin_memcpy (&result
, p
, sizeof(int32_t));
244 p
+= sizeof(int32_t);
247 case DW_EH_PE_udata4
:
250 __builtin_memcpy (&result
, p
, sizeof(uint32_t));
252 p
+= sizeof(uint32_t);
255 case DW_EH_PE_sdata8
:
258 __builtin_memcpy (&result
, p
, sizeof(int64_t));
260 p
+= sizeof(int64_t);
263 case DW_EH_PE_udata8
:
266 __builtin_memcpy (&result
, p
, sizeof(uint64_t));
268 p
+= sizeof(uint64_t);
271 case DW_EH_PE_uleb128
:
274 p
= read_uleb128 (p
, &value
);
275 decoded
= (_Unwind_Internal_Ptr
)value
;
278 case DW_EH_PE_sleb128
:
281 p
= read_sleb128 (p
, &value
);
282 decoded
= (_Unwind_Internal_Ptr
)value
;
285 case DW_EH_PE_absptr
:
286 __builtin_memcpy (&decoded
, (const void *)p
, sizeof(const void*));
299 if ((encoding
& 0x70) == DW_EH_PE_pcrel
)
300 decoded
+= ((_Unwind_Internal_Ptr
)origp
);
304 if ((encoding
& DW_EH_PE_indirect
) != 0)
305 decoded
= *(_Unwind_Internal_Ptr
*)decoded
;
312 value_size (uint8_t encoding
)
314 switch (encoding
& 0x0f)
316 case DW_EH_PE_sdata2
:
317 case DW_EH_PE_udata2
:
319 case DW_EH_PE_sdata4
:
320 case DW_EH_PE_udata4
:
322 case DW_EH_PE_sdata8
:
323 case DW_EH_PE_udata8
:
325 case DW_EH_PE_absptr
:
326 return sizeof(uintptr
);
333 /* The rest of this code is really similar to gcc/unwind-c.c and
334 libjava/exception.cc. */
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
;
347 static const unsigned char *
348 parse_lsda_header (struct _Unwind_Context
*context
, const unsigned char *p
,
349 lsda_header_info
*info
)
352 unsigned char lpstart_encoding
;
354 info
->Start
= (context
? _Unwind_GetRegionStart (context
) : 0);
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
);
361 info
->LPStart
= info
->Start
;
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
)
367 p
= read_uleb128 (p
, &tmp
);
368 info
->TType
= p
+ tmp
;
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
;
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. */
387 #ifdef __ARM_EABI_UNWINDER__
388 /* ARM EABI personality routines must also unwind the stack. */
389 #define CONTINUE_UNWINDING \
392 if (__gnu_unwind_frame (ue_header, context) != _URC_OK) \
393 return _URC_FAILURE; \
394 return _URC_CONTINUE_UNWIND; \
398 #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
401 #ifdef __ARM_EABI_UNWINDER__
402 #define STOP_UNWINDING _URC_FAILURE
404 #define STOP_UNWINDING _URC_NORMAL_STOP
407 #ifdef __USING_SJLJ_EXCEPTIONS__
408 #define PERSONALITY_FUNCTION __gccgo_personality_sj0
409 #define __builtin_eh_return_data_regno(x) x
411 #define PERSONALITY_FUNCTION __gccgo_personality_v0
414 #ifdef __ARM_EABI_UNWINDER__
416 PERSONALITY_FUNCTION (_Unwind_State
, struct _Unwind_Exception
*,
417 struct _Unwind_Context
*)
418 __attribute__ ((no_split_stack
, flatten
, target ("general-regs-only")));
421 PERSONALITY_FUNCTION (_Unwind_State state
,
422 struct _Unwind_Exception
* ue_header
,
423 struct _Unwind_Context
* context
)
426 PERSONALITY_FUNCTION (int, _Unwind_Action
, _Unwind_Exception_Class
,
427 struct _Unwind_Exception
*, struct _Unwind_Context
*)
428 __attribute__ ((no_split_stack
, flatten
));
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
)
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;
445 #ifdef __ARM_EABI_UNWINDER__
446 _Unwind_Action actions
;
448 switch (state
& _US_ACTION_MASK
)
450 case _US_VIRTUAL_UNWIND_FRAME
:
451 if (state
& _UA_FORCE_UNWIND
)
452 /* We are called from _Unwind_Backtrace. No handler to run. */
454 actions
= _UA_SEARCH_PHASE
;
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
;
464 case _US_UNWIND_FRAME_RESUME
:
471 actions
|= state
& _US_FORCE_UNWIND
;
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
);
483 return _URC_FATAL_PHASE1_ERROR
;
485 is_foreign
= exception_class
!= __go_exception_class
;
488 language_specific_data
= (const unsigned char *)
489 _Unwind_GetLanguageSpecificData (context
);
491 /* If no LSDA, then there are no handlers or cleanups. */
492 if (! language_specific_data
)
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
);
500 ip
= _Unwind_GetIP (context
);
502 if (! ip_before_insn
)
505 action_record
= NULL
;
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
513 return _URC_CONTINUE_UNWIND
;
516 _uleb128_t cs_lp
, cs_action
;
519 p
= read_uleb128 (p
, &cs_lp
);
520 p
= read_uleb128 (p
, &cs_action
);
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;
528 action_record
= info
.action_table
+ cs_action
- 1;
529 goto found_something
;
532 /* Search the call-site table for the action associated with this IP. */
533 while (p
< info
.action_table
)
535 _Unwind_Ptr cs_start
, cs_len
, cs_lp
;
536 _uleb128_t cs_action
;
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
);
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
)
550 landing_pad
= info
.LPStart
+ cs_lp
;
552 action_record
= info
.action_table
+ cs_action
- 1;
553 goto found_something
;
558 /* IP is not in table. No associated cleanups. */
562 if (landing_pad
== 0)
564 /* IP is present, but has a null landing pad.
565 No handler to be run. */
569 if (actions
& _UA_SEARCH_PHASE
)
571 if (action_record
== 0)
573 /* This indicates a cleanup rather than an exception
578 return _URC_HANDLER_FOUND
;
581 /* It's possible for g to be NULL here for an exception thrown by a
582 language other than Go. */
591 g
->exception
= ue_header
;
592 g
->isforeign
= is_foreign
;
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
;
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.
606 __gccgo_personality_dummy (int, _Unwind_Action
, _Unwind_Exception_Class
,
607 struct _Unwind_Exception
*, struct _Unwind_Context
*)
608 __attribute__ ((no_split_stack
));
611 #ifdef __ARM_EABI_UNWINDER__
612 __attribute__ ((target ("general-regs-only")))
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
)))
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
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))
634 uint8 data
[1]; // variabe length
638 runtime_scanstackblockwithmap (uintptr ip
, uintptr sp
, uintptr size
, uint8
*ptrmask
, void* gcw
)
639 __asm__ (GOSYM_PREFIX
"runtime.scanstackblockwithmap");
642 #define NOTFOUND_OK 1
643 #define NOTFOUND_BAD 2
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.
648 findstackmaps (struct _Unwind_Context
*context
, _Unwind_Ptr
*ip
, _Unwind_Ptr
*sp
, struct _stackmap
**stackmap
)
650 lsda_header_info info
;
651 const unsigned char *language_specific_data
, *p
, *action_record
;
653 struct _stackmap
*stackmap1
;
655 int ip_before_insn
= 0;
659 #ifdef HAVE_GETIPINFO
660 ip1
= _Unwind_GetIPInfo (context
, &ip_before_insn
);
662 ip1
= _Unwind_GetIP (context
);
664 if (! ip_before_insn
)
670 *sp
= _Unwind_GetCFA (context
);
672 #ifdef __ARM_EABI_UNWINDER__
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.
683 language_specific_data
= (const unsigned char *)
684 _Unwind_GetLanguageSpecificData (context
);
686 /* If no LSDA, then there is no stack maps. */
687 if (! language_specific_data
)
690 p
= parse_lsda_header (context
, language_specific_data
, &info
);
692 if (info
.TType
== NULL
)
695 size
= value_size (info
.ttype_encoding
);
697 action_record
= NULL
;
700 /* Search the call-site table for the action associated with this IP. */
701 while (p
< info
.action_table
)
703 _Unwind_Ptr cs_start
, cs_len
, cs_lp
;
704 _uleb128_t cs_action
;
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
);
714 // For a Go function, the first entry points to the sentinel value.
716 const unsigned char *p1
, *action1
;
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
)
733 /* The table is sorted, so if we've passed the ip, stop. */
734 if (ip1
< info
.Start
+ cs_start
)
736 else if (ip1
< info
.Start
+ cs_start
+ cs_len
)
739 action_record
= info
.action_table
+ cs_action
- 1;
744 if (action_record
== NULL
)
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
)
753 if (stackmap
!= NULL
)
754 *stackmap
= stackmap1
;
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
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
)
768 struct _stackmap
*stackmap
;
771 struct scanstate
* state
= (struct scanstate
*) arg
;
777 switch (findstackmaps (context
, &ip
, &sp
, &stackmap
))
780 // Not a Go function. Skip this frame.
781 return _URC_NO_REASON
;
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
)
789 // TODO: print gp, pc, sp
790 runtime_throw ("no stack map");
792 return STOP_UNWINDING
;
801 runtime_scanstackblockwithmap (ip
, sp
, (uintptr
)(stackmap
->len
) * sizeof(uintptr
), stackmap
->data
, gcw
);
803 return _URC_NO_REASON
;
806 // Scan the stack with stack maps. Return whether the scan
809 scanstackwithmap (void *gcw
)
811 _Unwind_Reason_Code code
;
813 struct scanstate state
;
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
)
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
)
838 // Returns whether stack map is enabled.
842 return runtime_usestackmaps
;
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
)))
850 switch (findstackmaps (context
, NULL
, NULL
, NULL
))
854 return _URC_NO_REASON
;
861 // Found a stack map. No need to keep unwinding.
862 runtime_usestackmaps
= true;
863 return STOP_UNWINDING
;
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.
871 runtime_usestackmaps
= false;
872 _Unwind_Backtrace (probestackmaps_callback
, NULL
);
873 return runtime_usestackmaps
;