debug.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,665 行 · 第 1/5 页
C
2,665 行
struct debug_type_compare_list{ /* Next type on list. */ struct debug_type_compare_list *next; /* The types we are comparing. */ struct debug_type *t1; struct debug_type *t2;};/* During debug_get_real_type, a linked list of these structures is kept on the stack to avoid infinite recursion. */struct debug_type_real_list{ /* Next type on list. */ struct debug_type_real_list *next; /* The type we are checking. */ struct debug_type *t;};/* Local functions. */static void debug_error PARAMS ((const char *));static struct debug_name *debug_add_to_namespace PARAMS ((struct debug_handle *, struct debug_namespace **, const char *, enum debug_object_kind, enum debug_object_linkage));static struct debug_name *debug_add_to_current_namespace PARAMS ((struct debug_handle *, const char *, enum debug_object_kind, enum debug_object_linkage));static struct debug_type *debug_make_type PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int));static struct debug_type *debug_get_real_type PARAMS ((PTR, debug_type, struct debug_type_real_list *));static boolean debug_write_name PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, struct debug_name *));static boolean debug_write_type PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, struct debug_type *, struct debug_name *));static boolean debug_write_class_type PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, struct debug_type *, const char *));static boolean debug_write_function PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, const char *, enum debug_object_linkage, struct debug_function *));static boolean debug_write_block PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, struct debug_block *));static boolean debug_write_linenos PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, bfd_vma));static boolean debug_set_class_id PARAMS ((struct debug_handle *, const char *, struct debug_type *));static boolean debug_type_samep PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));static boolean debug_class_type_samep PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));/* Issue an error message. */static voiddebug_error (message) const char *message;{ fprintf (stderr, "%s\n", message);}/* Add an object to a namespace. */static struct debug_name *debug_add_to_namespace (info, nsp, name, kind, linkage) struct debug_handle *info ATTRIBUTE_UNUSED; struct debug_namespace **nsp; const char *name; enum debug_object_kind kind; enum debug_object_linkage linkage;{ struct debug_name *n; struct debug_namespace *ns; n = (struct debug_name *) xmalloc (sizeof *n); memset (n, 0, sizeof *n); n->name = name; n->kind = kind; n->linkage = linkage; ns = *nsp; if (ns == NULL) { ns = (struct debug_namespace *) xmalloc (sizeof *ns); memset (ns, 0, sizeof *ns); ns->tail = &ns->list; *nsp = ns; } *ns->tail = n; ns->tail = &n->next; return n;}/* Add an object to the current namespace. */static struct debug_name *debug_add_to_current_namespace (info, name, kind, linkage) struct debug_handle *info; const char *name; enum debug_object_kind kind; enum debug_object_linkage linkage;{ struct debug_namespace **nsp; if (info->current_unit == NULL || info->current_file == NULL) { debug_error (_("debug_add_to_current_namespace: no current file")); return NULL; } if (info->current_block != NULL) nsp = &info->current_block->locals; else nsp = &info->current_file->globals; return debug_add_to_namespace (info, nsp, name, kind, linkage);}/* Return a handle for debugging information. */PTRdebug_init (){ struct debug_handle *ret; ret = (struct debug_handle *) xmalloc (sizeof *ret); memset (ret, 0, sizeof *ret); return (PTR) ret;}/* Set the source filename. This implicitly starts a new compilation unit. */booleandebug_set_filename (handle, name) PTR handle; const char *name;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_file *nfile; struct debug_unit *nunit; if (name == NULL) name = ""; nfile = (struct debug_file *) xmalloc (sizeof *nfile); memset (nfile, 0, sizeof *nfile); nfile->filename = name; nunit = (struct debug_unit *) xmalloc (sizeof *nunit); memset (nunit, 0, sizeof *nunit); nunit->files = nfile; info->current_file = nfile; if (info->current_unit != NULL) info->current_unit->next = nunit; else { assert (info->units == NULL); info->units = nunit; } info->current_unit = nunit; info->current_function = NULL; info->current_block = NULL; info->current_lineno = NULL; return true;}/* Change source files to the given file name. This is used for include files in a single compilation unit. */booleandebug_start_source (handle, name) PTR handle; const char *name;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_file *f, **pf; if (name == NULL) name = ""; if (info->current_unit == NULL) { debug_error (_("debug_start_source: no debug_set_filename call")); return false; } for (f = info->current_unit->files; f != NULL; f = f->next) { if (f->filename[0] == name[0] && f->filename[1] == name[1] && strcmp (f->filename, name) == 0) { info->current_file = f; return true; } } f = (struct debug_file *) xmalloc (sizeof *f); memset (f, 0, sizeof *f); f->filename = name; for (pf = &info->current_file->next; *pf != NULL; pf = &(*pf)->next) ; *pf = f; info->current_file = f; return true;}/* Record a function definition. This implicitly starts a function block. The debug_type argument is the type of the return value. The boolean indicates whether the function is globally visible. The bfd_vma is the address of the start of the function. Currently the parameter types are specified by calls to debug_record_parameter. FIXME: There is no way to specify nested functions. */booleandebug_record_function (handle, name, return_type, global, addr) PTR handle; const char *name; debug_type return_type; boolean global; bfd_vma addr;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_function *f; struct debug_block *b; struct debug_name *n; if (name == NULL) name = ""; if (return_type == NULL) return false; if (info->current_unit == NULL) { debug_error (_("debug_record_function: no debug_set_filename call")); return false; } f = (struct debug_function *) xmalloc (sizeof *f); memset (f, 0, sizeof *f); f->return_type = return_type; b = (struct debug_block *) xmalloc (sizeof *b); memset (b, 0, sizeof *b); b->start = addr; b->end = (bfd_vma) -1; f->blocks = b; info->current_function = f; info->current_block = b; /* FIXME: If we could handle nested functions, this would be the place: we would want to use a different namespace. */ n = debug_add_to_namespace (info, &info->current_file->globals, name, DEBUG_OBJECT_FUNCTION, (global ? DEBUG_LINKAGE_GLOBAL : DEBUG_LINKAGE_STATIC)); if (n == NULL) return false; n->u.function = f; return true;}/* Record a parameter for the current function. */booleandebug_record_parameter (handle, name, type, kind, val) PTR handle; const char *name; debug_type type; enum debug_parm_kind kind; bfd_vma val;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_parameter *p, **pp; if (name == NULL || type == NULL) return false; if (info->current_unit == NULL || info->current_function == NULL) { debug_error (_("debug_record_parameter: no current function")); return false; } p = (struct debug_parameter *) xmalloc (sizeof *p); memset (p, 0, sizeof *p); p->name = name; p->type = type; p->kind = kind; p->val = val; for (pp = &info->current_function->parameters; *pp != NULL; pp = &(*pp)->next) ; *pp = p; return true;}/* End a function. FIXME: This should handle function nesting. */booleandebug_end_function (handle, addr) PTR handle; bfd_vma addr;{ struct debug_handle *info = (struct debug_handle *) handle; if (info->current_unit == NULL || info->current_block == NULL || info->current_function == NULL) { debug_error (_("debug_end_function: no current function")); return false; } if (info->current_block->parent != NULL) { debug_error (_("debug_end_function: some blocks were not closed")); return false; } info->current_block->end = addr; info->current_function = NULL; info->current_block = NULL; return true;}/* Start a block in a function. All local information will be recorded in this block, until the matching call to debug_end_block. debug_start_block and debug_end_block may be nested. The bfd_vma argument is the address at which this block starts. */booleandebug_start_block (handle, addr) PTR handle; bfd_vma addr;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_block *b, **pb; /* We must always have a current block: debug_record_function sets one up. */ if (info->current_unit == NULL || info->current_block == NULL) { debug_error (_("debug_start_block: no current block")); return false; } b = (struct debug_block *) xmalloc (sizeof *b); memset (b, 0, sizeof *b); b->parent = info->current_block; b->start = addr; b->end = (bfd_vma) -1; /* This new block is a child of the current block. */ for (pb = &info->current_block->children; *pb != NULL; pb = &(*pb)->next) ; *pb = b; info->current_block = b; return true;}/* Finish a block in a function. This matches the call to debug_start_block. The argument is the address at which this block ends. */booleandebug_end_block (handle, addr) PTR handle; bfd_vma addr;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_block *parent; if (info->current_unit == NULL || info->current_block == NULL) { debug_error (_("debug_end_block: no current block")); return false; } parent = info->current_block->parent; if (parent == NULL) { debug_error (_("debug_end_block: attempt to close top level block")); return false; } info->current_block->end = addr; info->current_block = parent; return true;}/* Associate a line number in the current source file and function with a given address. */booleandebug_record_line (handle, lineno, addr) PTR handle; unsigned long lineno; bfd_vma addr;{ struct debug_handle *info = (struct debug_handle *) handle; struct debug_lineno *l; unsigned int i; if (info->current_unit == NULL) { debug_error (_("debug_record_line: no current unit")); return false; } l = info->current_lineno; if (l != NULL && l->file == info->current_file) { for (i = 0; i < DEBUG_LINENO_COUNT; i++) { if (l->linenos[i] == (unsigned long) -1) { l->linenos[i] = lineno; l->addrs[i] = addr; return true; } } } /* If we get here, then either 1) there is no current_lineno structure, which means this is the first line number in this compilation unit, 2) the current_lineno structure is for a different file, or 3) the current_lineno structure is full. Regardless, we want to allocate a new debug_lineno structure, put it in the right place, and make it the new current_lineno structure. */ l = (struct debug_lineno *) xmalloc (sizeof *l); memset (l, 0, sizeof *l); l->file = info->current_file; l->linenos[0] = lineno; l->addrs[0] = addr; for (i = 1; i < DEBUG_LINENO_COUNT; i++) l->linenos[i] = (unsigned long) -1; if (info->current_lineno != NULL) info->current_lineno->next = l; else info->current_unit->linenos = l; info->current_lineno = l; return true;}/* Start a named common block. This is a block of variables that may move in memory. */booleandebug_start_common_block (handle, name) PTR handle ATTRIBUTE_UNUSED; const char *name ATTRIBUTE_UNUSED;{ /* FIXME */ debug_error (_("debug_start_common_block: not implemented")); return false;}/* End a named common block. */booleandebug_end_common_block (handle, name) PTR handle ATTRIBUTE_UNUSED; const char *name ATTRIBUTE_UNUSED;{ /* FIXME */ debug_error (_("debug_end_common_block: not implemented")); return false;}/* Record a named integer constant. */booleandebug_record_int_const (handle, name, val) PTR handle;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?