debug.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,665 行 · 第 1/5 页
C
2,665 行
PTR handle; const char *name; enum debug_type_kind kind;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_unit *u; /* We search the globals of all the compilation units. I don't know if this is correct or not. It would be easy to change. */ for (u = info->units; u != NULL; u = u->next) { struct debug_file *f; for (f = u->files; f != NULL; f = f->next) { struct debug_name *n; if (f->globals != NULL) { for (n = f->globals->list; n != NULL; n = n->next) { if (n->kind == DEBUG_OBJECT_TAG && (kind == DEBUG_KIND_ILLEGAL || n->u.tag->kind == kind) && n->name[0] == name[0] && strcmp (n->name, name) == 0) return n->u.tag; } } } } return DEBUG_TYPE_NULL;}/* Get a base type. We build a linked list on the stack to avoid crashing if the type is defined circularly. */static struct debug_type *debug_get_real_type (handle, type, list) PTR handle; debug_type type; struct debug_type_real_list *list;{ struct debug_type_real_list *l; struct debug_type_real_list rl; switch (type->kind) { default: return type; case DEBUG_KIND_INDIRECT: case DEBUG_KIND_NAMED: case DEBUG_KIND_TAGGED: break; } for (l = list; l != NULL; l = l->next) { if (l->t == type) { fprintf (stderr, _("debug_get_real_type: circular debug information for %s\n"), debug_get_type_name (handle, type)); return NULL; } } rl.next = list; rl.t = type; switch (type->kind) { /* The default case is just here to avoid warnings. */ default: case DEBUG_KIND_INDIRECT: if (*type->u.kindirect->slot != NULL) return debug_get_real_type (handle, *type->u.kindirect->slot, &rl); return type; case DEBUG_KIND_NAMED: case DEBUG_KIND_TAGGED: return debug_get_real_type (handle, type->u.knamed->type, &rl); } /*NOTREACHED*/}/* Get the kind of a type. */enum debug_type_kinddebug_get_type_kind (handle, type) PTR handle; debug_type type;{ if (type == NULL) return DEBUG_KIND_ILLEGAL; type = debug_get_real_type (handle, type, NULL); if (type == NULL) return DEBUG_KIND_ILLEGAL; return type->kind;}/* Get the name of a type. */const char *debug_get_type_name (handle, type) PTR handle; debug_type type;{ if (type->kind == DEBUG_KIND_INDIRECT) { if (*type->u.kindirect->slot != NULL) return debug_get_type_name (handle, *type->u.kindirect->slot); return type->u.kindirect->tag; } if (type->kind == DEBUG_KIND_NAMED || type->kind == DEBUG_KIND_TAGGED) return type->u.knamed->name->name; return NULL;}/* Get the size of a type. */bfd_vmadebug_get_type_size (handle, type) PTR handle; debug_type type;{ if (type == NULL) return 0; /* We don't call debug_get_real_type, because somebody might have called debug_record_type_size on a named or indirect type. */ if (type->size != 0) return type->size; switch (type->kind) { default: return 0; case DEBUG_KIND_INDIRECT: if (*type->u.kindirect->slot != NULL) return debug_get_type_size (handle, *type->u.kindirect->slot); return 0; case DEBUG_KIND_NAMED: case DEBUG_KIND_TAGGED: return debug_get_type_size (handle, type->u.knamed->type); } /*NOTREACHED*/}/* Get the return type of a function or method type. */debug_typedebug_get_return_type (handle, type) PTR handle; debug_type type;{ if (type == NULL) return DEBUG_TYPE_NULL; type = debug_get_real_type (handle, type, NULL); if (type == NULL) return DEBUG_TYPE_NULL; switch (type->kind) { default: return DEBUG_TYPE_NULL; case DEBUG_KIND_FUNCTION: return type->u.kfunction->return_type; case DEBUG_KIND_METHOD: return type->u.kmethod->return_type; } /*NOTREACHED*/ }/* Get the parameter types of a function or method type (except that we don't currently store the parameter types of a function). */const debug_type *debug_get_parameter_types (handle, type, pvarargs) PTR handle; debug_type type; boolean *pvarargs;{ 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_FUNCTION: *pvarargs = type->u.kfunction->varargs; return type->u.kfunction->arg_types; case DEBUG_KIND_METHOD: *pvarargs = type->u.kmethod->varargs; return type->u.kmethod->arg_types; } /*NOTREACHED*/}/* Get the target type of a type. */debug_typedebug_get_target_type (handle, type) PTR handle; debug_type type;{ 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_POINTER: return type->u.kpointer; case DEBUG_KIND_REFERENCE: return type->u.kreference; case DEBUG_KIND_CONST: return type->u.kconst; case DEBUG_KIND_VOLATILE: return type->u.kvolatile; } /*NOTREACHED*/}/* Get the NULL terminated array of fields for a struct, union, or class. */const debug_field *debug_get_fields (handle, type) PTR handle; debug_type type;{ 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_typedebug_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_vmadebug_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_vmadebug_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_visibilitydebug_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. */booleandebug_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; 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 booleandebug_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 booleandebug_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.ki
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?