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