github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/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  
    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
    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
   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
   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 *
   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 *
   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 *
   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
   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 *
   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
   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
   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
   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
   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
   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
   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
   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
   865  probestackmaps ()
   866  {
   867    runtime_usestackmaps = false;
   868    _Unwind_Backtrace (probestackmaps_callback, NULL);
   869    return runtime_usestackmaps;
   870  }