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

📄 dbxout.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		 We want the value of that CONST_INT.  */	      current_sym_value		= DEBUGGER_AUTO_OFFSET (XEXP (XEXP (DECL_RTL (decl), 0), 0));	    }	  /* Effectively do build_pointer_type, but don't cache this type,	     since it might be temporary whereas the type it points to	     might have been saved for inlining.  */	  /* Don't use REFERENCE_TYPE because dbx can't handle that.  */	  type = make_node (POINTER_TYPE);	  TREE_TYPE (type) = TREE_TYPE (decl);	}      else if (GET_CODE (DECL_RTL (decl)) == MEM	       && GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG)	{	  current_sym_code = N_LSYM;	  current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0));	}      else if (GET_CODE (DECL_RTL (decl)) == MEM	       && GET_CODE (XEXP (DECL_RTL (decl), 0)) == PLUS	       && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 1)) == CONST_INT)	{	  current_sym_code = N_LSYM;	  /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))	     We want the value of that CONST_INT.  */	  current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0));	}      else if (GET_CODE (DECL_RTL (decl)) == MEM	       && GET_CODE (XEXP (DECL_RTL (decl), 0)) == CONST)	{	  /* Handle an obscure case which can arise when optimizing and	     when there are few available registers.  (This is *always*	     the case for i386/i486 targets).  The DECL_RTL looks like	     (MEM (CONST ...)) even though this variable is a local `auto'	     or a local `register' variable.  In effect, what has happened	     is that the reload pass has seen that all assignments and	     references for one such a local variable can be replaced by	     equivalent assignments and references to some static storage	     variable, thereby avoiding the need for a register.  In such	     cases we're forced to lie to debuggers and tell them that	     this variable was itself `static'.  */	  current_sym_code = N_LCSYM;	  letter = 'V';	  current_sym_addr = XEXP (XEXP (DECL_RTL (decl), 0), 0);	}      else	/* Address might be a MEM, when DECL is a variable-sized object.	   Or it might be const0_rtx, meaning previous passes	   want us to ignore this variable.  */	break;      /* Ok, start a symtab entry and output the variable name.  */      FORCE_TEXT;#ifdef DBX_STATIC_BLOCK_START      DBX_STATIC_BLOCK_START (asmfile, current_sym_code);#endif      /* One slight hitch: if this is a VAR_DECL which is a static	 class member, we must put out the mangled name instead of the	 DECL_NAME.  */      {	char *name;	/* Note also that static member (variable) names DO NOT begin	   with underscores in .stabs directives.  */	if (DECL_LANG_SPECIFIC (decl))	  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));	else	  name = IDENTIFIER_POINTER (DECL_NAME (decl));	fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, name);      }      if (letter) putc (letter, asmfile);      dbxout_type (type, 0, 0);      dbxout_finish_symbol (decl);#ifdef DBX_STATIC_BLOCK_END      DBX_STATIC_BLOCK_END (asmfile, current_sym_code);#endif      break;    }}static voiddbxout_prepare_symbol (decl)     tree decl;{#ifdef WINNING_GDB  char *filename = DECL_SOURCE_FILE (decl);  dbxout_source_file (asmfile, filename);#endif}static voiddbxout_finish_symbol (sym)     tree sym;{#ifdef DBX_FINISH_SYMBOL  DBX_FINISH_SYMBOL (sym);#else  int line = 0;#ifdef WINNING_GDB  if (sym != 0)    line = DECL_SOURCE_LINE (sym);#endif  fprintf (asmfile, "\",%d,0,%d,", current_sym_code, line);  if (current_sym_addr)    output_addr_const (asmfile, current_sym_addr);  else    fprintf (asmfile, "%d", current_sym_value);  putc ('\n', asmfile);#endif}/* Output definitions of all the decls in a chain.  */voiddbxout_syms (syms)     tree syms;{  while (syms)    {      dbxout_symbol (syms, 1);      syms = TREE_CHAIN (syms);    }}/* The following two functions output definitions of function parameters.   Each parameter gets a definition locating it in the parameter list.   Each parameter that is a register variable gets a second definition   locating it in the register.   Printing or argument lists in gdb uses the definitions that   locate in the parameter list.  But reference to the variable in   expressions uses preferentially the definition as a register.  *//* Output definitions, referring to storage in the parmlist,   of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */voiddbxout_parms (parms)     tree parms;{  for (; parms; parms = TREE_CHAIN (parms))    if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)      {	dbxout_prepare_symbol (parms);	/* Perform any necessary register eliminations on the parameter's rtl,	   so that the debugging output will be accurate.  */	DECL_INCOMING_RTL (parms)	  = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);	DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);#ifdef LEAF_REG_REMAP	if (leaf_function)	  {	    leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));	    leaf_renumber_regs_insn (DECL_RTL (parms));	  }#endif	if (PARM_PASSED_IN_MEMORY (parms))	  {	    rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);	    /* ??? Here we assume that the parm address is indexed	       off the frame pointer or arg pointer.	       If that is not true, we produce meaningless results,	       but do not crash.  */	    if (GET_CODE (addr) == PLUS		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)	      current_sym_value = INTVAL (XEXP (addr, 1));	    else	      current_sym_value = 0;	    current_sym_code = N_PSYM;	    current_sym_addr = 0;	    FORCE_TEXT;	    if (DECL_NAME (parms))	      {		current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));		fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,			 IDENTIFIER_POINTER (DECL_NAME (parms)),			 DBX_MEMPARM_STABS_LETTER);	      }	    else	      {		current_sym_nchars = 8;		fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,			 DBX_MEMPARM_STABS_LETTER);	      }	    if (GET_CODE (DECL_RTL (parms)) == REG		&& REGNO (DECL_RTL (parms)) >= 0		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)	      dbxout_type (DECL_ARG_TYPE (parms), 0, 0);	    else	      {		int original_value = current_sym_value;		/* This is the case where the parm is passed as an int or double		   and it is converted to a char, short or float and stored back		   in the parmlist.  In this case, describe the parm		   with the variable's declared type, and adjust the address		   if the least significant bytes (which we are using) are not		   the first ones.  */#if BYTES_BIG_ENDIAN		if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))		  current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))					- GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));#endif		if (GET_CODE (DECL_RTL (parms)) == MEM		    && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS		    && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT		    && INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == current_sym_value)		  dbxout_type (TREE_TYPE (parms), 0, 0);		else		  {		    current_sym_value = original_value;		    dbxout_type (DECL_ARG_TYPE (parms), 0, 0);		  }	      }	    current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);	    dbxout_finish_symbol (parms);	  }	else if (GET_CODE (DECL_RTL (parms)) == REG)	  {	    rtx best_rtl;	    char regparm_letter;	    /* Parm passed in registers and lives in registers or nowhere.  */	    current_sym_code = DBX_REGPARM_STABS_CODE;	    regparm_letter = DBX_REGPARM_STABS_LETTER;	    current_sym_addr = 0;	    /* If parm lives in a register, use that register;	       pretend the parm was passed there.  It would be more consistent	       to describe the register where the parm was passed,	       but in practice that register usually holds something else.  */	    if (REGNO (DECL_RTL (parms)) >= 0		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)	      best_rtl = DECL_RTL (parms);	    /* If the parm lives nowhere,	       use the register where it was passed.  */	    else	      best_rtl = DECL_INCOMING_RTL (parms);	    current_sym_value = DBX_REGISTER_NUMBER (REGNO (best_rtl));	    FORCE_TEXT;	    if (DECL_NAME (parms))	      {		current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));		fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,			 IDENTIFIER_POINTER (DECL_NAME (parms)),			 regparm_letter);	      }	    else	      {		current_sym_nchars = 8;		fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,			 regparm_letter);	      }	    dbxout_type (DECL_ARG_TYPE (parms), 0, 0);	    dbxout_finish_symbol (parms);	  }	else if (GET_CODE (DECL_RTL (parms)) == MEM		 && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG)/*		 && rtx_equal_p (XEXP (DECL_RTL (parms), 0),				 DECL_INCOMING_RTL (parms))) */	  {	    /* Parm was passed via invisible reference.	       That is, its address was passed in a register.	       Output it as if it lived in that register.	       The debugger will know from the type	       that it was actually passed by invisible reference.  */	    char regparm_letter;	    /* Parm passed in registers and lives in registers or nowhere.  */	    current_sym_code = DBX_REGPARM_STABS_CODE;	    regparm_letter = DBX_REGPARM_STABS_LETTER;	    /* DECL_RTL looks like (MEM (REG...).  Get the register number.  */	    current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0));	    current_sym_addr = 0;	    FORCE_TEXT;	    if (DECL_NAME (parms))	      {		current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));		fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,			 IDENTIFIER_POINTER (DECL_NAME (parms)),			 DBX_REGPARM_STABS_LETTER);	      }	    else	      {		current_sym_nchars = 8;		fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,			 DBX_REGPARM_STABS_LETTER);	      }	    dbxout_type (TREE_TYPE (parms), 0, 0);	    dbxout_finish_symbol (parms);	  }	else if (GET_CODE (DECL_RTL (parms)) == MEM		 && XEXP (DECL_RTL (parms), 0) != const0_rtx)	  {	    /* Parm was passed in registers but lives on the stack.  */	    current_sym_code = N_PSYM;	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),	       in which case we want the value of that CONST_INT,	       or (MEM (REG ...)) or (MEM (MEM ...)),	       in which case we use a value of zero.  */	    if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG		|| GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)	      current_sym_value = 0;	    else	      current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));	    current_sym_addr = 0;	    FORCE_TEXT;	    if (DECL_NAME (parms))	      {		current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));		fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,			 IDENTIFIER_POINTER (DECL_NAME (parms)),			 DBX_MEMPARM_STABS_LETTER);	      }	    else	      {		current_sym_nchars = 8;		fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,		DBX_MEMPARM_STABS_LETTER);	      }	    current_sym_value	      = DEBUGGER_ARG_OFFSET (current_sym_value,				     XEXP (DECL_RTL (parms), 0));	    dbxout_type (TREE_TYPE (parms), 0, 0);	    dbxout_finish_symbol (parms);	  }      }}/* Output definitions for the places where parms live during the function,   when different from where they were passed, when the parms were passed   in memory.   It is not useful to do this for parms passed in registers   that live during the function in different registers, because it is   impossible to look in the passed register for the passed value,   so we use the within-the-function register to begin with.   PARMS is a chain of PARM_DECL nodes.  */voiddbxout_reg_parms (parms)     tree parms;{  for (; parms; parms = TREE_CHAIN (parms))    if (DECL_NAME (parms))      {	dbxout_prepare_symbol (parms);	/* Report parms that live in registers during the function	   but were passed in memory.  */	if (GET_CODE (DECL_RTL (parms)) == REG	    && REGNO (DECL_RTL (parms)) >= 0	    && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER	    && PARM_PASSED_IN_MEMORY (parms))	  {	    current_sym_code = N_RSYM;	    current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms)));	    current_sym_addr = 0;	    FORCE_TEXT;	    if (DECL_NAME (parms))	      {		current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));		fprintf (asmfile, "%s \"%s:r", ASM_STABS_OP,			 IDENTIFIER_POINTER (DECL_NAME (parms)));	      }	    else	      {		current_sym_nchars = 8;		fprintf (asmfile, "%s \"(anon):r", ASM_STABS_OP);	      }	    dbxout_type (TREE_TYPE (parms), 0, 0);	    dbxout_finish_symbol (parms);	  }	/* Report parms that live in memory but not where they were passed.  */	else if (GET_CODE (DECL_RTL (parms)) == MEM		 && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS		 && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT		 && PARM_PASSED_IN_MEMORY (parms)		 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))	  {#if 0 /* ??? It is not clear yet what should replace this.  */	    int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;	    /* A parm declared char is really passed as an int,	       so it occupies the least significant bytes.	       On a big-endian machine those are not the low-numbered ones.  */#if BYTES_BIG_ENDIAN	    if (offset != -1 && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))	      offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))			 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));#endif	    if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}#endif	    current_sym_code = N_LSYM;	    current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (parms), 0));	    current_sym_addr = 0;	    FORCE_TEXT;	    if (DECL_NAME (parms))	      {		current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));		fprintf (asmfile, "%s \"%s:", ASM_STABS_OP,			 IDENTIFIER_POINTER (DECL_NAME (parms)));	      }	    e

⌨️ 快捷键说明

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