📄 debug.c
字号:
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 + -