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