stabs.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,559 行 · 第 1/5 页

C
2,559
字号
      if (dtype == DEBUG_TYPE_NULL)	return false;      if (slot != NULL)	*slot = dtype;      break;    case 'T':      /* Struct, union, or enum tag.  For GNU C++, this can be be followed	 by 't' which means we are typedef'ing it as well.  */      if (*p != 't')	{	  synonym = false;	  /* FIXME: gdb sets synonym to true if the current language             is C++.  */	}      else	{	  synonym = true;	  ++p;	}      dtype = parse_stab_type (dhandle, info, name, &p, &slot);      if (dtype == DEBUG_TYPE_NULL)	return false;      if (name == NULL)	return true;      /* INFO->SELF_CROSSREF is set by parse_stab_type if this type is         a cross reference to itself.  These are generated by some         versions of g++.  */      self_crossref = info->self_crossref;      dtype = debug_tag_type (dhandle, name, dtype);      if (dtype == DEBUG_TYPE_NULL)	return false;      if (slot != NULL)	*slot = dtype;      /* See if we have a cross reference to this tag which we can now         fill in.  Avoid filling in a cross reference to ourselves,         because that would lead to circular debugging information.  */      if (! self_crossref)	{	  register struct stab_tag **pst;	  for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)	    {	      if ((*pst)->name[0] == name[0]		  && strcmp ((*pst)->name, name) == 0)		{		  (*pst)->slot = dtype;		  *pst = (*pst)->next;		  break;		}	    }	}      if (synonym)	{	  dtype = debug_name_type (dhandle, name, dtype);	  if (dtype == DEBUG_TYPE_NULL)	    return false;	  if (slot != NULL)	    *slot = dtype;	}      break;    case 'V':      /* Static symbol of local scope */      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,			       (debug_type **) NULL);      if (dtype == DEBUG_TYPE_NULL)	return false;      /* FIXME: gdb checks os9k_stabs here.  */      if (! stab_record_variable (dhandle, info, name, dtype,				  DEBUG_LOCAL_STATIC, value))	return false;      break;    case 'v':      /* Reference parameter.  */      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,			       (debug_type **) NULL);      if (dtype == DEBUG_TYPE_NULL)	return false;      if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,				    value))	return false;      break;    case 'a':      /* Reference parameter which is in a register.  */      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,			       (debug_type **) NULL);      if (dtype == DEBUG_TYPE_NULL)	return false;      if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,				    value))	return false;      break;    case 'X':      /* This is used by Sun FORTRAN for "function result value".	 Sun claims ("dbx and dbxtool interfaces", 2nd ed)	 that Pascal uses it too, but when I tried it Pascal used	 "x:3" (local symbol) instead.  */      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,			       (debug_type **) NULL);      if (dtype == DEBUG_TYPE_NULL)	return false;      if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,				  value))	return false;      break;    default:      bad_stab (string);      return false;    }  /* FIXME: gdb converts structure values to structure pointers in a     couple of cases, depending upon the target.  */  return true;}/* Parse a stabs type.  The typename argument is non-NULL if this is a   typedef or a tag definition.  The pp argument points to the stab   string, and is updated.  The slotp argument points to a place to   store the slot used if the type is being defined.  */static debug_typeparse_stab_type (dhandle, info, typename, pp, slotp)     PTR dhandle;     struct stab_handle *info;     const char *typename;     const char **pp;     debug_type **slotp;{  const char *orig;  int typenums[2];  int size;  boolean stringp;  int descriptor;  debug_type dtype;  if (slotp != NULL)    *slotp = NULL;  orig = *pp;  size = -1;  stringp = false;  info->self_crossref = false;  /* Read type number if present.  The type number may be omitted.     for instance in a two-dimensional array declared with type     "ar1;1;10;ar1;1;10;4".  */  if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')    {      /* 'typenums=' not present, type is anonymous.  Read and return	 the definition, but don't put it in the type vector.  */      typenums[0] = typenums[1] = -1;    }  else    {      if (! parse_stab_type_number (pp, typenums))	return DEBUG_TYPE_NULL;      if (**pp != '=')	{	  /* Type is not being defined here.  Either it already	     exists, or this is a forward reference to it.  */	  return stab_find_type (dhandle, info, typenums);	}      /* Only set the slot if the type is being defined.  This means         that the mapping from type numbers to types will only record         the name of the typedef which defines a type.  If we don't do         this, then something like	     typedef int foo;	     int i;	 will record that i is of type foo.  Unfortunately, stabs	 information is ambiguous about variable types.  For this code,	     typedef int foo;	     int i;	     foo j;	 the stabs information records both i and j as having the same	 type.  This could be fixed by patching the compiler.  */      if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0)	*slotp = stab_find_slot (info, typenums);      /* Type is being defined here.  */      /* Skip the '='.  */      ++*pp;      while (**pp == '@')	{	  const char *p = *pp + 1;	  const char *attr;	  if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')	    {	      /* Member type.  */	      break;	    }	  /* Type attributes.  */	  attr = p;	  for (; *p != ';'; ++p)	    {	      if (*p == '\0')		{		  bad_stab (orig);		  return DEBUG_TYPE_NULL;		}	    }	  *pp = p + 1;	  switch (*attr)	    {	    case 's':	      size = atoi (attr + 1);	      size /= 8;  /* Size is in bits.  We store it in bytes.  */	      if (size <= 0)		size = -1;	      break;	    case 'S':	      stringp = true;	      break;	    default:	      /* Ignore unrecognized type attributes, so future		 compilers can invent new ones.  */	      break;	    }	}    }  descriptor = **pp;  ++*pp;  switch (descriptor)    {    case 'x':      {	enum debug_type_kind code;	const char *q1, *q2, *p;	/* A cross reference to another type.  */	switch (**pp)	  {	  case 's':	    code = DEBUG_KIND_STRUCT;	    break;	  case 'u':	    code = DEBUG_KIND_UNION;	    break;	  case 'e':	    code = DEBUG_KIND_ENUM;	    break;	  default:	    /* Complain and keep going, so compilers can invent new	       cross-reference types.  */	    warn_stab (orig, _("unrecognized cross reference type"));	    code = DEBUG_KIND_STRUCT;	    break;	  }	++*pp;	q1 = strchr (*pp, '<');	p = strchr (*pp, ':');	if (p == NULL)	  {	    bad_stab (orig);	    return DEBUG_TYPE_NULL;	  }	if (q1 != NULL && p > q1 && p[1] == ':')	  {	    int nest = 0;	    for (q2 = q1; *q2 != '\0'; ++q2)	      {		if (*q2 == '<')		  ++nest;		else if (*q2 == '>')		  --nest;		else if (*q2 == ':' && nest == 0)		  break;	      }	    p = q2;	    if (*p != ':')	      {		bad_stab (orig);		return DEBUG_TYPE_NULL;	      }	  }	/* Some versions of g++ can emit stabs like	       fleep:T20=xsfleep:	   which define structures in terms of themselves.  We need to	   tell the caller to avoid building a circular structure.  */	if (typename != NULL	    && strncmp (typename, *pp, p - *pp) == 0	    && typename[p - *pp] == '\0')	  info->self_crossref = true;	dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);	*pp = p + 1;      }      break;    case '-':    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':    case '9':    case '(':      {	const char *hold;	int xtypenums[2];	/* This type is defined as another type.  */	(*pp)--;	hold = *pp;	/* Peek ahead at the number to detect void.  */	if (! parse_stab_type_number (pp, xtypenums))	  return DEBUG_TYPE_NULL;	if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])	  {	    /* This type is being defined as itself, which means that               it is void.  */	    dtype = debug_make_void_type (dhandle);	  }	else	  {	    *pp = hold;	    /* Go back to the number and have parse_stab_type get it.	       This means that we can deal with something like	       t(1,2)=(3,4)=... which the Lucid compiler uses.  */	    dtype = parse_stab_type (dhandle, info, (const char *) NULL,				     pp, (debug_type **) NULL);	    if (dtype == DEBUG_TYPE_NULL)	      return DEBUG_TYPE_NULL;	  }	if (typenums[0] != -1)	  {	    if (! stab_record_type (dhandle, info, typenums, dtype))	      return DEBUG_TYPE_NULL;	  }	break;      }    case '*':      dtype = debug_make_pointer_type (dhandle,				       parse_stab_type (dhandle, info,							(const char *) NULL,							pp,							(debug_type **) NULL));      break;    case '&':      /* Reference to another type.  */      dtype = (debug_make_reference_type	       (dhandle,		parse_stab_type (dhandle, info, (const char *) NULL, pp,				 (debug_type **) NULL)));      break;    case 'f':      /* Function returning another type.  */      /* FIXME: gdb checks os9k_stabs here.  */      dtype = (debug_make_function_type	       (dhandle,		parse_stab_type (dhandle, info, (const char *) NULL, pp,				 (debug_type **) NULL),		(debug_type *) NULL, false));      break;    case 'k':      /* Const qualifier on some type (Sun).  */      /* FIXME: gdb accepts 'c' here if os9k_stabs.  */      dtype = debug_make_const_type (dhandle,				     parse_stab_type (dhandle, info,						      (const char *) NULL,						      pp,						      (debug_type **) NULL));      break;    case 'B':      /* Volatile qual on some type (Sun).  */      /* FIXME: gdb accepts 'i' here if os9k_stabs.  */      dtype = (debug_make_volatile_type	       (dhandle,		parse_stab_type (dhandle, info, (const char *) NULL, pp,				 (debug_type **) NULL)));      break;    case '@':      /* Offset (class & variable) type.  This is used for a pointer         relative to an object.  */      {	debug_type domain;	debug_type memtype;	/* Member type.  */	domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,				  (debug_type **) NULL);	if (domain == DEBUG_TYPE_NULL)	  return DEBUG_TYPE_NULL;	if (**pp != ',')	  {	    bad_stab (orig);	    return DEBUG_TYPE_NULL;	  }	++*pp;	memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,				   (debug_type **) NULL);	if (memtype == DEBUG_TYPE_NULL)	  return DEBUG_TYPE_NULL;	dtype = debug_make_offset_type (dhandle, domain, memtype);      }      break;    case '#':      /* Method (class & fn) type.  */      if (**pp == '#')	{	  debug_type return_type;	  ++*pp;	  return_type = parse_stab_type (dhandle, info, (const char *) NULL,					 pp, (debug_type **) NULL);	  if (return_type == DEBUG_TYPE_NULL)	    return DEBUG_TYPE_NULL;	  if (**pp != ';')	    {	      bad_stab (orig);	      return DEBUG_TYPE_NULL;	    }	  ++*pp;	  dtype = debug_make_method_type (dhandle, return_type,					  DEBUG_TYPE_NULL,					  (debug_type *) NULL, false);	}      else	{	  debug_type domain;	  debug_type return_type;	  debug_type *args;	  unsigned int n;	  unsigned int alloc;	  boolean varargs;	  domain = parse_stab_type (dhandle, info, (const char *) NULL,				    pp, (debug_type **) NULL);	  if (domain == DEBUG_TYPE_NULL)	    return DEBUG_TYPE_NULL;	  if (**pp != ',')	    {	      bad_stab (orig);	      return DEBUG_TYPE_NULL;	    }	  ++*pp;	  return_type = parse_stab_type (dhandle, info, (const char *) NULL,					 pp, (debug_type **) NULL);	  if (return_type == DEBUG_TYPE_NULL)	    return DEBUG_TYPE_NULL;	  alloc = 10;	  args = (debug_type *) xmalloc (alloc * sizeof *args);	  n = 0;	  while (**pp != ';')	    {	      if (**pp != ',')		{		  bad_stab (orig);		  return DEBUG_TYPE_NULL;		}	      ++*pp;	      if (n + 1 >= alloc)		{		  alloc += 10;		  args = ((debug_type *)

⌨️ 快捷键说明

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