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

📄 debug.c

📁 java 反射机制详解示例,实现类属性及方法修改
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (type == NULL)
    return NULL;
  type = debug_get_real_type (handle, type, NULL);
  if (type == NULL)
    return NULL;
  switch (type->kind)
    {
    default:
      return NULL;
    case DEBUG_KIND_STRUCT:
    case DEBUG_KIND_UNION:
    case DEBUG_KIND_CLASS:
    case DEBUG_KIND_UNION_CLASS:
      return type->u.kclass->fields;
    }
  /*NOTREACHED*/
}

/* Get the type of a field.  */

/*ARGSUSED*/
debug_type
debug_get_field_type (handle, field)
     PTR handle ATTRIBUTE_UNUSED;
     debug_field field;
{
  if (field == NULL)
    return NULL;
  return field->type;
}

/* Get the name of a field.  */

/*ARGSUSED*/
const char *
debug_get_field_name (handle, field)
     PTR handle ATTRIBUTE_UNUSED;
     debug_field field;
{
  if (field == NULL)
    return NULL;
  return field->name;
}

/* Get the bit position of a field.  */

/*ARGSUSED*/
bfd_vma
debug_get_field_bitpos (handle, field)
     PTR handle ATTRIBUTE_UNUSED;
     debug_field field;
{
  if (field == NULL || field->static_member)
    return (bfd_vma) -1;
  return field->u.f.bitpos;
}

/* Get the bit size of a field.  */

/*ARGSUSED*/
bfd_vma
debug_get_field_bitsize (handle, field)
     PTR handle ATTRIBUTE_UNUSED;
     debug_field field;
{
  if (field == NULL || field->static_member)
    return (bfd_vma) -1;
  return field->u.f.bitsize;
}

/* Get the visibility of a field.  */

/*ARGSUSED*/
enum debug_visibility
debug_get_field_visibility (handle, field)
     PTR handle ATTRIBUTE_UNUSED;
     debug_field field;
{
  if (field == NULL)
    return DEBUG_VISIBILITY_IGNORE;
  return field->visibility;
}

/* Get the physical name of a field.  */

const char *
debug_get_field_physname (handle, field)
     PTR handle ATTRIBUTE_UNUSED;
     debug_field field;
{
  if (field == NULL || ! field->static_member)
    return NULL;
  return field->u.s.physname;
}

/* Write out the debugging information.  This is given a handle to
   debugging information, and a set of function pointers to call.  */

bfd_boolean
debug_write (handle, fns, fhandle)
     PTR handle;
     const struct debug_write_fns *fns;
     PTR fhandle;
{
  struct debug_handle *info = (struct debug_handle *) handle;
  struct debug_unit *u;

  /* We use a mark to tell whether we have already written out a
     particular name.  We use an integer, so that we don't have to
     clear the mark fields if we happen to write out the same
     information more than once.  */
  ++info->mark;

  /* The base_id field holds an ID value which will never be used, so
     that we can tell whether we have assigned an ID during this call
     to debug_write.  */
  info->base_id = info->class_id;

  /* We keep a linked list of classes for which was have assigned ID's
     during this call to debug_write.  */
  info->id_list = NULL;

  for (u = info->units; u != NULL; u = u->next)
    {
      struct debug_file *f;
      bfd_boolean first_file;

      info->current_write_lineno = u->linenos;
      info->current_write_lineno_index = 0;

      if (! (*fns->start_compilation_unit) (fhandle, u->files->filename))
	return false;

      first_file = true;
      for (f = u->files; f != NULL; f = f->next)
	{
	  struct debug_name *n;

	  if (first_file)
	    first_file = false;
	  else
	    {
	      if (! (*fns->start_source) (fhandle, f->filename))
		return false;
	    }

	  if (f->globals != NULL)
	    {
	      for (n = f->globals->list; n != NULL; n = n->next)
		{
		  if (! debug_write_name (info, fns, fhandle, n))
		    return false;
		}
	    }
	}

      /* Output any line number information which hasn't already been
         handled.  */
      if (! debug_write_linenos (info, fns, fhandle, (bfd_vma) -1))
        return false;
    }

  return true;
}

/* Write out an element in a namespace.  */

static bfd_boolean
debug_write_name (info, fns, fhandle, n)
     struct debug_handle *info;
     const struct debug_write_fns *fns;
     PTR fhandle;
     struct debug_name *n;
{
  switch (n->kind)
    {
    case DEBUG_OBJECT_TYPE:
      if (! debug_write_type (info, fns, fhandle, n->u.type, n)
	  || ! (*fns->typdef) (fhandle, n->name))
	return false;
      return true;
    case DEBUG_OBJECT_TAG:
      if (! debug_write_type (info, fns, fhandle, n->u.tag, n))
	return false;
      return (*fns->tag) (fhandle, n->name);
    case DEBUG_OBJECT_VARIABLE:
      if (! debug_write_type (info, fns, fhandle, n->u.variable->type,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->variable) (fhandle, n->name, n->u.variable->kind,
			       n->u.variable->val);
    case DEBUG_OBJECT_FUNCTION:
      return debug_write_function (info, fns, fhandle, n->name,
				   n->linkage, n->u.function);
    case DEBUG_OBJECT_INT_CONSTANT:
      return (*fns->int_constant) (fhandle, n->name, n->u.int_constant);
    case DEBUG_OBJECT_FLOAT_CONSTANT:
      return (*fns->float_constant) (fhandle, n->name, n->u.float_constant);
    case DEBUG_OBJECT_TYPED_CONSTANT:
      if (! debug_write_type (info, fns, fhandle, n->u.typed_constant->type,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->typed_constant) (fhandle, n->name,
				     n->u.typed_constant->val);
    default:
      abort ();
      return false;
    }
  /*NOTREACHED*/
}

/* Write out a type.  If the type is DEBUG_KIND_NAMED or
   DEBUG_KIND_TAGGED, then the name argument is the name for which we
   are about to call typedef or tag.  If the type is anything else,
   then the name argument is a tag from a DEBUG_KIND_TAGGED type which
   points to this one.  */

static bfd_boolean
debug_write_type (info, fns, fhandle, type, name)
     struct debug_handle *info;
     const struct debug_write_fns *fns;
     PTR fhandle;
     struct debug_type *type;
     struct debug_name *name;
{
  unsigned int i;
  int is;
  const char *tag = NULL;

  /* If we have a name for this type, just output it.  We only output
     typedef names after they have been defined.  We output type tags
     whenever we are not actually defining them.  */
  if ((type->kind == DEBUG_KIND_NAMED
       || type->kind == DEBUG_KIND_TAGGED)
      && (type->u.knamed->name->mark == info->mark
	  || (type->kind == DEBUG_KIND_TAGGED
	      && type->u.knamed->name != name)))
    {
      if (type->kind == DEBUG_KIND_NAMED)
	return (*fns->typedef_type) (fhandle, type->u.knamed->name->name);
      else
	{
	  struct debug_type *real;
	  unsigned int id;
          
	  real = debug_get_real_type ((PTR) info, type, NULL);
	  if (real == NULL)
	    return (*fns->empty_type) (fhandle);
	  id = 0;
	  if ((real->kind == DEBUG_KIND_STRUCT
	       || real->kind == DEBUG_KIND_UNION
	       || real->kind == DEBUG_KIND_CLASS
	       || real->kind == DEBUG_KIND_UNION_CLASS)
	      && real->u.kclass != NULL)
	    {
	      if (real->u.kclass->id <= info->base_id)
		{
		  if (! debug_set_class_id (info,
					    type->u.knamed->name->name,
					    real))
		    return false;
		}
	      id = real->u.kclass->id;
	    }

	  return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id,
				   real->kind);
	}
    }

  /* Mark the name after we have already looked for a known name, so
     that we don't just define a type in terms of itself.  We need to
     mark the name here so that a struct containing a pointer to
     itself will work.  */
  if (name != NULL)
    name->mark = info->mark;

  if (name != NULL
      && type->kind != DEBUG_KIND_NAMED
      && type->kind != DEBUG_KIND_TAGGED)
    {
      assert (name->kind == DEBUG_OBJECT_TAG);
      tag = name->name;
    }

  switch (type->kind)
    {
    case DEBUG_KIND_ILLEGAL:
      debug_error ("debug_write_type: illegal type encountered");
      return false;
    case DEBUG_KIND_INDIRECT:
      if (*type->u.kindirect->slot == DEBUG_TYPE_NULL)
	return (*fns->empty_type) (fhandle);
      return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot,
			       name);
    case DEBUG_KIND_VOID:
      return (*fns->void_type) (fhandle);
    case DEBUG_KIND_INT:
      return (*fns->int_type) (fhandle, type->size, type->u.kint);
    case DEBUG_KIND_FLOAT:
      return (*fns->float_type) (fhandle, type->size);
    case DEBUG_KIND_COMPLEX:
      return (*fns->complex_type) (fhandle, type->size);
    case DEBUG_KIND_BOOL:
      return (*fns->bool_type) (fhandle, type->size);
    case DEBUG_KIND_STRUCT:
    case DEBUG_KIND_UNION:
      if (type->u.kclass != NULL)
	{
	  if (type->u.kclass->id <= info->base_id)
	    {
	      if (! debug_set_class_id (info, tag, type))
		return false;
	    }

	  if (info->mark == type->u.kclass->mark)
	    {
	      /* We are currently outputting this struct, or we have
		 already output it.  I don't know if this can happen,
		 but it can happen for a class.  */
	      assert (type->u.kclass->id > info->base_id);
	      return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
				       type->kind);
	    }
	  type->u.kclass->mark = info->mark;
	}

      if (! (*fns->start_struct_type) (fhandle, tag,
				       (type->u.kclass != NULL
					? type->u.kclass->id
					: 0),
				       type->kind == DEBUG_KIND_STRUCT,
				       type->size))
	return false;
      if (type->u.kclass != NULL
	  && type->u.kclass->fields != NULL)
	{
	  for (i = 0; type->u.kclass->fields[i] != NULL; i++)
	    {
	      struct debug_field *f;

	      f = type->u.kclass->fields[i];
	      if (! debug_write_type (info, fns, fhandle, f->type,
				      (struct debug_name *) NULL)
		  || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos,
					     f->u.f.bitsize, f->visibility))
		return false;
	    }
	}
      return (*fns->end_struct_type) (fhandle);
    case DEBUG_KIND_CLASS:
    case DEBUG_KIND_UNION_CLASS:
      return debug_write_class_type (info, fns, fhandle, type, tag);
    case DEBUG_KIND_ENUM:
      if (type->u.kenum == NULL)
	return (*fns->enum_type) (fhandle, tag, (const char **) NULL,
				  (bfd_signed_vma *) NULL);
      return (*fns->enum_type) (fhandle, tag, type->u.kenum->names,
				type->u.kenum->values);
    case DEBUG_KIND_POINTER:
      if (! debug_write_type (info, fns, fhandle, type->u.kpointer,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->pointer_type) (fhandle);
    case DEBUG_KIND_FUNCTION:
      if (! debug_write_type (info, fns, fhandle,
			      type->u.kfunction->return_type,
			      (struct debug_name *) NULL))
	return false;
      if (type->u.kfunction->arg_types == NULL)
	is = -1;
      else
	{
	  for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++)
	    if (! debug_write_type (info, fns, fhandle,
				    type->u.kfunction->arg_types[is],
				    (struct debug_name *) NULL))
	      return false;
	}
      return (*fns->function_type) (fhandle, is,
				    type->u.kfunction->varargs);
    case DEBUG_KIND_REFERENCE:
      if (! debug_write_type (info, fns, fhandle, type->u.kreference,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->reference_type) (fhandle);
    case DEBUG_KIND_RANGE:
      if (! debug_write_type (info, fns, fhandle, type->u.krange->type,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->range_type) (fhandle, type->u.krange->lower,
				 type->u.krange->upper);
    case DEBUG_KIND_ARRAY:
      if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type,
			      (struct debug_name *) NULL)
	  || ! debug_write_type (info, fns, fhandle,
				 type->u.karray->range_type,
				 (struct debug_name *) NULL))
	return false;
      return (*fns->array_type) (fhandle, type->u.karray->lower,
				 type->u.karray->upper,
				 type->u.karray->stringp);
    case DEBUG_KIND_SET:
      if (! debug_write_type (info, fns, fhandle, type->u.kset->type,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->set_type) (fhandle, type->u.kset->bitstringp);
    case DEBUG_KIND_OFFSET:
      if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type,
			      (struct debug_name *) NULL)
	  || ! debug_write_type (info, fns, fhandle,
				 type->u.koffset->target_type,
				 (struct debug_name *) NULL))
	return false;
      return (*fns->offset_type) (fhandle);
    case DEBUG_KIND_METHOD:
      if (! debug_write_type (info, fns, fhandle,
			      type->u.kmethod->return_type,
			      (struct debug_name *) NULL))
	return false;
      if (type->u.kmethod->arg_types == NULL)
	is = -1;
      else
	{
	  for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++)
	    if (! debug_write_type (info, fns, fhandle,
				    type->u.kmethod->arg_types[is],
				    (struct debug_name *) NULL))
	      return false;
	}
      if (type->u.kmethod->domain_type != NULL)
	{
	  if (! debug_write_type (info, fns, fhandle,
				  type->u.kmethod->domain_type,
				  (struct debug_name *) NULL))
	    return false;
	}
      return (*fns->method_type) (fhandle,
				  type->u.kmethod->domain_type != NULL,
				  is,
				  type->u.kmethod->varargs);
    case DEBUG_KIND_CONST:
      if (! debug_write_type (info, fns, fhandle, type->u.kconst,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->const_type) (fhandle);
    case DEBUG_KIND_VOLATILE:
      if (! debug_write_type (info, fns, fhandle, type->u.kvolatile,
			      (struct debug_name *) NULL))
	return false;
      return (*fns->volatile_type) (fhandle);
    case DEBUG_KIND_NAMED:
      return debug_write_type (info, fns, fhandle, type->u.knamed->type,
			       (struct debug_name *) NULL);
    case DEBUG_KIND_TAGGED:
      return debug_write_type (info, fns, fhandle, type->u.knamed->type,
			       type->u.knamed->name);
    default:
      abort ();
      return false;
    }
}

/* Write out a class type.  */

static bfd_boolean
debug_write_class_type (info, fns, fhandle, type, tag)
     struct debug_handle *info;
     const struct debug_write_fns *fns;
     PTR fhandle;
     struct debug_type *type;
     const char *tag;
{
  unsigned int i;
  unsigned int id;
  struct debug_type *vptrbase;

  if (type->u.kclass == NULL)
    {
      id = 0;
      vptrbase = NULL;
    }
  else
    {
      if (type->u.kclass->id <= info->base_id)
	{
	  if (! debug_set_class_id (info, tag, type))
	    return false;
	}

      if (info->mark == type->u.kclass->mark)
	{
	  /* We are currently outputting this class, or we have
	     already output it.  This can happen when there are
	     methods for an anonymous class

⌨️ 快捷键说明

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