1 /* DWARF2 exception handling and frame unwinding for Xtensa.
2    Copyright (C) 1997-2021 Free Software Foundation, Inc.
3 
4    This file is part of GCC.
5 
6    GCC is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    GCC is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15 
16    Under Section 7 of GPL version 3, you are granted additional
17    permissions described in the GCC Runtime Library Exception, version
18    3.1, as published by the Free Software Foundation.
19 
20    You should have received a copy of the GNU General Public License and
21    a copy of the GCC Runtime Library Exception along with this program;
22    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23    <http://www.gnu.org/licenses/>.  */
24 
25 #include "tconfig.h"
26 #include "tsystem.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "libgcc_tm.h"
30 #include "dwarf2.h"
31 #include "unwind.h"
32 #ifdef __USING_SJLJ_EXCEPTIONS__
33 # define NO_SIZE_OF_ENCODED_VALUE
34 #endif
35 #include "unwind-pe.h"
36 #include "unwind-dw2-fde.h"
37 #include "unwind-dw2-xtensa.h"
38 
39 #ifndef __USING_SJLJ_EXCEPTIONS__
40 
41 /* The standard CIE and FDE structures work fine for Xtensa but the
42    variable-size register window save areas are not a good fit for the rest
43    of the standard DWARF unwinding mechanism.  Nor is that mechanism
44    necessary, since the register save areas are always in fixed locations
45    in each stack frame.  This file is a stripped down and customized version
46    of the standard DWARF unwinding code.  It needs to be customized to have
47    builtin logic for finding the save areas and also to track the stack
48    pointer value (besides the CFA) while unwinding since the primary save
49    area is located below the stack pointer.  It is stripped down to reduce
50    code size and ease the maintenance burden of tracking changes in the
51    standard version of the code.  */
52 
53 #ifndef DWARF_REG_TO_UNWIND_COLUMN
54 #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
55 #endif
56 
57 #define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
58 
59 /* This is the register and unwind state for a particular frame.  This
60    provides the information necessary to unwind up past a frame and return
61    to its caller.  */
62 struct _Unwind_Context
63 {
64   /* Track register window save areas of 4 registers each, instead of
65      keeping separate addresses for the individual registers.  */
66   _Unwind_Word *reg[4];
67 
68   void *cfa;
69   void *sp;
70   void *ra;
71 
72   /* Cache the 2 high bits to replace the window size in return addresses.  */
73   _Unwind_Word ra_high_bits;
74 
75   void *lsda;
76   struct dwarf_eh_bases bases;
77   /* Signal frame context.  */
78 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
79   _Unwind_Word flags;
80   /* 0 for now, can be increased when further fields are added to
81      struct _Unwind_Context.  */
82   _Unwind_Word version;
83 };
84 
85 
86 /* Read unaligned data from the instruction buffer.  */
87 
88 union unaligned
89 {
90   void *p;
91 } __attribute__ ((packed));
92 
93 static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
94 static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
95 					       _Unwind_FrameState *);
96 
97 static inline void *
read_pointer(const void * p)98 read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
99 
100 static inline _Unwind_Word
_Unwind_IsSignalFrame(struct _Unwind_Context * context)101 _Unwind_IsSignalFrame (struct _Unwind_Context *context)
102 {
103   return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
104 }
105 
106 static inline void
_Unwind_SetSignalFrame(struct _Unwind_Context * context,int val)107 _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
108 {
109   if (val)
110     context->flags |= SIGNAL_FRAME_BIT;
111   else
112     context->flags &= ~SIGNAL_FRAME_BIT;
113 }
114 
115 /* Get the value of register INDEX as saved in CONTEXT.  */
116 
117 inline _Unwind_Word
_Unwind_GetGR(struct _Unwind_Context * context,int index)118 _Unwind_GetGR (struct _Unwind_Context *context, int index)
119 {
120   _Unwind_Word *ptr;
121 
122   index = DWARF_REG_TO_UNWIND_COLUMN (index);
123   ptr = context->reg[index >> 2] + (index & 3);
124 
125   return *ptr;
126 }
127 
128 /* Get the value of the CFA as saved in CONTEXT.  */
129 
130 _Unwind_Word
_Unwind_GetCFA(struct _Unwind_Context * context)131 _Unwind_GetCFA (struct _Unwind_Context *context)
132 {
133   return (_Unwind_Ptr) context->sp;
134 }
135 
136 /* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
137 
138 inline void
_Unwind_SetGR(struct _Unwind_Context * context,int index,_Unwind_Word val)139 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
140 {
141   _Unwind_Word *ptr;
142 
143   index = DWARF_REG_TO_UNWIND_COLUMN (index);
144   ptr = context->reg[index >> 2] + (index & 3);
145 
146   *ptr = val;
147 }
148 
149 /* Retrieve the return address for CONTEXT.  */
150 
151 inline _Unwind_Ptr
_Unwind_GetIP(struct _Unwind_Context * context)152 _Unwind_GetIP (struct _Unwind_Context *context)
153 {
154   return (_Unwind_Ptr) context->ra;
155 }
156 
157 /* Retrieve the return address and flag whether that IP is before
158    or after first not yet fully executed instruction.  */
159 
160 inline _Unwind_Ptr
_Unwind_GetIPInfo(struct _Unwind_Context * context,int * ip_before_insn)161 _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
162 {
163   *ip_before_insn = _Unwind_IsSignalFrame (context);
164   return (_Unwind_Ptr) context->ra;
165 }
166 
167 /* Overwrite the return address for CONTEXT with VAL.  */
168 
169 inline void
_Unwind_SetIP(struct _Unwind_Context * context,_Unwind_Ptr val)170 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
171 {
172   context->ra = (void *) val;
173 }
174 
175 void *
_Unwind_GetLanguageSpecificData(struct _Unwind_Context * context)176 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
177 {
178   return context->lsda;
179 }
180 
181 _Unwind_Ptr
_Unwind_GetRegionStart(struct _Unwind_Context * context)182 _Unwind_GetRegionStart (struct _Unwind_Context *context)
183 {
184   return (_Unwind_Ptr) context->bases.func;
185 }
186 
187 void *
_Unwind_FindEnclosingFunction(void * pc)188 _Unwind_FindEnclosingFunction (void *pc)
189 {
190   struct dwarf_eh_bases bases;
191   const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
192   if (fde)
193     return bases.func;
194   else
195     return NULL;
196 }
197 
198 _Unwind_Ptr
_Unwind_GetDataRelBase(struct _Unwind_Context * context)199 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
200 {
201   return (_Unwind_Ptr) context->bases.dbase;
202 }
203 
204 _Unwind_Ptr
_Unwind_GetTextRelBase(struct _Unwind_Context * context)205 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
206 {
207   return (_Unwind_Ptr) context->bases.tbase;
208 }
209 
210 #include "md-unwind-support.h"
211 
212 /* Extract any interesting information from the CIE for the translation
213    unit F belongs to.  Return a pointer to the byte after the augmentation,
214    or NULL if we encountered an undecipherable augmentation.  */
215 
216 static const unsigned char *
extract_cie_info(const struct dwarf_cie * cie,struct _Unwind_Context * context,_Unwind_FrameState * fs)217 extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
218 		  _Unwind_FrameState *fs)
219 {
220   const unsigned char *aug = cie->augmentation;
221   const unsigned char *p = aug + strlen ((const char *)aug) + 1;
222   const unsigned char *ret = NULL;
223   _uleb128_t utmp;
224   _sleb128_t stmp;
225 
226   /* g++ v2 "eh" has pointer immediately following augmentation string,
227      so it must be handled first.  */
228   if (aug[0] == 'e' && aug[1] == 'h')
229     {
230       fs->eh_ptr = read_pointer (p);
231       p += sizeof (void *);
232       aug += 2;
233     }
234 
235   /* Immediately following the augmentation are the code and
236      data alignment and return address column.  */
237   p = read_uleb128 (p, &utmp);
238   p = read_sleb128 (p, &stmp);
239   if (cie->version == 1)
240     fs->retaddr_column = *p++;
241   else
242     {
243       p = read_uleb128 (p, &utmp);
244       fs->retaddr_column = (_Unwind_Word)utmp;
245     }
246   fs->lsda_encoding = DW_EH_PE_omit;
247 
248   /* If the augmentation starts with 'z', then a uleb128 immediately
249      follows containing the length of the augmentation field following
250      the size.  */
251   if (*aug == 'z')
252     {
253       p = read_uleb128 (p, &utmp);
254       ret = p + utmp;
255 
256       fs->saw_z = 1;
257       ++aug;
258     }
259 
260   /* Iterate over recognized augmentation subsequences.  */
261   while (*aug != '\0')
262     {
263       /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
264       if (aug[0] == 'L')
265 	{
266 	  fs->lsda_encoding = *p++;
267 	  aug += 1;
268 	}
269 
270       /* "R" indicates a byte indicating how FDE addresses are encoded.  */
271       else if (aug[0] == 'R')
272 	{
273 	  fs->fde_encoding = *p++;
274 	  aug += 1;
275 	}
276 
277       /* "P" indicates a personality routine in the CIE augmentation.  */
278       else if (aug[0] == 'P')
279 	{
280 	  _Unwind_Ptr personality;
281 
282 	  p = read_encoded_value (context, *p, p + 1, &personality);
283 	  fs->personality = (_Unwind_Personality_Fn) personality;
284 	  aug += 1;
285 	}
286 
287       /* "S" indicates a signal frame.  */
288       else if (aug[0] == 'S')
289 	{
290 	  fs->signal_frame = 1;
291 	  aug += 1;
292 	}
293 
294       /* Otherwise we have an unknown augmentation string.
295 	 Bail unless we saw a 'z' prefix.  */
296       else
297 	return ret;
298     }
299 
300   return ret ? ret : p;
301 }
302 
303 /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
304    its caller and decode it into FS.  This function also sets the
305    lsda member of CONTEXT, as it is really information
306    about the caller's frame.  */
307 
308 static _Unwind_Reason_Code
uw_frame_state_for(struct _Unwind_Context * context,_Unwind_FrameState * fs)309 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
310 {
311   const struct dwarf_fde *fde;
312   const struct dwarf_cie *cie;
313   const unsigned char *aug;
314   int window_size;
315   _Unwind_Word *ra_ptr;
316 
317   memset (fs, 0, sizeof (*fs));
318   context->lsda = 0;
319 
320   fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
321 			  &context->bases);
322   if (fde == NULL)
323     {
324 #ifdef MD_FALLBACK_FRAME_STATE_FOR
325       _Unwind_Reason_Code reason;
326       /* Couldn't find frame unwind info for this function.  Try a
327 	 target-specific fallback mechanism.  This will necessarily
328 	 not provide a personality routine or LSDA.  */
329       reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs);
330       if (reason != _URC_END_OF_STACK)
331 	return reason;
332 #endif
333       /* The frame was not recognized and handled by the fallback function,
334 	 but it is not really the end of the stack.  Fall through here and
335 	 unwind it anyway.  */
336     }
337   else
338     {
339       cie = get_cie (fde);
340       if (extract_cie_info (cie, context, fs) == NULL)
341 	/* CIE contained unknown augmentation.  */
342 	return _URC_FATAL_PHASE1_ERROR;
343 
344       /* Locate augmentation for the fde.  */
345       aug = (const unsigned char *) fde + sizeof (*fde);
346       aug += 2 * size_of_encoded_value (fs->fde_encoding);
347       if (fs->saw_z)
348 	{
349 	  _uleb128_t i;
350 	  aug = read_uleb128 (aug, &i);
351 	}
352       if (fs->lsda_encoding != DW_EH_PE_omit)
353 	{
354 	  _Unwind_Ptr lsda;
355 
356 	  aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
357 	  context->lsda = (void *) lsda;
358 	}
359     }
360 
361   /* Check for the end of the stack.  This needs to be checked after
362      the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because
363      the contents of context->reg[0] are undefined at a signal frame,
364      and register a0 may appear to be zero.  (The return address in
365      context->ra comes from register a4 or a8).  */
366   ra_ptr = context->reg[0];
367   if (ra_ptr && *ra_ptr == 0)
368     return _URC_END_OF_STACK;
369 
370   /* Find the window size from the high bits of the return address.  */
371   if (ra_ptr)
372     window_size = (*ra_ptr >> 30) * 4;
373   else
374     window_size = 8;
375 
376   fs->retaddr_column = window_size;
377 
378   return _URC_NO_REASON;
379 }
380 
381 static void
uw_update_context_1(struct _Unwind_Context * context,_Unwind_FrameState * fs)382 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
383 {
384   struct _Unwind_Context orig_context = *context;
385   _Unwind_Word *sp, *cfa, *next_cfa;
386   int i;
387 
388   if (fs->signal_regs)
389     {
390       cfa = (_Unwind_Word *) fs->signal_regs[1];
391       next_cfa = (_Unwind_Word *) cfa[-3];
392 
393       for (i = 0; i < 4; i++)
394 	context->reg[i] = fs->signal_regs + (i << 2);
395     }
396   else
397     {
398       int window_size = fs->retaddr_column >> 2;
399 
400       sp = (_Unwind_Word *) orig_context.sp;
401       cfa = (_Unwind_Word *) orig_context.cfa;
402       next_cfa = (_Unwind_Word *) cfa[-3];
403 
404       /* Registers a0-a3 are in the save area below sp.  */
405       context->reg[0] = sp - 4;
406 
407       /* Find the extra save area below next_cfa.  */
408       for (i = 1; i < window_size; i++)
409 	context->reg[i] = next_cfa - 4 * (1 + window_size - i);
410 
411       /* Remaining registers rotate from previous save areas.  */
412       for (i = window_size; i < 4; i++)
413 	context->reg[i] = orig_context.reg[i - window_size];
414     }
415 
416   context->sp = cfa;
417   context->cfa = next_cfa;
418 
419   _Unwind_SetSignalFrame (context, fs->signal_frame);
420 }
421 
422 /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
423    of its caller.  Update CONTEXT to refer to the caller as well.  Note
424    that the lsda member is not updated here, but later in
425    uw_frame_state_for.  */
426 
427 static void
uw_update_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)428 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
429 {
430   uw_update_context_1 (context, fs);
431 
432   /* Compute the return address now, since the return address column
433      can change from frame to frame.  */
434   if (fs->signal_ra != 0)
435     context->ra = (void *) fs->signal_ra;
436   else
437     context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column)
438 			     & XTENSA_RA_FIELD_MASK) | context->ra_high_bits);
439 }
440 
441 static void
uw_advance_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)442 uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
443 {
444   uw_update_context (context, fs);
445 }
446 
447 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
448    level will be the return address and the CFA.  */
449 
450 #define uw_init_context(CONTEXT)					   \
451   do									   \
452     {									   \
453       __builtin_unwind_init ();						   \
454       uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
455 			 __builtin_return_address (0));			   \
456     }									   \
457   while (0)
458 
459 static void __attribute__((noinline))
uw_init_context_1(struct _Unwind_Context * context,void * outer_cfa,void * outer_ra)460 uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
461 		   void *outer_ra)
462 {
463   void *ra = __builtin_return_address (0);
464   void *cfa = __builtin_dwarf_cfa ();
465   _Unwind_FrameState fs;
466 
467   memset (context, 0, sizeof (struct _Unwind_Context));
468   context->ra = ra;
469 
470   memset (&fs, 0, sizeof (fs));
471   fs.retaddr_column = 8;
472   context->sp = cfa;
473   context->cfa = outer_cfa;
474   context->ra_high_bits =
475     ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK;
476   uw_update_context_1 (context, &fs);
477 
478   context->ra = outer_ra;
479 }
480 
481 
482 /* Install TARGET into CURRENT so that we can return to it.  This is a
483    macro because __builtin_eh_return must be invoked in the context of
484    our caller, and also because spilling registers of the caller before
485    the context installation may result in reload of wrong register values
486    after the context installation due to the change of the stack pointer
487    in the base save area.  This spilling may be caused by an interrupt
488    handler on baremetal host.  */
489 
490 #define uw_install_context(CURRENT, TARGET, FRAMES)			 \
491   do									 \
492     {									 \
493       void *handler = __builtin_frob_return_addr ((TARGET)->ra);	 \
494       long i;								 \
495 									 \
496       /* The eh_return insn assumes a window size of 8, so don't bother	 \
497 	 copying the save areas for registers a8-a15 since they won't be \
498 	 reloaded.  */							 \
499       for (i = 0; i < 2; ++i)						 \
500 	{								 \
501 	  _Unwind_Word *c = (CURRENT)->reg[i];				 \
502 	  _Unwind_Word *t = (TARGET)->reg[i];				 \
503 	  int j;							 \
504 									 \
505 	  if (t && c && t != c)						 \
506 	    for (j = 0; j < 4; ++j)					 \
507 	      *c++ = *t++;						 \
508 	}								 \
509       __builtin_eh_return (0, handler);					 \
510     }									 \
511   while (0)
512 
513 static inline _Unwind_Ptr
uw_identify_context(struct _Unwind_Context * context)514 uw_identify_context (struct _Unwind_Context *context)
515 {
516   return _Unwind_GetCFA (context);
517 }
518 
519 
520 #include "unwind.inc"
521 
522 #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
523 alias (_Unwind_Backtrace);
524 alias (_Unwind_DeleteException);
525 alias (_Unwind_FindEnclosingFunction);
526 alias (_Unwind_ForcedUnwind);
527 alias (_Unwind_GetDataRelBase);
528 alias (_Unwind_GetTextRelBase);
529 alias (_Unwind_GetCFA);
530 alias (_Unwind_GetGR);
531 alias (_Unwind_GetIP);
532 alias (_Unwind_GetLanguageSpecificData);
533 alias (_Unwind_GetRegionStart);
534 alias (_Unwind_RaiseException);
535 alias (_Unwind_Resume);
536 alias (_Unwind_Resume_or_Rethrow);
537 alias (_Unwind_SetGR);
538 alias (_Unwind_SetIP);
539 #endif
540 
541 #endif /* !USING_SJLJ_EXCEPTIONS */
542