diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2004-05-21 19:18:40 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2004-05-21 19:18:40 +0000 |
commit | 6a565344557d0acb4bd34cc9a0bf698662f9006b (patch) | |
tree | 5c120526742e6dbb98c8c3d2857c18f7de16143a /gnu/usr.bin/binutils/gdb/block.c | |
parent | a0769fe1e18fcff10de0bca7c087aacab3cda1cb (diff) |
GDB 6.1 (excluding .info files)
Diffstat (limited to 'gnu/usr.bin/binutils/gdb/block.c')
-rw-r--r-- | gnu/usr.bin/binutils/gdb/block.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/gdb/block.c b/gnu/usr.bin/binutils/gdb/block.c new file mode 100644 index 00000000000..28b1181ffe8 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/block.c @@ -0,0 +1,295 @@ +/* Block-related functions for the GNU debugger, GDB. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + 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. */ + +#include "defs.h" +#include "block.h" +#include "symtab.h" +#include "symfile.h" +#include "gdb_obstack.h" +#include "cp-support.h" + +/* This is used by struct block to store namespace-related info for + C++ files, namely using declarations and the current namespace in + scope. */ + +struct block_namespace_info +{ + const char *scope; + struct using_direct *using; +}; + +static void block_initialize_namespace (struct block *block, + struct obstack *obstack); + +/* Return Nonzero if block a is lexically nested within block b, + or if a and b have the same pc range. + Return zero otherwise. */ + +int +contained_in (const struct block *a, const struct block *b) +{ + if (!a || !b) + return 0; + return BLOCK_START (a) >= BLOCK_START (b) + && BLOCK_END (a) <= BLOCK_END (b); +} + + +/* Return the symbol for the function which contains a specified + lexical block, described by a struct block BL. */ + +struct symbol * +block_function (const struct block *bl) +{ + while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0) + bl = BLOCK_SUPERBLOCK (bl); + + return BLOCK_FUNCTION (bl); +} + +/* Return the blockvector immediately containing the innermost lexical block + containing the specified pc value and section, or 0 if there is none. + PINDEX is a pointer to the index value of the block. If PINDEX + is NULL, we don't pass this information back to the caller. */ + +struct blockvector * +blockvector_for_pc_sect (CORE_ADDR pc, struct bfd_section *section, + int *pindex, struct symtab *symtab) +{ + struct block *b; + int bot, top, half; + struct blockvector *bl; + + if (symtab == 0) /* if no symtab specified by caller */ + { + /* First search all symtabs for one whose file contains our pc */ + symtab = find_pc_sect_symtab (pc, section); + if (symtab == 0) + return 0; + } + + bl = BLOCKVECTOR (symtab); + b = BLOCKVECTOR_BLOCK (bl, 0); + + /* Then search that symtab for the smallest block that wins. */ + /* Use binary search to find the last block that starts before PC. */ + + bot = 0; + top = BLOCKVECTOR_NBLOCKS (bl); + + while (top - bot > 1) + { + half = (top - bot + 1) >> 1; + b = BLOCKVECTOR_BLOCK (bl, bot + half); + if (BLOCK_START (b) <= pc) + bot += half; + else + top = bot + half; + } + + /* Now search backward for a block that ends after PC. */ + + while (bot >= 0) + { + b = BLOCKVECTOR_BLOCK (bl, bot); + if (BLOCK_END (b) > pc) + { + if (pindex) + *pindex = bot; + return bl; + } + bot--; + } + return 0; +} + +/* Return the blockvector immediately containing the innermost lexical block + containing the specified pc value, or 0 if there is none. + Backward compatibility, no section. */ + +struct blockvector * +blockvector_for_pc (CORE_ADDR pc, int *pindex) +{ + return blockvector_for_pc_sect (pc, find_pc_mapped_section (pc), + pindex, NULL); +} + +/* Return the innermost lexical block containing the specified pc value + in the specified section, or 0 if there is none. */ + +struct block * +block_for_pc_sect (CORE_ADDR pc, struct bfd_section *section) +{ + struct blockvector *bl; + int index; + + bl = blockvector_for_pc_sect (pc, section, &index, NULL); + if (bl) + return BLOCKVECTOR_BLOCK (bl, index); + return 0; +} + +/* Return the innermost lexical block containing the specified pc value, + or 0 if there is none. Backward compatibility, no section. */ + +struct block * +block_for_pc (CORE_ADDR pc) +{ + return block_for_pc_sect (pc, find_pc_mapped_section (pc)); +} + +/* Now come some functions designed to deal with C++ namespace issues. + The accessors are safe to use even in the non-C++ case. */ + +/* This returns the namespace that BLOCK is enclosed in, or "" if it + isn't enclosed in a namespace at all. This travels the chain of + superblocks looking for a scope, if necessary. */ + +const char * +block_scope (const struct block *block) +{ + for (; block != NULL; block = BLOCK_SUPERBLOCK (block)) + { + if (BLOCK_NAMESPACE (block) != NULL + && BLOCK_NAMESPACE (block)->scope != NULL) + return BLOCK_NAMESPACE (block)->scope; + } + + return ""; +} + +/* Set BLOCK's scope member to SCOPE; if needed, allocate memory via + OBSTACK. (It won't make a copy of SCOPE, however, so that already + has to be allocated correctly.) */ + +void +block_set_scope (struct block *block, const char *scope, + struct obstack *obstack) +{ + block_initialize_namespace (block, obstack); + + BLOCK_NAMESPACE (block)->scope = scope; +} + +/* This returns the first using directives associated to BLOCK, if + any. */ + +/* FIXME: carlton/2003-04-23: This uses the fact that we currently + only have using directives in static blocks, because we only + generate using directives from anonymous namespaces. Eventually, + when we support using directives everywhere, we'll want to replace + this by some iterator functions. */ + +struct using_direct * +block_using (const struct block *block) +{ + const struct block *static_block = block_static_block (block); + + if (static_block == NULL + || BLOCK_NAMESPACE (static_block) == NULL) + return NULL; + else + return BLOCK_NAMESPACE (static_block)->using; +} + +/* Set BLOCK's using member to USING; if needed, allocate memory via + OBSTACK. (It won't make a copy of USING, however, so that already + has to be allocated correctly.) */ + +void +block_set_using (struct block *block, + struct using_direct *using, + struct obstack *obstack) +{ + block_initialize_namespace (block, obstack); + + BLOCK_NAMESPACE (block)->using = using; +} + +/* If BLOCK_NAMESPACE (block) is NULL, allocate it via OBSTACK and + ititialize its members to zero. */ + +static void +block_initialize_namespace (struct block *block, struct obstack *obstack) +{ + if (BLOCK_NAMESPACE (block) == NULL) + { + BLOCK_NAMESPACE (block) + = obstack_alloc (obstack, sizeof (struct block_namespace_info)); + BLOCK_NAMESPACE (block)->scope = NULL; + BLOCK_NAMESPACE (block)->using = NULL; + } +} + +/* Return the static block associated to BLOCK. Return NULL if block + is NULL or if block is a global block. */ + +const struct block * +block_static_block (const struct block *block) +{ + if (block == NULL || BLOCK_SUPERBLOCK (block) == NULL) + return NULL; + + while (BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) != NULL) + block = BLOCK_SUPERBLOCK (block); + + return block; +} + +/* Return the static block associated to BLOCK. Return NULL if block + is NULL. */ + +const struct block * +block_global_block (const struct block *block) +{ + if (block == NULL) + return NULL; + + while (BLOCK_SUPERBLOCK (block) != NULL) + block = BLOCK_SUPERBLOCK (block); + + return block; +} + +/* Allocate a block on OBSTACK, and initialize its elements to + zero/NULL. This is useful for creating "dummy" blocks that don't + correspond to actual source files. + + Warning: it sets the block's BLOCK_DICT to NULL, which isn't a + valid value. If you really don't want the block to have a + dictionary, then you should subsequently set its BLOCK_DICT to + dict_create_linear (obstack, NULL). */ + +struct block * +allocate_block (struct obstack *obstack) +{ + struct block *bl = obstack_alloc (obstack, sizeof (struct block)); + + BLOCK_START (bl) = 0; + BLOCK_END (bl) = 0; + BLOCK_FUNCTION (bl) = NULL; + BLOCK_SUPERBLOCK (bl) = NULL; + BLOCK_DICT (bl) = NULL; + BLOCK_NAMESPACE (bl) = NULL; + BLOCK_GCC_COMPILED (bl) = 0; + + return bl; +} |