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
rethrowException()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
unwindExceptionSize()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
throwException()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
encoded_value_base(uint8_t encoding,struct _Unwind_Context * context)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 *
read_uleb128(const uint8_t * p,_uleb128_t * val)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 *
read_sleb128(const uint8_t * p,_sleb128_t * val)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 *
read_encoded_value(struct _Unwind_Context * context,uint8_t encoding,const uint8_t * p,_Unwind_Ptr * val)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
value_size(uint8_t encoding)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 *
parse_lsda_header(struct _Unwind_Context * context,const unsigned char * p,lsda_header_info * info)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
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)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
__gccgo_personality_dummy(int version,_Unwind_Action actions,_Unwind_Exception_Class exception_class,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)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
findstackmaps(struct _Unwind_Context * context,_Unwind_Ptr * ip,_Unwind_Ptr * sp,struct _stackmap ** stackmap)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
scanstackwithmap_callback(struct _Unwind_Context * context,void * arg)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
scanstackwithmap(void * gcw)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
usestackmaps()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
probestackmaps_callback(struct _Unwind_Context * context,void * arg)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
probestackmaps()869 probestackmaps ()
870 {
871   runtime_usestackmaps = false;
872   _Unwind_Backtrace (probestackmaps_callback, NULL);
873   return runtime_usestackmaps;
874 }
875