wrstabs.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,416 行 · 第 1/4 页
C
2,416 行
/* wrstabs.c -- Output stabs debugging information Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc. Written by Ian Lance Taylor <ian@cygnus.com>. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* This file contains code which writes out stabs debugging information. */#include <stdio.h>#include <ctype.h>#include <assert.h>#include "bfd.h"#include "bucomm.h"#include "libiberty.h"#include "debug.h"#include "budbg.h"/* Meaningless definition needs by aout64.h. FIXME. */#define BYTES_IN_WORD 4#include "aout/aout64.h"#include "aout/stab_gnu.h"/* The size of a stabs symbol. This presumes 32 bit values. */#define STAB_SYMBOL_SIZE (12)/* An entry in a string hash table. */struct string_hash_entry{ struct bfd_hash_entry root; /* Next string in this table. */ struct string_hash_entry *next; /* Index in string table. */ long index; /* Size of type if this is a typedef. */ unsigned int size;};/* A string hash table. */struct string_hash_table{ struct bfd_hash_table table;};/* The type stack. Each element on the stack is a string. */struct stab_type_stack{ /* The next element on the stack. */ struct stab_type_stack *next; /* This element as a string. */ char *string; /* The type index of this element. */ long index; /* The size of the type. */ unsigned int size; /* Whether type string defines a new type. */ boolean definition; /* String defining struct fields. */ char *fields; /* NULL terminated array of strings defining base classes for a class. */ char **baseclasses; /* String defining class methods. */ char *methods; /* String defining vtable pointer for a class. */ char *vtable;};/* This structure is used to keep track of type indices for tagged types. */struct stab_tag{ /* The type index. */ long index; /* The tag name. */ const char *tag; /* The kind of type. This is set to DEBUG_KIND_ILLEGAL when the type is defined. */ enum debug_type_kind kind; /* The size of the struct. */ unsigned int size;};/* We remember various sorts of type indices. They are not related, but, for convenience, we keep all the information in this structure. */struct stab_type_cache{ /* The void type index. */ long void_type; /* Signed integer type indices, indexed by size - 1. */ long signed_integer_types[8]; /* Unsigned integer type indices, indexed by size - 1. */ long unsigned_integer_types[8]; /* Floating point types, indexed by size - 1. */ long float_types[16]; /* Pointers to types, indexed by the type index. */ long *pointer_types; size_t pointer_types_alloc; /* Functions returning types, indexed by the type index. */ long *function_types; size_t function_types_alloc; /* References to types, indexed by the type index. */ long *reference_types; size_t reference_types_alloc; /* Struct/union/class type indices, indexed by the struct id. */ struct stab_tag *struct_types; size_t struct_types_alloc;};/* This is the handle passed through debug_write. */struct stab_write_handle{ /* The BFD. */ bfd *abfd; /* This buffer holds the symbols. */ bfd_byte *symbols; size_t symbols_size; size_t symbols_alloc; /* This is a list of hash table entries for the strings. */ struct string_hash_entry *strings; /* The last string hash table entry. */ struct string_hash_entry *last_string; /* The size of the strings. */ size_t strings_size; /* This hash table eliminates duplicate strings. */ struct string_hash_table strhash; /* The type stack. */ struct stab_type_stack *type_stack; /* The next type index. */ long type_index; /* The type cache. */ struct stab_type_cache type_cache; /* A mapping from typedef names to type indices. */ struct string_hash_table typedef_hash; /* If this is not -1, it is the offset to the most recent N_SO symbol, and the value of that symbol needs to be set. */ long so_offset; /* If this is not -1, it is the offset to the most recent N_FUN symbol, and the value of that symbol needs to be set. */ long fun_offset; /* The last text section address seen. */ bfd_vma last_text_address; /* The block nesting depth. */ unsigned int nesting; /* The function address. */ bfd_vma fnaddr; /* A pending LBRAC symbol. */ bfd_vma pending_lbrac; /* The current line number file name. */ const char *lineno_filename;};static struct bfd_hash_entry *string_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static boolean stab_write_symbol PARAMS ((struct stab_write_handle *, int, int, bfd_vma, const char *));static boolean stab_push_string PARAMS ((struct stab_write_handle *, const char *, long, boolean, unsigned int));static boolean stab_push_defined_type PARAMS ((struct stab_write_handle *, long, unsigned int));static char *stab_pop_type PARAMS ((struct stab_write_handle *));static boolean stab_modify_type PARAMS ((struct stab_write_handle *, int, unsigned int, long **, size_t *));static long stab_get_struct_index PARAMS ((struct stab_write_handle *, const char *, unsigned int, enum debug_type_kind, unsigned int *));static boolean stab_class_method_var PARAMS ((struct stab_write_handle *, const char *, enum debug_visibility, boolean, boolean, boolean, bfd_vma, boolean));static boolean stab_start_compilation_unit PARAMS ((PTR, const char *));static boolean stab_start_source PARAMS ((PTR, const char *));static boolean stab_empty_type PARAMS ((PTR));static boolean stab_void_type PARAMS ((PTR));static boolean stab_int_type PARAMS ((PTR, unsigned int, boolean));static boolean stab_float_type PARAMS ((PTR, unsigned int));static boolean stab_complex_type PARAMS ((PTR, unsigned int));static boolean stab_bool_type PARAMS ((PTR, unsigned int));static boolean stab_enum_type PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));static boolean stab_pointer_type PARAMS ((PTR));static boolean stab_function_type PARAMS ((PTR, int, boolean));static boolean stab_reference_type PARAMS ((PTR));static boolean stab_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));static boolean stab_array_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));static boolean stab_set_type PARAMS ((PTR, boolean));static boolean stab_offset_type PARAMS ((PTR));static boolean stab_method_type PARAMS ((PTR, boolean, int, boolean));static boolean stab_const_type PARAMS ((PTR));static boolean stab_volatile_type PARAMS ((PTR));static boolean stab_start_struct_type PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));static boolean stab_struct_field PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));static boolean stab_end_struct_type PARAMS ((PTR));static boolean stab_start_class_type PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, boolean));static boolean stab_class_static_member PARAMS ((PTR, const char *, const char *, enum debug_visibility));static boolean stab_class_baseclass PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));static boolean stab_class_start_method PARAMS ((PTR, const char *));static boolean stab_class_method_variant PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, bfd_vma, boolean));static boolean stab_class_static_method_variant PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));static boolean stab_class_end_method PARAMS ((PTR));static boolean stab_end_class_type PARAMS ((PTR));static boolean stab_typedef_type PARAMS ((PTR, const char *));static boolean stab_tag_type PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));static boolean stab_typdef PARAMS ((PTR, const char *));static boolean stab_tag PARAMS ((PTR, const char *));static boolean stab_int_constant PARAMS ((PTR, const char *, bfd_vma));static boolean stab_float_constant PARAMS ((PTR, const char *, double));static boolean stab_typed_constant PARAMS ((PTR, const char *, bfd_vma));static boolean stab_variable PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));static boolean stab_start_function PARAMS ((PTR, const char *, boolean));static boolean stab_function_parameter PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));static boolean stab_start_block PARAMS ((PTR, bfd_vma));static boolean stab_end_block PARAMS ((PTR, bfd_vma));static boolean stab_end_function PARAMS ((PTR));static boolean stab_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));static const struct debug_write_fns stab_fns ={ stab_start_compilation_unit, stab_start_source, stab_empty_type, stab_void_type, stab_int_type, stab_float_type, stab_complex_type, stab_bool_type, stab_enum_type, stab_pointer_type, stab_function_type, stab_reference_type, stab_range_type, stab_array_type, stab_set_type, stab_offset_type, stab_method_type, stab_const_type, stab_volatile_type, stab_start_struct_type, stab_struct_field, stab_end_struct_type, stab_start_class_type, stab_class_static_member, stab_class_baseclass, stab_class_start_method, stab_class_method_variant, stab_class_static_method_variant, stab_class_end_method, stab_end_class_type, stab_typedef_type, stab_tag_type, stab_typdef, stab_tag, stab_int_constant, stab_float_constant, stab_typed_constant, stab_variable, stab_start_function, stab_function_parameter, stab_start_block, stab_end_block, stab_end_function, stab_lineno};/* Routine to create an entry in a string hash table. */static struct bfd_hash_entry *string_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct string_hash_entry *ret = (struct string_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == (struct string_hash_entry *) NULL) ret = ((struct string_hash_entry *) bfd_hash_allocate (table, sizeof (struct string_hash_entry))); if (ret == (struct string_hash_entry *) NULL) return NULL; /* Call the allocation method of the superclass. */ ret = ((struct string_hash_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret) { /* Initialize the local fields. */ ret->next = NULL; ret->index = -1; ret->size = 0; } return (struct bfd_hash_entry *) ret;}/* Look up an entry in a string hash table. */#define string_hash_lookup(t, string, create, copy) \ ((struct string_hash_entry *) \ bfd_hash_lookup (&(t)->table, (string), (create), (copy)))/* Add a symbol to the stabs debugging information we are building. */static booleanstab_write_symbol (info, type, desc, value, string) struct stab_write_handle *info; int type; int desc; bfd_vma value; const char *string;{ bfd_size_type strx; bfd_byte sym[STAB_SYMBOL_SIZE]; if (string == NULL) strx = 0; else { struct string_hash_entry *h; h = string_hash_lookup (&info->strhash, string, true, true); if (h == NULL) { non_fatal (_("string_hash_lookup failed: %s"), bfd_errmsg (bfd_get_error ())); return false; } if (h->index != -1) strx = h->index; else { strx = info->strings_size; h->index = strx; if (info->last_string == NULL) info->strings = h; else info->last_string->next = h; info->last_string = h; info->strings_size += strlen (string) + 1; } } /* This presumes 32 bit values. */ bfd_put_32 (info->abfd, strx, sym); bfd_put_8 (info->abfd, type, sym + 4); bfd_put_8 (info->abfd, 0, sym + 5); bfd_put_16 (info->abfd, desc, sym + 6); bfd_put_32 (info->abfd, value, sym + 8); if (info->symbols_size + STAB_SYMBOL_SIZE > info->symbols_alloc) { info->symbols_alloc *= 2; info->symbols = (bfd_byte *) xrealloc (info->symbols, info->symbols_alloc); } memcpy (info->symbols + info->symbols_size, sym, STAB_SYMBOL_SIZE); info->symbols_size += STAB_SYMBOL_SIZE; return true;}/* Push a string on to the type stack. */static booleanstab_push_string (info, string, index, definition, size) struct stab_write_handle *info; const char *string; long index; boolean definition; unsigned int size;{ struct stab_type_stack *s; s = (struct stab_type_stack *) xmalloc (sizeof *s); s->string = xstrdup (string); s->index = index; s->definition = definition; s->size = size; s->fields = NULL; s->baseclasses = NULL; s->methods = NULL; s->vtable = NULL; s->next = info->type_stack; info->type_stack = s; return true;}/* Push a type index which has already been defined. */static booleanstab_push_defined_type (info, index, size) struct stab_write_handle *info; long index; unsigned int size;{ char buf[20]; sprintf (buf, "%ld", index); return stab_push_string (info, buf, index, false, size);}/* Pop a type off the type stack. The caller is responsible for freeing the string. */static char *stab_pop_type (info) struct stab_write_handle *info;{ struct stab_type_stack *s; char *ret; s = info->type_stack; assert (s != NULL); info->type_stack = s->next; ret = s->string; free (s); return ret;}/* The general routine to write out stabs in sections debugging information. This accumulates the stabs symbols and the strings in two obstacks. We can't easily write out the information as we go along, because we need to know the section sizes before we can write out the section contents. ABFD is the BFD and DHANDLE is the handle for the debugging information. This sets *PSYMS to point to the symbols, *PSYMSIZE the size of the symbols, *PSTRINGS to the strings, and *PSTRINGSIZE to the size of the strings. */booleanwrite_stabs_in_sections_debugging_info (abfd, dhandle, psyms, psymsize, pstrings, pstringsize) bfd *abfd; PTR dhandle; bfd_byte **psyms; bfd_size_type *psymsize; bfd_byte **pstrings; bfd_size_type *pstringsize;{ struct stab_write_handle info; struct string_hash_entry *h; bfd_byte *p; info.abfd = abfd; info.symbols_size = 0; info.symbols_alloc = 500; info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc); info.strings = NULL; info.last_string = NULL; /* Reserve 1 byte for a null byte. */ info.strings_size = 1; if (! bfd_hash_table_init (&info.strhash.table, string_hash_newfunc) || ! bfd_hash_table_init (&info.typedef_hash.table, string_hash_newfunc)) { non_fatal ("bfd_hash_table_init_failed: %s", bfd_errmsg (bfd_get_error ())); return false; } info.type_stack = NULL; info.type_index = 1; memset (&info.type_cache, 0, sizeof info.type_cache); info.so_offset = -1; info.fun_offset = -1; info.last_text_address = 0; info.nesting = 0; info.fnaddr = 0; info.pending_lbrac = (bfd_vma) -1; /* The initial symbol holds the string size. */ if (! stab_write_symbol (&info, 0, 0, 0, (const char *) NULL)) return false; /* Output an initial N_SO symbol. */ info.so_offset = info.symbols_size; if (! stab_write_symbol (&info, N_SO, 0, 0, bfd_get_filename (abfd))) return false; if (! debug_write (dhandle, &stab_fns, (PTR) &info)) return false; assert (info.pending_lbrac == (bfd_vma) -1); /* Output a trailing N_SO. */ if (! stab_write_symbol (&info, N_SO, 0, info.last_text_address, (const char *) NULL)) return false; /* Put the string size in the initial symbol. */ bfd_put_32 (abfd, info.strings_size, info.symbols + 8); *psyms = info.symbols; *psymsize = info.symbols_size; *pstringsize = info.strings_size; *pstrings = (bfd_byte *) xmalloc (info.strings_size); p = *pstrings; *p++ = '\0'; for (h = info.strings; h != NULL; h = h->next) { strcpy ((char *) p, h->root.string); p += strlen ((char *) p) + 1; } return true;}/* Start writing out information for a compilation unit. */static booleanstab_start_compilation_unit (p, filename) PTR p; const char *filename;{ struct stab_write_handle *info = (struct stab_write_handle *) p; /* We would normally output an N_SO symbol here. However, that would force us to reset all of our type information. I think we will be better off just outputting an N_SOL symbol, and not worrying about splitting information between files. */ info->lineno_filename = filename; return stab_write_symbol (info, N_SOL, 0, 0, filename);}/* Start writing out information for a particular source file. */static booleanstab_start_source (p, filename) PTR p; const char *filename;{ struct stab_write_handle *info = (struct stab_write_handle *) p; /* FIXME: The symbol's value is supposed to be the text section address. However, we would have to fill it in later, and gdb doesn't care, so we don't bother with it. */ info->lineno_filename = filename; return stab_write_symbol (info, N_SOL, 0, 0, filename);}/* Push an empty type. This shouldn't normally happen. We just use a void type. */static booleanstab_empty_type (p) PTR p;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?