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

📄 eh.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 2 页
字号:
find_exception_handler (void *pc, exception_descriptor *table,                         __eh_info *eh_info, int rethrow, int *cleanup){  void *retval = NULL;  *cleanup = 1;  if (table)    {      int pos = 0;      /* The new model assumed the table is sorted inner-most out so the         first region we find which matches is the correct one */      exception_table *tab = &(table->table[0]);      /* Subtract 1 from the PC to avoid hitting the next region */      if (rethrow)         {          /* pc is actually the region table entry to rethrow out of */          pos = ((exception_table *) pc) - tab;          pc = ((exception_table *) pc)->end_region - 1;          /* The label is always on the LAST handler entry for a region,              so we know the next entry is a different region, even if the             addresses are the same. Make sure its not end of table tho. */          if (tab[pos].start_region != (void *) -1)            pos++;        }      else        pc--;            /* We can't do a binary search because the table is in inner-most         to outermost address ranges within functions */      for ( ; tab[pos].start_region != (void *) -1; pos++)        {           if (tab[pos].start_region <= pc && tab[pos].end_region > pc)            {              if (tab[pos].match_info)                {                  __eh_matcher matcher = eh_info->match_function;                  /* match info but no matcher is NOT a match */                  if (matcher)                     {                      void *ret = (*matcher)((void *) eh_info,                                              tab[pos].match_info, table);                      if (ret)                         {                          if (retval == NULL)                            retval = tab[pos].exception_handler;                          *cleanup = 0;                          break;                        }                    }                }              else                {                  if (retval == NULL)                    retval = tab[pos].exception_handler;                }            }        }    }  return retval;}#endif /* DWARF2_UNWIND_INFO */#endif /* EH_TABLE_LOOKUP */#ifdef DWARF2_UNWIND_INFO/* Support code for exception handling using static unwind information.  */#include "frame.h"/* This type is used in get_reg and put_reg to deal with ABIs where a void*   is smaller than a word, such as the Irix 6 n32 ABI.  We cast twice to   avoid a warning about casting between int and pointer of different   sizes.  */typedef int ptr_type __attribute__ ((mode (pointer)));#ifdef INCOMING_REGNO/* Is the saved value for register REG in frame UDATA stored in a register   window in the previous frame?  *//* ??? The Sparc INCOMING_REGNO references TARGET_FLAT.  This allows us   to use the macro here.  One wonders, though, that perhaps TARGET_FLAT   compiled functions won't work with the frame-unwind stuff here.     Perhaps the entireity of in_reg_window should be conditional on having   seen a DW_CFA_GNU_window_save?  */#define target_flags 0static intin_reg_window (int reg, frame_state *udata){  if (udata->saved[reg] == REG_SAVED_REG)    return INCOMING_REGNO (reg) == reg;  if (udata->saved[reg] != REG_SAVED_OFFSET)    return 0;#ifdef STACK_GROWS_DOWNWARD  return udata->reg_or_offset[reg] > 0;#else  return udata->reg_or_offset[reg] < 0;#endif}#elsestatic inline int in_reg_window (int reg, frame_state *udata) { return 0; }#endif /* INCOMING_REGNO *//* Get the address of register REG as saved in UDATA, where SUB_UDATA is a   frame called by UDATA or 0.  */static word_type *get_reg_addr (unsigned reg, frame_state *udata, frame_state *sub_udata){  while (udata->saved[reg] == REG_SAVED_REG)    {      reg = udata->reg_or_offset[reg];      if (in_reg_window (reg, udata))	{          udata = sub_udata;	  sub_udata = NULL;	}    }  if (udata->saved[reg] == REG_SAVED_OFFSET)    return (word_type *)(udata->cfa + udata->reg_or_offset[reg]);  else    abort ();}/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a   frame called by UDATA or 0.  */static inline void *get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata){  return (void *)(ptr_type) *get_reg_addr (reg, udata, sub_udata);}/* Overwrite the saved value for register REG in frame UDATA with VAL.  */static inline voidput_reg (unsigned reg, void *val, frame_state *udata){  *get_reg_addr (reg, udata, NULL) = (word_type)(ptr_type) val;}/* Copy the saved value for register REG from frame UDATA to frame   TARGET_UDATA.  Unlike the previous two functions, this can handle   registers that are not one word large.  */static voidcopy_reg (unsigned reg, frame_state *udata, frame_state *target_udata){  word_type *preg = get_reg_addr (reg, udata, NULL);  word_type *ptreg = get_reg_addr (reg, target_udata, NULL);  memcpy (ptreg, preg, dwarf_reg_size_table [reg]);}/* Retrieve the return address for frame UDATA.  */static inline void *get_return_addr (frame_state *udata, frame_state *sub_udata){  return __builtin_extract_return_addr    (get_reg (udata->retaddr_column, udata, sub_udata));}/* Overwrite the return address for frame UDATA with VAL.  */static inline voidput_return_addr (void *val, frame_state *udata){  val = __builtin_frob_return_addr (val);  put_reg (udata->retaddr_column, val, udata);}static frame_state */* ARGSUSED */default_frame_state_for(void *pc, frame_state *udata, frame_state *caller_udata){  return __frame_state_for(pc, caller_udata);}frame_state * (*__frame_state_for_func)(void *, frame_state *, frame_state *) =	default_frame_state_for;/* Given the current frame UDATA and its return address PC, return the   information about the calling frame in CALLER_UDATA.  */static void *next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata){  caller_udata = (*__frame_state_for_func) (pc, udata, caller_udata);  if (! caller_udata)    return 0;  /* Now go back to our caller's stack frame.  If our caller's CFA register     was saved in our stack frame, restore it; otherwise, assume the CFA     register is SP and restore it to our CFA value.  */  if (udata->saved[caller_udata->cfa_reg])    caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);  else    caller_udata->cfa = udata->cfa;  caller_udata->cfa += caller_udata->cfa_offset;  return caller_udata;}/* Hook to call before __terminate if only cleanup handlers remain. */void __unwinding_cleanup (){}/* throw_helper performs some of the common grunt work for a throw. This   routine is called by throw and rethrows. This is pretty much split    out from the old __throw routine. An addition has been added which allows   for a dummy call to a routine __unwinding_cleanup() when there are nothing   but cleanups remaining. This allows a debugger to examine the state   at which the throw was executed, before any cleanups, rather than   at the terminate point after the stack has been unwound.   EH is the current eh_context structure.   PC is the address of the call to __throw.   MY_UDATA is the unwind information for __throw.   OFFSET_P is where we return the SP adjustment offset.  */static void *throw_helper (eh, pc, my_udata, offset_p)     struct eh_context *eh;     void *pc;     frame_state *my_udata;     long *offset_p;{  frame_state ustruct2, *udata = &ustruct2;  frame_state ustruct;  frame_state *sub_udata = &ustruct;  void *saved_pc = pc;  void *handler;  void *handler_p;  void *pc_p;  frame_state saved_ustruct;  int new_eh_model;  int cleanup = 0;  int only_cleanup = 0;  int rethrow = 0;  int saved_state = 0;  long args_size;  __eh_info *eh_info = (__eh_info *)eh->info;  /* Do we find a handler based on a re-throw PC? */  if (eh->table_index != (void *) 0)    rethrow = 1;  memcpy (udata, my_udata, sizeof (*udata));  handler = (void *) 0;  for (;;)    {       frame_state *p = udata;      udata = next_stack_level (pc, udata, sub_udata);      sub_udata = p;      /* If we couldn't find the next frame, we lose.  */      if (! udata)	break;      if (udata->eh_ptr == NULL)        new_eh_model = 0;      else        new_eh_model = (((exception_descriptor *)(udata->eh_ptr))->                                          runtime_id_field == NEW_EH_RUNTIME);      if (rethrow)         {          rethrow = 0;          handler = find_exception_handler (eh->table_index, udata->eh_ptr,                                           eh_info, 1, &cleanup);          eh->table_index = (void *)0;        }      else        if (new_eh_model)          handler = find_exception_handler (pc, udata->eh_ptr, eh_info,                                             0, &cleanup);        else          handler = old_find_exception_handler (pc, udata->eh_ptr);      /* If we found one, we can stop searching, if its not a cleanup.          for cleanups, we save the state, and keep looking. This allows         us to call a debug hook if there are nothing but cleanups left. */      if (handler)	{	  if (cleanup)	    {	      if (!saved_state)		{		  saved_ustruct = *udata;		  handler_p = handler;		  pc_p = pc;		  saved_state = 1;		  only_cleanup = 1;		}	    }	  else	    {	      only_cleanup = 0;	      break;	    }	}      /* Otherwise, we continue searching.  We subtract 1 from PC to avoid	 hitting the beginning of the next region.  */      pc = get_return_addr (udata, sub_udata) - 1;    }  if (saved_state)     {      udata = &saved_ustruct;      handler = handler_p;      pc = pc_p;      if (only_cleanup)        __unwinding_cleanup ();    }  /* If we haven't found a handler by now, this is an unhandled     exception.  */  if (! handler)     __terminate();  eh->handler_label = handler;  args_size = udata->args_size;  if (pc == saved_pc)    /* We found a handler in the throw context, no need to unwind.  */    udata = my_udata;  else    {      int i;      /* Unwind all the frames between this one and the handler by copying	 their saved register values into our register save slots.  */      /* Remember the PC where we found the handler.  */      void *handler_pc = pc;      /* Start from the throw context again.  */      pc = saved_pc;      memcpy (udata, my_udata, sizeof (*udata));      while (pc != handler_pc)	{	  frame_state *p = udata;	  udata = next_stack_level (pc, udata, sub_udata);	  sub_udata = p;	  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)	    if (i != udata->retaddr_column && udata->saved[i])	      {		/* If you modify the saved value of the return address		   register on the SPARC, you modify the return address for		   your caller's frame.  Don't do that here, as it will		   confuse get_return_addr.  */		if (in_reg_window (i, udata)		    && udata->saved[udata->retaddr_column] == REG_SAVED_REG		    && udata->reg_or_offset[udata->retaddr_column] == i)		  continue;		copy_reg (i, udata, my_udata);	      }	  pc = get_return_addr (udata, sub_udata) - 1;	}      /* But we do need to update the saved return address register from	 the last frame we unwind, or the handler frame will have the wrong	 return address.  */      if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)	{	  i = udata->reg_or_offset[udata->retaddr_column];	  if (in_reg_window (i, udata))	    copy_reg (i, udata, my_udata);	}    }  /* udata now refers to the frame called by the handler frame.  */  /* We adjust SP by the difference between __throw's CFA and the CFA for     the frame called by the handler frame, because those CFAs correspond     to the SP values at the two call sites.  We need to further adjust by     the args_size of the handler frame itself to get the handler frame's     SP from before the args were pushed for that call.  */#ifdef STACK_GROWS_DOWNWARD  *offset_p = udata->cfa - my_udata->cfa + args_size;#else  *offset_p = my_udata->cfa - udata->cfa - args_size;#endif		         return handler;}/* We first search for an exception handler, and if we don't find   it, we call __terminate on the current stack frame so that we may   use the debugger to walk the stack and understand why no handler   was found.   If we find one, then we unwind the frames down to the one that   has the handler and transfer control into the handler.  *//*extern void __throw(void) __attribute__ ((__noreturn__));*/void__throw (){  struct eh_context *eh = (*get_eh_context) ();  void *pc, *handler;  long offset;  /* XXX maybe make my_ustruct static so we don't have to look it up for     each throw.  */  frame_state my_ustruct, *my_udata = &my_ustruct;  /* This is required for C++ semantics.  We must call terminate if we     try and rethrow an exception, when there is no exception currently     active.  */  if (! eh->info)    __terminate ();      /* Start at our stack frame.  */label:  my_udata = __frame_state_for (&&label, my_udata);  if (! my_udata)    __terminate ();  /* We need to get the value from the CFA register. */  my_udata->cfa = __builtin_dwarf_cfa ();  /* Do any necessary initialization to access arbitrary stack frames.     On the SPARC, this means flushing the register windows.  */  __builtin_unwind_init ();  /* Now reset pc to the right throw point.  */  pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;  handler = throw_helper (eh, pc, my_udata, &offset);  /* Now go!  */  __builtin_eh_return ((void *)eh, offset, handler);  /* Epilogue:  restore the handler frame's register values and return     to the stub.  */}/*extern void __rethrow(void *) __attribute__ ((__noreturn__));*/void__rethrow (index)     void *index;{  struct eh_context *eh = (*get_eh_context) ();  void *pc, *handler;  long offset;  /* XXX maybe make my_ustruct static so we don't have to look it up for     each throw.  */  frame_state my_ustruct, *my_udata = &my_ustruct;  /* This is required for C++ semantics.  We must call terminate if we     try and rethrow an exception, when there is no exception currently     active.  */  if (! eh->info)    __terminate ();  /* This is the table index we want to rethrow from. The value of     the END_REGION label is used for the PC of the throw, and the     search begins with the next table entry. */  eh->table_index = index;      /* Start at our stack frame.  */label:  my_udata = __frame_state_for (&&label, my_udata);  if (! my_udata)    __terminate ();  /* We need to get the value from the CFA register. */  my_udata->cfa = __builtin_dwarf_cfa ();  /* Do any necessary initialization to access arbitrary stack frames.     On the SPARC, this means flushing the register windows.  */  __builtin_unwind_init ();  /* Now reset pc to the right throw point.  */  pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;  handler = throw_helper (eh, pc, my_udata, &offset);  /* Now go!  */  __builtin_eh_return ((void *)eh, offset, handler);  /* Epilogue:  restore the handler frame's register values and return     to the stub.  */}#endif /* DWARF2_UNWIND_INFO *//*----------------------------------------------------------------------*/#endif /* defined(HAVE_GCJ_SUPPORT) */

⌨️ 快捷键说明

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