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

📄 stabs.c

📁 java 反射机制详解示例,实现类属性及方法修改
💻 C
📖 第 1 页 / 共 5 页
字号:

  /* The second number is always 0, so ignore it too. */
  (void) parse_number (pp, (bfd_boolean *) NULL);
  if (**pp != ';')
    {
      bad_stab (orig);
      return DEBUG_TYPE_NULL;
    }
  ++*pp;

  /* The third number is the number of bits for this type. */
  bits = parse_number (pp, (bfd_boolean *) NULL);

  /* The type *should* end with a semicolon.  If it are embedded
     in a larger type the semicolon may be the only way to know where
     the type ends.  If this type is at the end of the stabstring we
     can deal with the omitted semicolon (but we don't have to like
     it).  Don't bother to complain(), Sun's compiler omits the semicolon
     for "void".  */
  if (**pp == ';')
    ++*pp;

  if (bits == 0)
    return debug_make_void_type (dhandle);

  return debug_make_int_type (dhandle, bits / 8, unsignedp);
}

/* Parse a builtin floating type generated by the Sun compiler.  */

static debug_type
parse_stab_sun_floating_type (dhandle, pp)
     PTR dhandle;
     const char **pp;
{
  const char *orig;
  bfd_vma details;
  bfd_vma bytes;

  orig = *pp;

  /* The first number has more details about the type, for example
     FN_COMPLEX.  */
  details = parse_number (pp, (bfd_boolean *) NULL);
  if (**pp != ';')
    {
      bad_stab (orig);
      return DEBUG_TYPE_NULL;
    }

  /* The second number is the number of bytes occupied by this type */
  bytes = parse_number (pp, (bfd_boolean *) NULL);
  if (**pp != ';')
    {
      bad_stab (orig);
      return DEBUG_TYPE_NULL;
    }
#if 0
   if (details == NF_COMPLEX
      || details == NF_COMPLEX16
      || details == NF_COMPLEX32)
     return debug_make_complex_type (dhandle, bytes);
#endif   

  return debug_make_float_type (dhandle, bytes);      
}

/* Handle an enum type.  */

static debug_type
parse_stab_enum_type (dhandle, pp)
     PTR dhandle;
     const char **pp;
{
  const char *orig;
  const char **names;
  bfd_signed_vma *values;
  unsigned int n;
  unsigned int alloc;

  orig = *pp;

  /* FIXME: gdb checks os9k_stabs here.  */

  /* The aix4 compiler emits an extra field before the enum members;
     my guess is it's a type of some sort.  Just ignore it.  */
  if (**pp == '-')
    {
      while (**pp != ':')
	++*pp;
      ++*pp;
    }

  /* Read the value-names and their values.
     The input syntax is NAME:VALUE,NAME:VALUE, and so on.
     A semicolon or comma instead of a NAME means the end.  */
  alloc = 10;
  names = (const char **) xmalloc (alloc * sizeof *names);
  values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values);
  n = 0;
  while (**pp != '\0' && **pp != ';' && **pp != ',')
    {
      const char *p;
      char *name;
      bfd_signed_vma val;

      p = *pp;
      while (*p != ':')
	++p;

      name = savestring (*pp, p - *pp);

      *pp = p + 1;
      val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
      if (**pp != ',')
	{
	  bad_stab (orig);
	  return DEBUG_TYPE_NULL;
	}
      ++*pp;

      if (n + 1 >= alloc)
	{
	  alloc += 10;
	  names = ((const char **)
		   xrealloc ((PTR) names, alloc * sizeof *names));
	  values = ((bfd_signed_vma *)
		    xrealloc ((PTR) values, alloc * sizeof *values));
	}

      names[n] = name;
      values[n] = val;
      ++n;
    }

  names[n] = NULL;
  values[n] = 0;

  if (**pp == ';')
    ++*pp;

  return debug_make_enum_type (dhandle, names, values);
}

/* Read the description of a structure (or union type) and return an object
   describing the type.

   PP points to a character pointer that points to the next unconsumed token
   in the the stabs string.  For example, given stabs "A:T4=s4a:1,0,32;;",
   *PP will point to "4a:1,0,32;;".  */

static debug_type
parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums)
     PTR dhandle;
     struct stab_handle *info;
     const char *tagname;
     const char **pp;
     bfd_boolean structp;
     const int *typenums;
{
  const char *orig;
  bfd_vma size;
  debug_baseclass *baseclasses;
  debug_field *fields;
  bfd_boolean statics;
  debug_method *methods;
  debug_type vptrbase;
  bfd_boolean ownvptr;

  orig = *pp;

  /* Get the size.  */
  size = parse_number (pp, (bfd_boolean *) NULL);

  /* Get the other information.  */
  if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
      || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
      || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
      || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
				   &ownvptr))
    return DEBUG_TYPE_NULL;

  if (! statics
      && baseclasses == NULL
      && methods == NULL
      && vptrbase == DEBUG_TYPE_NULL
      && ! ownvptr)
    return debug_make_struct_type (dhandle, structp, size, fields);

  return debug_make_object_type (dhandle, structp, size, fields, baseclasses,
				 methods, vptrbase, ownvptr);
}

/* The stabs for C++ derived classes contain baseclass information which
   is marked by a '!' character after the total size.  This function is
   called when we encounter the baseclass marker, and slurps up all the
   baseclass information.

   Immediately following the '!' marker is the number of base classes that
   the class is derived from, followed by information for each base class.
   For each base class, there are two visibility specifiers, a bit offset
   to the base class information within the derived class, a reference to
   the type for the base class, and a terminating semicolon.

   A typical example, with two base classes, would be "!2,020,19;0264,21;".
   						       ^^ ^ ^ ^  ^ ^  ^
	Baseclass information marker __________________|| | | |  | |  |
	Number of baseclasses __________________________| | | |  | |  |
	Visibility specifiers (2) ________________________| | |  | |  |
	Offset in bits from start of class _________________| |  | |  |
	Type number for base class ___________________________|  | |  |
	Visibility specifiers (2) _______________________________| |  |
	Offset in bits from start of class ________________________|  |
	Type number of base class ____________________________________|

  Return true for success, false for failure.  */

static bfd_boolean
parse_stab_baseclasses (dhandle, info, pp, retp)
     PTR dhandle;
     struct stab_handle *info;
     const char **pp;
     debug_baseclass **retp;
{
  const char *orig;
  unsigned int c, i;
  debug_baseclass *classes;

  *retp = NULL;

  orig = *pp;

  if (**pp != '!')
    {
      /* No base classes.  */
      return true;
    }
  ++*pp;

  c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL);

  if (**pp != ',')
    {
      bad_stab (orig);
      return false;
    }
  ++*pp;

  classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp));

  for (i = 0; i < c; i++)
    {
      bfd_boolean virtual;
      enum debug_visibility visibility;
      bfd_vma bitpos;
      debug_type type;

      switch (**pp)
	{
	case '0':
	  virtual = false;
	  break;
	case '1':
	  virtual = true;
	  break;
	default:
	  warn_stab (orig, _("unknown virtual character for baseclass"));
	  virtual = false;
	  break;
	}
      ++*pp;

      switch (**pp)
	{
	case '0':
	  visibility = DEBUG_VISIBILITY_PRIVATE;
	  break;
	case '1':
	  visibility = DEBUG_VISIBILITY_PROTECTED;
	  break;
	case '2':
	  visibility = DEBUG_VISIBILITY_PUBLIC;
	  break;
	default:
	  warn_stab (orig, _("unknown visibility character for baseclass"));
	  visibility = DEBUG_VISIBILITY_PUBLIC;
	  break;
	}
      ++*pp;

      /* The remaining value is the bit offset of the portion of the
	 object corresponding to this baseclass.  Always zero in the
	 absence of multiple inheritance.  */
      bitpos = parse_number (pp, (bfd_boolean *) NULL);
      if (**pp != ',')
	{
	  bad_stab (orig);
	  return false;
	}
      ++*pp;

      type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
			      (debug_type **) NULL);
      if (type == DEBUG_TYPE_NULL)
	return false;

      classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
					 visibility);
      if (classes[i] == DEBUG_BASECLASS_NULL)
	return false;

      if (**pp != ';')
	return false;
      ++*pp;
    }

  classes[i] = DEBUG_BASECLASS_NULL;

  *retp = classes;

  return true;
}

/* Read struct or class data fields.  They have the form:

   	NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;

   At the end, we see a semicolon instead of a field.

   In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
   a static field.

   The optional VISIBILITY is one of:

   	'/0'	(VISIBILITY_PRIVATE)
	'/1'	(VISIBILITY_PROTECTED)
	'/2'	(VISIBILITY_PUBLIC)
	'/9'	(VISIBILITY_IGNORE)

   or nothing, for C style fields with public visibility.

   Returns 1 for success, 0 for failure.  */

static bfd_boolean
parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
     PTR dhandle;
     struct stab_handle *info;
     const char **pp;
     debug_field **retp;
     bfd_boolean *staticsp;
{
  const char *orig;
  const char *p;
  debug_field *fields;
  unsigned int c;
  unsigned int alloc;

  *retp = NULL;
  *staticsp = false;

  orig = *pp;

  c = 0;
  alloc = 10;
  fields = (debug_field *) xmalloc (alloc * sizeof *fields);
  while (**pp != ';')
    {
      /* FIXME: gdb checks os9k_stabs here.  */

      p = *pp;

      /* Add 1 to c to leave room for NULL pointer at end.  */
      if (c + 1 >= alloc)
	{
	  alloc += 10;
	  fields = ((debug_field *)
		    xrealloc ((PTR) fields, alloc * sizeof *fields));
	}

      /* If it starts with CPLUS_MARKER it is a special abbreviation,
	 unless the CPLUS_MARKER is followed by an underscore, in
	 which case it is just the name of an anonymous type, which we
	 should handle like any other type name.  We accept either '$'
	 or '.', because a field name can never contain one of these
	 characters except as a CPLUS_MARKER.  */

      if ((*p == '$' || *p == '.') && p[1] != '_')
	{
	  ++*pp;
	  if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
	    return false;
	  ++c;
	  continue;
	}

      /* Look for the ':' that separates the field name from the field
	 values.  Data members are delimited by a single ':', while member
	 functions are delimited by a pair of ':'s.  When we hit the member
	 functions (if any), terminate scan loop and return. */

      p = strchr (p, ':');
      if (p == NULL)
	{
	  bad_stab (orig);
	  return false;
	}

      if (p[1] == ':')
	break;

      if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
					 staticsp))
	return false;

      ++c;
    }

  fields[c] = DEBUG_FIELD_NULL;

  *retp = fields;

  return true;
}

/* Special GNU C++ name.  */

static bfd_boolean
parse_stab_cpp_abbrev (dhandle, info, pp, retp)
     PTR dhandle;
     struct stab_handle *info;
     const char **pp;
     debug_field *retp;
{
  const char *orig;
  int cpp_abbrev;
  debug_type context;
  const char *name;
  const char *typename;
  debug_type type;
  bfd_vma bitpos;

  *retp = DEBUG_FIELD_NULL;

  orig = *pp;

  if (**pp != 'v')
    {
      bad_stab (*pp);
      return false;
    }
  ++*pp;

  cpp_abbrev = **pp;
  ++*pp;

  /* At this point, *pp points to something like "22:23=*22...", where
     the type number before the ':' is the "context" and everything
     after is a regular type definition.  Lookup the type, find it's
     name, and construct the field name.  */

  context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
			     (debug_type **) NULL);
  if (context == DEBUG_TYPE_NULL)
    return false;

  switch (cpp_abbrev)
    {
    case 'f':
      /* $vf -- a virtual function table pointer.  */
      name = "_vptr$";
      break;
    case 'b':
      /* $vb -- a virtual bsomethingorother */
      typename = debug_get_type_name (dhandle, context);
      if (typename == NULL)
	{
	  warn_stab (orig, _("unnamed $vb type"));
	  typename = "FOO";
	}
      name = concat ("_vb$", typename, (const char *) NULL);
      break;
    default

⌨️ 快捷键说明

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