diff options
author | gdb-2.4+.aux.coff <gdb@fsf.org> | 1988-01-16 04:39:57 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2012-06-03 15:36:30 +0100 |
commit | 7b4ac7e1ed2c4616bce56d1760807798be87ac9e (patch) | |
tree | 777c9f6aba126e91e4a25d7b1fa34c2213d038da /gdb/symmisc.c | |
download | gdb-7b4ac7e1ed2c4616bce56d1760807798be87ac9e.zip gdb-7b4ac7e1ed2c4616bce56d1760807798be87ac9e.tar.gz gdb-7b4ac7e1ed2c4616bce56d1760807798be87ac9e.tar.bz2 |
gdb-2.4+.aux.coff
Diffstat (limited to 'gdb/symmisc.c')
-rw-r--r-- | gdb/symmisc.c | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/gdb/symmisc.c b/gdb/symmisc.c new file mode 100644 index 0000000..d17cbdd --- /dev/null +++ b/gdb/symmisc.c @@ -0,0 +1,535 @@ +/* Do various things to symbol tables (other than lookup)), for GDB. + Copyright (C) 1986, 1987 Free Software Foundation, Inc. + +GDB is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY. No author or distributor accepts responsibility to anyone +for the consequences of using it or for whether it serves any +particular purpose or works at all, unless he says so in writing. +Refer to the GDB General Public License for full details. + +Everyone is granted permission to copy, modify and redistribute GDB, +but only under the conditions described in the GDB General Public +License. A copy of this license is supposed to have been given to you +along with GDB so you can know your rights and responsibilities. It +should be in a file named COPYING. Among other things, the copyright +notice and this notice must be preserved on all copies. + +In other words, go ahead and share GDB, but don't try to stop +anyone else from sharing it farther. Help stamp out software hoarding! +*/ + + +#include "defs.h" +#include "initialize.h" +#include "symtab.h" + +#include <stdio.h> +#include <obstack.h> + +static void free_symtab (); + +START_FILE + +/* Free all the symtabs that are currently installed, + and all storage associated with them. + Leaves us in a consistent state with no symtabs installed. */ + +void +free_all_symtabs () +{ + register struct symtab *s, *snext; + + /* All values will be invalid because their types will be! */ + + clear_value_history (); + clear_displays (); + clear_internalvars (); + clear_breakpoints (); + set_default_breakpoint (0, 0, 0, 0); + + current_source_symtab = 0; + + for (s = symtab_list; s; s = snext) + { + snext = s->next; + free_symtab (s); + } + symtab_list = 0; + obstack_free (symbol_obstack, 0); + obstack_init (symbol_obstack); + + if (misc_function_vector) + free (misc_function_vector); + misc_function_count = 0; + misc_function_vector = 0; +} + +/* Free a struct block <- B and all the symbols defined in that block. */ + +static void +free_symtab_block (b) + struct block *b; +{ + register int i, n; + n = BLOCK_NSYMS (b); + for (i = 0; i < n; i++) + { + free (SYMBOL_NAME (BLOCK_SYM (b, i))); + free (BLOCK_SYM (b, i)); + } + free (b); +} + +/* Free all the storage associated with the struct symtab <- S. + Note that some symtabs have contents malloc'ed structure by structure, + while some have contents that all live inside one big block of memory, + and some share the contents of another symbol table and so you should + not free the contents on their behalf (except sometimes the linetable, + which maybe per symtab even when the rest is not). + It is s->free_code that says which alternative to use. */ + +static void +free_symtab (s) + register struct symtab *s; +{ + register int i, n; + register struct blockvector *bv; + register struct type *type; + register struct typevector *tv; + + switch (s->free_code) + { + case free_nothing: + /* All the contents are part of a big block of memory + and some other symtab is in charge of freeing that block. + Therefore, do nothing. */ + break; + + case free_explicit: + /* All the contents are part of a big block of memory + and that is our `free_ptr' and will be freed below. */ + break; + + case free_contents: + /* Here all the contents were malloc'ed structure by structure + and must be freed that way. */ + /* First free the blocks (and their symbols. */ + bv = BLOCKVECTOR (s); + n = BLOCKVECTOR_NBLOCKS (bv); + for (i = 0; i < n; i++) + free_symtab_block (BLOCKVECTOR_BLOCK (bv, i)); + /* Free the blockvector itself. */ + free (bv); + /* Free the type vector. */ + tv = TYPEVECTOR (s); + if (tv) /* FIXME, should this happen? It does... */ + free (tv); + /* Also free the linetable. */ + + case free_linetable: + /* Everything will be freed either by our `free_ptr' + or by some other symbatb, except for our linetable. + Free that now. */ + free (LINETABLE (s)); + break; + } + + /* If there is a single block of memory to free, free it. */ + if (s->free_ptr) + free (s->free_ptr); + + if (s->line_charpos) + free (s->line_charpos); + free (s->filename); + free (s); +} + +/* Convert a raw symbol-segment to a struct symtab, + and relocate its internal pointers so that it is valid. */ + +/* This is how to relocate one pointer, given a name for it. + Works independent of the type of object pointed to. */ +#define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0) + +/* This is the inverse of RELOCATE. We use it when storing + a core address into a slot that has yet to be relocated. */ +#define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0) + +/* During the process of relocation, this holds the amount to relocate by + (the address of the file's symtab data, in core in the debugger). */ +static int relocation; + +#define CORE_RELOCATE(slot) \ + ((slot) += (((slot) < data_start) ? text_relocation \ + : ((slot) < bss_start) ? data_relocation : bss_relocation)) + +#define TEXT_RELOCATE(slot) ((slot) += text_relocation) + +/* Relocation amounts for addresses in the program's core image. */ +static int text_relocation, data_relocation, bss_relocation; + +/* Boundaries that divide program core addresses into text, data and bss; + used to determine which relocation amount to use. */ +static int data_start, bss_start; + +static void relocate_typevector (); +static void relocate_blockvector (); +static void relocate_type (); +static void relocate_block (); +static void relocate_symbol (); + +/* Relocate a file symbol table so that all the pointers + are valid C pointers. Pass the struct symtab for the file + and the amount to relocate by. */ + +static struct symtab * +relocate_symtab (root) + struct symbol_root *root; +{ + struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab)); + bzero (sp, sizeof (struct symtab)); + + relocation = (int) root; + text_relocation = root->textrel; + data_relocation = root->datarel; + bss_relocation = root->bssrel; + data_start = root->databeg; + bss_start = root->bssbeg; + + sp->filename = root->filename; + sp->ldsymoff = root->ldsymoff; + sp->language = root->language; + sp->compilation = root->compilation; + sp->version = root->version; + sp->blockvector = root->blockvector; + sp->typevector = root->typevector; + sp->free_code = free_explicit; + sp->free_ptr = (char *) root; + + RELOCATE (TYPEVECTOR (sp)); + RELOCATE (BLOCKVECTOR (sp)); + RELOCATE (sp->version); + RELOCATE (sp->compilation); + RELOCATE (sp->filename); + + relocate_typevector (TYPEVECTOR (sp)); + relocate_blockvector (BLOCKVECTOR (sp)); + + return sp; +} + +static void +relocate_typevector (tv) + struct typevector *tv; +{ + register int ntypes = TYPEVECTOR_NTYPES (tv); + register int i; + + for (i = 0; i < ntypes; i++) + RELOCATE (TYPEVECTOR_TYPE (tv, i)); + for (i = 0; i < ntypes; i++) + relocate_type (TYPEVECTOR_TYPE (tv, i)); +} + +static void +relocate_blockvector (blp) + register struct blockvector *blp; +{ + register int nblocks = BLOCKVECTOR_NBLOCKS (blp); + register int i; + for (i = 0; i < nblocks; i++) + RELOCATE (BLOCKVECTOR_BLOCK (blp, i)); + for (i = 0; i < nblocks; i++) + relocate_block (BLOCKVECTOR_BLOCK (blp, i)); +} + +static void +relocate_block (bp) + register struct block *bp; +{ + register int nsyms = BLOCK_NSYMS (bp); + register int i; + + TEXT_RELOCATE (BLOCK_START (bp)); + TEXT_RELOCATE (BLOCK_END (bp)); + + /* These two should not be recursively processed. + The superblock need not be because all blocks are + processed from relocate_blockvector. + The function need not be because it will be processed + under the block which is its scope. */ + RELOCATE (BLOCK_SUPERBLOCK (bp)); + RELOCATE (BLOCK_FUNCTION (bp)); + + for (i = 0; i < nsyms; i++) + RELOCATE (BLOCK_SYM (bp, i)); + + for (i = 0; i < nsyms; i++) + relocate_symbol (BLOCK_SYM (bp, i)); +} + +static void +relocate_symbol (sp) + register struct symbol *sp; +{ + RELOCATE (SYMBOL_NAME (sp)); + if (SYMBOL_CLASS (sp) == LOC_BLOCK) + { + RELOCATE (SYMBOL_BLOCK_VALUE (sp)); + /* We can assume the block that belongs to this symbol + is not relocated yet, since it comes after + the block that contains this symbol. */ + BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp; + UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp))); + } + else if (SYMBOL_CLASS (sp) == LOC_STATIC) + CORE_RELOCATE (SYMBOL_VALUE (sp)); + else if (SYMBOL_CLASS (sp) == LOC_LABEL) + TEXT_RELOCATE (SYMBOL_VALUE (sp)); + RELOCATE (SYMBOL_TYPE (sp)); +} + +/* We cannot come up with an a priori spanning tree + for the network of types, since types can be used + for many symbols and also as components of other types. + Therefore, we need to be able to mark types that we + already have relocated (or are already in the middle of relocating) + as in a garbage collector. */ + +static void +relocate_type (tp) + register struct type *tp; +{ + register int nfields = TYPE_NFIELDS (tp); + register int i; + + RELOCATE (TYPE_NAME (tp)); + RELOCATE (TYPE_TARGET_TYPE (tp)); + RELOCATE (TYPE_FIELDS (tp)); + RELOCATE (TYPE_POINTER_TYPE (tp)); + + for (i = 0; i < nfields; i++) + { + RELOCATE (TYPE_FIELD_TYPE (tp, i)); + RELOCATE (TYPE_FIELD_NAME (tp, i)); + } +} + +/* Read symsegs from file named NAME open on DESC, + make symtabs from them, and return a chain of them. + Assumes DESC is prepositioned at the end of the string table, + just before the symsegs if there are any. */ + +struct symtab * +read_symsegs (desc, name) + int desc; + char *name; +{ + struct symbol_root root; + register char *data; + register struct symtab *sp, *chain = 0; + register int len; + + while (1) + { + len = myread (desc, &root, sizeof root); + if (len == 0 || root.format == 0) + break; + if (root.format != 1 || + root.length < sizeof root) + error ("Invalid symbol segment format code"); + data = (char *) xmalloc (root.length); + bcopy (&root, data, sizeof root); + len = myread (desc, data + sizeof root, + root.length - sizeof root); + sp = relocate_symtab (data); + sp->next = chain; + chain = sp; + } + + return chain; +} + +static int block_depth (); +static void print_spaces (); +static void print_symbol (); + +print_symtabs (filename) + char *filename; +{ + FILE *outfile; + register struct symtab *s; + register int i, j; + int len, line, blen; + register struct linetable *l; + struct blockvector *bv; + register struct block *b; + int depth; + struct cleanup *cleanups; + extern int fclose(); + + if (filename == 0) + error_no_arg ("file to write symbol data in"); + outfile = fopen (filename, "w"); + + cleanups = make_cleanup (fclose, outfile); + immediate_quit++; + + for (s = symtab_list; s; s = s->next) + { + /* First print the line table. */ + fprintf (outfile, "Symtab for file %s\n\n", s->filename); + fprintf (outfile, "Line table:\n\n"); + l = LINETABLE (s); + len = l->nitems; + for (i = 0; i < len; i++) + { + if (l->item[i] < 0) + line = - l->item[i] - 1; + else + fprintf (outfile, " line %d at %x\n", ++line, l->item[i]); + } + /* Now print the block info. */ + fprintf (outfile, "\nBlockvector:\n\n"); + bv = BLOCKVECTOR (s); + len = BLOCKVECTOR_NBLOCKS (bv); + for (i = 0; i < len; i++) + { + b = BLOCKVECTOR_BLOCK (bv, i); + depth = block_depth (b) * 2; + print_spaces (depth, outfile); + fprintf (outfile, "block #%03d (object 0x%x) ", i, b); + fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b)); + if (BLOCK_SUPERBLOCK (b)) + fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b)); + if (BLOCK_FUNCTION (b)) + fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b))); + fputc ('\n', outfile); + blen = BLOCK_NSYMS (b); + for (j = 0; j < blen; j++) + { + print_symbol (BLOCK_SYM (b, j), depth + 1, outfile); + } + } + + fprintf (outfile, "\n\n"); + } + + immediate_quit--; + do_cleanups (cleanups); +} + +static void +print_symbol (symbol, depth, outfile) + struct symbol *symbol; + int depth; + FILE *outfile; +{ + print_spaces (depth, outfile); + if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE) + { + fprintf (outfile, "label %s at 0x%x", SYMBOL_NAME (symbol), + SYMBOL_VALUE (symbol)); + return; + } + if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE) + { + if (TYPE_NAME (SYMBOL_TYPE (symbol))) + { + type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth); + } + else + { + fprintf (outfile, "%s %s = ", + (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM + ? "enum" + : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT + ? "struct" : "union")), + SYMBOL_NAME (symbol)); + type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth); + } + fprintf (outfile, ";\n"); + } + else + { + if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF) + fprintf (outfile, "typedef "); + if (SYMBOL_TYPE (symbol)) + { + type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol), + outfile, 1, depth); + fprintf (outfile, "; "); + } + else + fprintf (outfile, "%s ", SYMBOL_NAME (symbol)); + + switch (SYMBOL_CLASS (symbol)) + { + case LOC_CONST: + fprintf (outfile, "const %d (0x%x),", + SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol)); + break; + + case LOC_CONST_BYTES: + fprintf (outfile, "const %d hex bytes:", + TYPE_LENGTH (SYMBOL_TYPE (symbol))); + { + int i; + for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++) + fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]); + fprintf (outfile, ","); + } + break; + + case LOC_STATIC: + fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol)); + break; + + case LOC_REGISTER: + fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol)); + break; + + case LOC_ARG: + fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol)); + break; + + case LOC_LOCAL: + fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol)); + break; + + case LOC_TYPEDEF: + break; + + case LOC_LABEL: + fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol)); + break; + + case LOC_BLOCK: + fprintf (outfile, "block (object 0x%x) starting at 0x%x,", + SYMBOL_VALUE (symbol), + BLOCK_START (SYMBOL_BLOCK_VALUE (symbol))); + break; + } + } + fprintf (outfile, "\n"); +} + +/* Return the nexting depth of a block within other blocks in its symtab. */ + +static int +block_depth (block) + struct block *block; +{ + register int i = 0; + while (block = BLOCK_SUPERBLOCK (block)) i++; + return i; +} + +static +initialize () +{ + add_com ("printsyms", class_obscure, print_symtabs, + "Print dump of current symbol definitions to file OUTFILE."); +} + +END_FILE |