github.com/golang/gofrontend@v0.0.0-20240429183944-60f985a78526/libgo/runtime/go-unwind.c (about)

     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  }