⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unwind-ia64.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Subroutines needed for unwinding IA-64 standard format stack frame   info for exception handling.   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002   Free Software Foundation, Inc.   Contributed by Andrew MacLeod  <amacleod@cygnus.com>	          Andrew Haley  <aph@cygnus.com>		  David Mosberger-Tang <davidm@hpl.hp.com>   This file is part of GNU CC.   GNU CC is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   GNU CC is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with GNU CC; see the file COPYING.  If not, write to   the Free Software Foundation, 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.  *//* As a special exception, if you link this library with other files,   some of which are compiled with GCC, to produce an executable,   this library does not by itself cause the resulting executable   to be covered by the GNU General Public License.   This exception does not however invalidate any other reasons why   the executable file might be covered by the GNU General Public License.  */#include "tconfig.h"#include "tsystem.h"#include "unwind.h"#include "unwind-ia64.h"#include "ia64intrin.h"/* This isn't thread safe, but nice for occasional tests.  */#undef ENABLE_MALLOC_CHECKING#ifndef __USING_SJLJ_EXCEPTIONS__#define UNW_VER(x)		((x) >> 48)#define UNW_FLAG_MASK		0x0000ffff00000000#define UNW_FLAG_OSMASK		0x0000f00000000000#define UNW_FLAG_EHANDLER(x)	((x) & 0x0000000100000000L)#define UNW_FLAG_UHANDLER(x)	((x) & 0x0000000200000000L)#define UNW_LENGTH(x)		((x) & 0x00000000ffffffffL)enum unw_application_register{  UNW_AR_BSP,  UNW_AR_BSPSTORE,  UNW_AR_PFS,  UNW_AR_RNAT,  UNW_AR_UNAT,  UNW_AR_LC,  UNW_AR_EC,  UNW_AR_FPSR,  UNW_AR_RSC,  UNW_AR_CCV};enum unw_register_index{  /* Primary UNAT.  */  UNW_REG_PRI_UNAT_GR,  UNW_REG_PRI_UNAT_MEM,  /* Memory Stack.  */  UNW_REG_PSP,			/* previous memory stack pointer */  /* Register Stack.  */  UNW_REG_BSP,			/* register stack pointer */  UNW_REG_BSPSTORE,  UNW_REG_PFS,			/* previous function state */  UNW_REG_RNAT,  /* Return Pointer.  */  UNW_REG_RP,  /* Special preserved registers.  */  UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,  /* Non-stacked general registers.  */  UNW_REG_R2,  UNW_REG_R4 = UNW_REG_R2 + 2,  UNW_REG_R7 = UNW_REG_R2 + 5,  UNW_REG_R31 = UNW_REG_R2 + 29,  /* Non-stacked floating point registers.  */  UNW_REG_F2,  UNW_REG_F5 = UNW_REG_F2 + 3,  UNW_REG_F16 = UNW_REG_F2 + 14,  UNW_REG_F31 = UNW_REG_F2 + 29,  /* Branch registers.  */  UNW_REG_B0, UNW_REG_B1,  UNW_REG_B5 = UNW_REG_B1 + 4,  UNW_NUM_REGS};enum unw_where{  UNW_WHERE_NONE,	/* register isn't saved at all */  UNW_WHERE_GR,		/* register is saved in a general register */  UNW_WHERE_FR,		/* register is saved in a floating-point register */  UNW_WHERE_BR,		/* register is saved in a branch register */  UNW_WHERE_SPREL,	/* register is saved on memstack (sp-relative) */  UNW_WHERE_PSPREL,	/* register is saved on memstack (psp-relative) */  /* At the end of each prologue these locations get resolved to     UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively.  */  UNW_WHERE_SPILL_HOME,	/* register is saved in its spill home */  UNW_WHERE_GR_SAVE	/* register is saved in next general register */};#define UNW_WHEN_NEVER  0x7fffffffstruct unw_reg_info{  unsigned long val;		/* save location: register number or offset */  enum unw_where where;		/* where the register gets saved */  int when;			/* when the register gets saved */};struct unw_reg_state {	struct unw_reg_state *next;	/* next (outer) element on state stack */	struct unw_reg_info reg[UNW_NUM_REGS];	/* register save locations */};struct unw_labeled_state {	struct unw_labeled_state *next;		/* next labeled state (or NULL) */	unsigned long label;			/* label for this state */	struct unw_reg_state saved_state;};typedef struct unw_state_record{  unsigned int first_region : 1;	/* is this the first region? */  unsigned int done : 1;		/* are we done scanning descriptors? */  unsigned int any_spills : 1;		/* got any register spills? */  unsigned int in_body : 1;	/* are we inside a body? */  unsigned int no_reg_stack_frame : 1;	/* Don't adjust bsp for i&l regs */  unsigned char *imask;		/* imask of spill_mask record or NULL */  unsigned long pr_val;		/* predicate values */  unsigned long pr_mask;	/* predicate mask */  long spill_offset;		/* psp-relative offset for spill base */  int region_start;  int region_len;  int epilogue_start;  int epilogue_count;  int when_target;  unsigned char gr_save_loc;	/* next general register to use for saving */  unsigned char return_link_reg; /* branch register for return link */  unsigned short unwabi;  struct unw_labeled_state *labeled_states;	/* list of all labeled states */  struct unw_reg_state curr;	/* current state */  _Unwind_Personality_Fn personality;  } _Unwind_FrameState;enum unw_nat_type{  UNW_NAT_NONE,			/* NaT not represented */  UNW_NAT_VAL,			/* NaT represented by NaT value (fp reg) */  UNW_NAT_MEMSTK,		/* NaT value is in unat word at offset OFF  */  UNW_NAT_REGSTK		/* NaT is in rnat */};struct unw_stack{  unsigned long limit;  unsigned long top;};struct _Unwind_Context{  /* Initial frame info.  */  unsigned long rnat;		/* rse nat collection */  unsigned long regstk_top;	/* bsp for first frame */  /* Current frame info.  */  unsigned long bsp;		/* backing store pointer value				   corresponding to psp.  */  unsigned long sp;		/* stack pointer value */  unsigned long psp;		/* previous sp value */  unsigned long rp;		/* return pointer */  unsigned long pr;		/* predicate collection */  unsigned long region_start;	/* start of unwind region */  unsigned long gp;		/* global pointer value */  void *lsda;			/* language specific data area */  /* Preserved state.  */  unsigned long *bsp_loc;	/* previous bsp save location  				   Appears to be write-only?	*/  unsigned long *bspstore_loc;  unsigned long *pfs_loc;	/* Save location for pfs in current  				   (corr. to sp) frame.  Target  				   contains cfm for caller.	*/  unsigned long *pri_unat_loc;  unsigned long *unat_loc;  unsigned long *lc_loc;  unsigned long *fpsr_loc;  unsigned long eh_data[4];  struct unw_ireg  {    unsigned long *loc;    struct unw_ireg_nat    {      enum unw_nat_type type : 3;      signed long off : 61;		/* NaT word is at loc+nat.off */    } nat;  } ireg[32 - 2];	/* Indexed by <register number> - 2 */  unsigned long *br_loc[8];  void *fr_loc[32 - 2];  /* ??? We initially point pri_unat_loc here.  The entire NAT bit     logic needs work.  */  unsigned long initial_unat;};typedef unsigned long unw_word;/* Implicit register save order.  See section 11.4.2.3 Rules for Using   Unwind Descriptors, rule 3.  */static unsigned char const save_order[] ={  UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,  UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR};#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))/* MASK is a bitmap describing the allocation state of emergency buffers,   with bit set indicating free. Return >= 0 if allocation is successful;   < 0 if failure.  */static inline intatomic_alloc (unsigned int *mask){  unsigned int old = *mask, ret, new;  while (1)    {      if (old == 0)	return -1;      ret = old & -old;      new = old & ~ret;      new = __sync_val_compare_and_swap (mask, old, new);      if (old == new)	break;      old = new;    }  return __builtin_ffs (ret) - 1;}/* Similarly, free an emergency buffer.  */static inline voidatomic_free (unsigned int *mask, int bit){  __sync_xor_and_fetch (mask, 1 << bit);}#define SIZE(X)		(sizeof(X) / sizeof(*(X)))#define MASK_FOR(X)	((2U << (SIZE (X) - 1)) - 1)#define PTR_IN(X, P)	((P) >= (X) && (P) < (X) + SIZE (X))static struct unw_reg_state emergency_reg_state[32];static int emergency_reg_state_free = MASK_FOR (emergency_reg_state);static struct unw_labeled_state emergency_labeled_state[8];static int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);#ifdef ENABLE_MALLOC_CHECKINGstatic int reg_state_alloced;static int labeled_state_alloced;#endif/* Allocation and deallocation of structures.  */static struct unw_reg_state *alloc_reg_state (void){  struct unw_reg_state *rs;#ifdef ENABLE_MALLOC_CHECKING  reg_state_alloced++;#endif  rs = malloc (sizeof (struct unw_reg_state));  if (!rs)    {      int n = atomic_alloc (&emergency_reg_state_free);      if (n >= 0)	rs = &emergency_reg_state[n];    }  return rs;}static voidfree_reg_state (struct unw_reg_state *rs){#ifdef ENABLE_MALLOC_CHECKING  reg_state_alloced--;#endif  if (PTR_IN (emergency_reg_state, rs))    atomic_free (&emergency_reg_state_free, rs - emergency_reg_state);  else    free (rs);}static struct unw_labeled_state *alloc_label_state (void){  struct unw_labeled_state *ls;#ifdef ENABLE_MALLOC_CHECKING  labeled_state_alloced++;#endif  ls = malloc(sizeof(struct unw_labeled_state));  if (!ls)    {      int n = atomic_alloc (&emergency_labeled_state_free);      if (n >= 0)	ls = &emergency_labeled_state[n];    }  return ls;}static voidfree_label_state (struct unw_labeled_state *ls){#ifdef ENABLE_MALLOC_CHECKING  labeled_state_alloced--;#endif  if (PTR_IN (emergency_labeled_state, ls))    atomic_free (&emergency_labeled_state_free, emergency_labeled_state - ls);  else    free (ls);}/* Routines to manipulate the state stack.  */static voidpush (struct unw_state_record *sr){  struct unw_reg_state *rs = alloc_reg_state ();  memcpy (rs, &sr->curr, sizeof (*rs));  sr->curr.next = rs;}static voidpop (struct unw_state_record *sr){  struct unw_reg_state *rs = sr->curr.next;  if (!rs)    abort ();  memcpy (&sr->curr, rs, sizeof(*rs));  free_reg_state (rs);}/* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */static struct unw_reg_state *dup_state_stack (struct unw_reg_state *rs){  struct unw_reg_state *copy, *prev = NULL, *first = NULL;  while (rs)    {      copy = alloc_reg_state ();      memcpy (copy, rs, sizeof(*copy));      if (first)	prev->next = copy;      else	first = copy;      rs = rs->next;      prev = copy;    }  return first;}/* Free all stacked register states (but not RS itself).  */static voidfree_state_stack (struct unw_reg_state *rs){  struct unw_reg_state *p, *next;  for (p = rs->next; p != NULL; p = next)    {      next = p->next;      free_reg_state (p);    }  rs->next = NULL;}/* Free all labeled states.  */static voidfree_label_states (struct unw_labeled_state *ls){  struct unw_labeled_state *next;  for (; ls ; ls = next)    {      next = ls->next;      free_state_stack (&ls->saved_state);      free_label_state (ls);    }}/* Unwind decoder routines */static enum unw_register_index __attribute__((const))decode_abreg (unsigned char abreg, int memory){  switch (abreg)    {    case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);    case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);    case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);    case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);    case 0x60: return UNW_REG_PR;    case 0x61: return UNW_REG_PSP;    case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;    case 0x63: return UNW_REG_RP;    case 0x64: return UNW_REG_BSP;    case 0x65: return UNW_REG_BSPSTORE;    case 0x66: return UNW_REG_RNAT;    case 0x67: return UNW_REG_UNAT;    case 0x68: return UNW_REG_FPSR;    case 0x69: return UNW_REG_PFS;    case 0x6a: return UNW_REG_LC;    default:      abort ();  }}static voidset_reg (struct unw_reg_info *reg, enum unw_where where,	 int when, unsigned long val){  reg->val = val;  reg->where = where;  if (reg->when == UNW_WHEN_NEVER)    reg->when = when;}static voidalloc_spill_area (unsigned long *offp, unsigned long regsize,		  struct unw_reg_info *lo, struct unw_reg_info *hi){  struct unw_reg_info *reg;  for (reg = hi; reg >= lo; --reg)    {      if (reg->where == UNW_WHERE_SPILL_HOME)	{	  reg->where = UNW_WHERE_PSPREL;	  *offp -= regsize;	  reg->val = *offp;	}    }}static inline voidspill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim,		 unw_word t){  struct unw_reg_info *reg;  for (reg = *regp; reg <= lim; ++reg)    {      if (reg->where == UNW_WHERE_SPILL_HOME)	{	  reg->when = t;	  *regp = reg + 1;	  return;	}    }  /* Excess spill.  */  abort ();}static voidfinish_prologue (struct unw_state_record *sr){  struct unw_reg_info *reg;  unsigned long off;  int i;  /* First, resolve implicit register save locations     (see Section "11.4.2.3 Rules for Using Unwind Descriptors", rule 3).  */  for (i = 0; i < (int) sizeof (save_order); ++i)    {      reg = sr->curr.reg + save_order[i];      if (reg->where == UNW_WHERE_GR_SAVE)	{	  reg->where = UNW_WHERE_GR;	  reg->val = sr->gr_save_loc++;	}    }  /* Next, compute when the fp, general, and branch registers get saved.     This must come before alloc_spill_area() because we need to know     which registers are spilled to their home locations.  */  if (sr->imask)    {      static unsigned char const limit[3] = {	UNW_REG_F31, UNW_REG_R7, UNW_REG_B5      };      unsigned char kind, mask = 0, *cp = sr->imask;      int t;      struct unw_reg_info *(regs[3]);      regs[0] = sr->curr.reg + UNW_REG_F2;      regs[1] = sr->curr.reg + UNW_REG_R4;      regs[2] = sr->curr.reg + UNW_REG_B1;      for (t = 0; t < sr->region_len; ++t)	{	  if ((t & 3) == 0)	    mask = *cp++;	  kind = (mask >> 2*(3-(t & 3))) & 3;	  if (kind > 0)	    spill_next_when (&regs[kind - 1], sr->curr.reg + limit[kind - 1],			     sr->region_start + t);	}    }  /* Next, lay out the memory stack spill area.  */  if (sr->any_spills)    {      off = sr->spill_offset;      alloc_spill_area (&off, 16, sr->curr.reg + UNW_REG_F2,		        sr->curr.reg + UNW_REG_F31);       alloc_spill_area (&off,  8, sr->curr.reg + UNW_REG_B1,		        sr->curr.reg + UNW_REG_B5);      alloc_spill_area (&off,  8, sr->curr.reg + UNW_REG_R4,		        sr->curr.reg + UNW_REG_R7);    }}/* * Region header descriptors. */static voiddesc_prologue (int body, unw_word rlen, unsigned char mask,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -