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