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

📄 unwind-ia64.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  return dp;}/* RSE helper functions.  */static inline unsigned longia64_rse_slot_num (unsigned long *addr){  return (((unsigned long) addr) >> 3) & 0x3f;}/* Return TRUE if ADDR is the address of an RNAT slot.  */static inline unsigned longia64_rse_is_rnat_slot (unsigned long *addr){  return ia64_rse_slot_num (addr) == 0x3f;}/* Returns the address of the RNAT slot that covers the slot at   address SLOT_ADDR.  */static inline unsigned long *ia64_rse_rnat_addr (unsigned long *slot_addr){  return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));}/* Calculate the number of registers in the dirty partition starting at   BSPSTORE with a size of DIRTY bytes.  This isn't simply DIRTY   divided by eight because the 64th slot is used to store ar.rnat.  */static inline unsigned longia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp){  unsigned long slots = (bsp - bspstore);  return slots - (ia64_rse_slot_num (bspstore) + slots)/0x40;}/* The inverse of the above: given bspstore and the number of   registers, calculate ar.bsp.  */static inline unsigned long *ia64_rse_skip_regs (unsigned long *addr, long num_regs){  long delta = ia64_rse_slot_num (addr) + num_regs;  if (num_regs < 0)    delta -= 0x3e;  return addr + num_regs + delta/0x3f;}/* Copy register backing store from SRC to DST, LEN words   (which include both saved registers and nat collections).   DST_RNAT is a partial nat collection for DST.  SRC and DST   don't have to be equal modulo 64 slots, so it cannot be   done with a simple memcpy as the nat collections will be   at different relative offsets and need to be combined together.  */static voidia64_copy_rbs (struct _Unwind_Context *info, unsigned long dst,               unsigned long src, long len, unsigned long dst_rnat){  long count;  unsigned long src_rnat;  unsigned long shift1, shift2;  len <<= 3;  dst_rnat &= (1UL << ((dst >> 3) & 0x3f)) - 1;  src_rnat = src >= info->regstk_top	     ? info->rnat : *(unsigned long *) (src | 0x1f8);  src_rnat &= ~((1UL << ((src >> 3) & 0x3f)) - 1);  /* Just to make sure.  */  src_rnat &= ~(1UL << 63);  shift1 = ((dst - src) >> 3) & 0x3f;  if ((dst & 0x1f8) < (src & 0x1f8))    shift1--;  shift2 = 0x3f - shift1;  if ((dst & 0x1f8) >= (src & 0x1f8))    {      count = ~dst & 0x1f8;      goto first;    }  count = ~src & 0x1f8;  goto second;  while (len > 0)    {      src_rnat = src >= info->regstk_top		 ? info->rnat : *(unsigned long *) (src | 0x1f8);      /* Just to make sure.  */      src_rnat &= ~(1UL << 63);      count = shift2 << 3;first:      if (count > len)        count = len;      memcpy ((char *) dst, (char *) src, count);      dst += count;      src += count;      len -= count;      dst_rnat |= (src_rnat << shift1) & ~(1UL << 63);      if (len <= 0)        break;      *(long *) dst = dst_rnat;      dst += 8;      dst_rnat = 0;      count = shift1 << 3;second:      if (count > len)        count = len;      memcpy ((char *) dst, (char *) src, count);      dst += count;      src += count + 8;      len -= count + 8;      dst_rnat |= (src_rnat >> shift2);    }  if ((dst & 0x1f8) == 0x1f8)    {      *(long *) dst = dst_rnat;      dst += 8;      dst_rnat = 0;    }  /* Set info->regstk_top to lowest rbs address which will use     info->rnat collection.  */  info->regstk_top = dst & ~0x1ffUL;  info->rnat = dst_rnat;}/* Unwind accessors.  */static voidunw_access_gr (struct _Unwind_Context *info, int regnum,	       unsigned long *val, char *nat, int write){  unsigned long *addr, *nat_addr = 0, nat_mask = 0, dummy_nat;  struct unw_ireg *ireg;  if ((unsigned) regnum - 1 >= 127)    abort ();  if (regnum < 1)    {      nat_addr = addr = &dummy_nat;      dummy_nat = 0;    }  else if (regnum < 32)    {      /* Access a non-stacked register.  */      ireg = &info->ireg[regnum - 2];      addr = ireg->loc;      if (addr)	{	  nat_addr = addr + ireg->nat.off;	  switch (ireg->nat.type)	    {	    case UNW_NAT_VAL:	      /* Simulate getf.sig/setf.sig.  */	      if (write)		{		  if (*nat)		    {		      /* Write NaTVal and be done with it.  */		      addr[0] = 0;		      addr[1] = 0x1fffe;		      return;		    }		  addr[1] = 0x1003e;		}	      else if (addr[0] == 0 && addr[1] == 0x1ffe)		{		  /* Return NaT and be done with it.  */		  *val = 0;		  *nat = 1;		  return;		}	      /* FALLTHRU */	    case UNW_NAT_NONE:	      dummy_nat = 0;	      nat_addr = &dummy_nat;	      break;	    case UNW_NAT_MEMSTK:	      nat_mask = 1UL << ((long) addr & 0x1f8)/8;	      break;	    case UNW_NAT_REGSTK:	      if ((unsigned long) addr >= info->regstk_top)		nat_addr = &info->rnat;	      else		nat_addr = ia64_rse_rnat_addr (addr);	      nat_mask = 1UL << ia64_rse_slot_num (addr);	      break;	    }	}    }  else    {      /* Access a stacked register.  */      addr = ia64_rse_skip_regs ((unsigned long *) info->bsp, regnum - 32);      if ((unsigned long) addr >= info->regstk_top)	nat_addr = &info->rnat;      else	nat_addr = ia64_rse_rnat_addr (addr);      nat_mask = 1UL << ia64_rse_slot_num (addr);    }  if (write)    {      *addr = *val;      if (*nat)	*nat_addr |= nat_mask;      else	*nat_addr &= ~nat_mask;    }  else    {      *val = *addr;      *nat = (*nat_addr & nat_mask) != 0;    }}/* Get the value of register REG as saved in CONTEXT.  */_Unwind_Word_Unwind_GetGR (struct _Unwind_Context *context, int index){  _Unwind_Word ret;  char nat;  if (index == 1)    return context->gp;  else if (index >= 15 && index <= 18)    return context->eh_data[index - 15];  else    unw_access_gr (context, index, &ret, &nat, 0);  return ret;}/* Overwrite the saved value for register REG in CONTEXT with VAL.  */void_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val){  char nat = 0;  if (index == 1)    context->gp = val;  else if (index >= 15 && index <= 18)    context->eh_data[index - 15] = val;  else    unw_access_gr (context, index, &val, &nat, 1);}/* Retrieve the return address for CONTEXT.  */inline _Unwind_Ptr_Unwind_GetIP (struct _Unwind_Context *context){  return context->rp;}/* Overwrite the return address for CONTEXT with VAL.  */inline void_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val){  context->rp = val;}void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context){  return context->lsda;}_Unwind_Ptr_Unwind_GetRegionStart (struct _Unwind_Context *context){  return context->region_start;}void *_Unwind_FindEnclosingFunction (void *pc){  struct unw_table_entry *ent;  unsigned long segment_base, gp;  ent = _Unwind_FindTableEntry (pc, &segment_base, &gp);  if (ent == NULL)    return NULL;  else    return (void *)(segment_base + ent->start_offset);}/* Get the value of the CFA as saved in CONTEXT.  In GCC/Dwarf2 parlance,   the CFA is the value of the stack pointer on entry; In IA-64 unwind   parlance, this is the PSP.  */_Unwind_Word_Unwind_GetCFA (struct _Unwind_Context *context){  return (_Unwind_Ptr) context->psp;}/* Get the value of the Backing Store Pointer as saved in CONTEXT.  */_Unwind_Word_Unwind_GetBSP (struct _Unwind_Context *context){  return (_Unwind_Ptr) context->bsp;}#ifdef MD_UNWIND_SUPPORT#include MD_UNWIND_SUPPORT#endifstatic _Unwind_Reason_Codeuw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs){  struct unw_table_entry *ent;  unsigned long *unw, header, length;  unsigned char *insn, *insn_end;  unsigned long segment_base;  struct unw_reg_info *r;  memset (fs, 0, sizeof (*fs));  for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)    r->when = UNW_WHEN_NEVER;  context->lsda = 0;  ent = _Unwind_FindTableEntry ((void *) context->rp,				&segment_base, &context->gp);  if (ent == NULL)    {      /* Couldn't find unwind info for this function.  Try an	 os-specific fallback mechanism.  This will necessarily	 not provide a personality routine or LSDA.  */#ifdef MD_FALLBACK_FRAME_STATE_FOR      if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)	return _URC_NO_REASON;      /* [SCRA 11.4.1] A leaf function with no memory stack, no exception	 handlers, and which keeps the return value in B0 does not need	 an unwind table entry.	 This can only happen in the frame after unwinding through a signal	 handler.  Avoid infinite looping by requiring that B0 != RP.	 RP == 0 terminates the chain.  */      if (context->br_loc[0] && *context->br_loc[0] != context->rp	  && context->rp != 0)	{	  fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;	  fs->curr.reg[UNW_REG_RP].when = -1;	  fs->curr.reg[UNW_REG_RP].val = 0;	  return _URC_NO_REASON;	}#endif      return _URC_END_OF_STACK;    }  context->region_start = ent->start_offset + segment_base;  fs->when_target = ((context->rp & -16) - context->region_start) / 16 * 3		    + (context->rp & 15);  unw = (unsigned long *) (ent->info_offset + segment_base);  header = *unw;  length = UNW_LENGTH (header);  /* ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK.  */  if (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header))    {      fs->personality =	*(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp);      context->lsda = unw + length + 2;    }  insn = (unsigned char *) (unw + 1);  insn_end = (unsigned char *) (unw + 1 + length);  while (!fs->done && insn < insn_end)    insn = unw_decode (insn, fs->in_body, fs);  free_label_states (fs->labeled_states);  free_state_stack (&fs->curr);#ifdef ENABLE_MALLOC_CHECKING  if (reg_state_alloced || labeled_state_alloced)    abort ();#endif  /* If we're in the epilogue, sp has been restored and all values     on the memory stack below psp also have been restored.  */  if (fs->when_target > fs->epilogue_start)    {      struct unw_reg_info *r;      fs->curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;      fs->curr.reg[UNW_REG_PSP].val = 0;      for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)	if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)	    || r->where == UNW_WHERE_SPREL)	  r->where = UNW_WHERE_NONE;    }  /* If RP did't get saved, generate entry for the return link register.  */  if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)    {      fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;      fs->curr.reg[UNW_REG_RP].when = -1;      fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg;    }  return _URC_NO_REASON;}static voiduw_update_reg_address (struct _Unwind_Context *context,		       _Unwind_FrameState *fs,		       enum unw_register_index regno){  struct unw_reg_info *r = fs->curr.reg + regno;  void *addr;  unsigned long rval;  if (r->where == UNW_WHERE_NONE || r->when >= fs->when_target)    return;  rval = r->val;  switch (r->where)    {    case UNW_WHERE_GR:      if (rval >= 32)	addr = ia64_rse_skip_regs ((unsigned long *) context->bsp, rval - 32);      else if (rval >= 2)	addr = context->ireg[rval - 2].loc;      else if (rval == 0)	{	  static const unsigned long dummy;	  addr = (void *) &dummy;	}      else	abort ();      break;    case UNW_WHERE_FR:      if (rval >= 2 && rval < 32)	addr = context->fr_loc[rval - 2];      else	abort ();      break;    case UNW_WHERE_BR:      /* Note that while RVAL can only be 1-5 from normal descriptors,	 we can want to look at B0, B6 and B7 due to having manually unwound a	 signal frame.  */      if (rval < 8)	addr = context->br_loc[rval];      else	abort ();      break;    case UNW_WHERE_SPREL:      addr = (void *)(context->sp + rval);      break;    case UNW_WHERE_PSPREL:      addr = (void *)(context->psp + rval);      break;    default:      abort ();    }  switch (regno)    {    case UNW_REG_R2 ... UNW_REG_R31:      context->ireg[regno - UNW_REG_R2].loc = addr;      switch (r->where)      {      case UNW_WHERE_GR:	if (rval >= 32)	  {	    context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;

⌨️ 快捷键说明

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