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 _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
unwindExceptionSize()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
throwException()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
encoded_value_base(uint8_t encoding,struct _Unwind_Context * context)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 *
read_uleb128(const uint8_t * p,_uleb128_t * val)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 *
read_sleb128(const uint8_t * p,_sleb128_t * val)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 *
read_encoded_value(struct _Unwind_Context * context,uint8_t encoding,const uint8_t * p,_Unwind_Ptr * val)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
value_size(uint8_t encoding)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 *
parse_lsda_header(struct _Unwind_Context * context,const unsigned char * p,lsda_header_info * info)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
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)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
__gccgo_personality_dummy(int version,_Unwind_Action actions,_Unwind_Exception_Class exception_class,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)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
findstackmaps(struct _Unwind_Context * context,_Unwind_Ptr * ip,_Unwind_Ptr * sp,struct _stackmap ** stackmap)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
scanstackwithmap_callback(struct _Unwind_Context * context,void * arg)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
scanstackwithmap(void * gcw)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
usestackmaps()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
probestackmaps_callback(struct _Unwind_Context * context,void * arg)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
probestackmaps()869 probestackmaps ()
870 {
871 runtime_usestackmaps = false;
872 _Unwind_Backtrace (probestackmaps_callback, NULL);
873 return runtime_usestackmaps;
874 }
875