aboutsummaryrefslogtreecommitdiff
path: root/gdb/psymtab.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2010-03-10 18:20:08 +0000
committerTom Tromey <tromey@redhat.com>2010-03-10 18:20:08 +0000
commitccefe4c44c4b2d1bc88757fba90ff59eb017a074 (patch)
tree829f5399a69d6926d7ff1708b43ff81fb4faf453 /gdb/psymtab.c
parenta2a5469e7999a8e4e713e11bfd191c11a422e1e8 (diff)
downloadgdb-ccefe4c44c4b2d1bc88757fba90ff59eb017a074.zip
gdb-ccefe4c44c4b2d1bc88757fba90ff59eb017a074.tar.gz
gdb-ccefe4c44c4b2d1bc88757fba90ff59eb017a074.tar.bz2
gdb
* xcoffread.c: Include psymtab.h. (xcoff_sym_fns): Update. * symtab.h (struct partial_symbol): Remove. (PSYMBOL_DOMAIN, PSYMBOL_CLASS): Remove. (struct partial_symtab): Remove. (PSYMTAB_TO_SYMTAB): Remove. (lookup_partial_symbol, lookup_partial_symtab, find_pc_psymtab) (find_pc_sect_psymtab): Remove. (find_pc_sect_symtab_via_partial): Declare. (find_pc_psymtab, find_pc_sect_psymbol, psymtab_to_symtab) (find_main_psymtab): Remove. (find_main_filename): Declare. (fixup_psymbol_section): Remove. (fixup_section): Declare. * symtab.c: Include psymtab.h. (lookup_symtab): Use lookup_symtab method. (lookup_partial_symtab): Remove. (find_pc_sect_psymtab_closer): Remove. (find_pc_sect_psymtab): Remove. (find_pc_sect_symtab_via_partial): New function. (find_pc_psymtab, find_pc_sect_psymbol, find_pc_psymbol): Remove. (fixup_section): No longer static. (fixup_psymbol_section): Remove. (lookup_symbol_aux): Use lookup_symbol_aux_quick. (lookup_global_symbol_from_objfile): Likewise. (lookup_symbol_aux_psymtabs): Remove. (lookup_symbol_aux_quick): New function. (lookup_symbol_global): Use lookup_symbol_aux_quick. (lookup_partial_symbol): Remove. (basic_lookup_transparent_type_quick): New function. (basic_lookup_transparent_type): Use it. (find_main_psymtab): Remove. (find_main_filename): New function. (find_pc_sect_symtab): Use find_pc_sect_symtab method. (find_line_symtab): Use expand_symtabs_with_filename method. (output_partial_symbol_filename): New function. (sources_info): Use map_partial_symbol_filenames. (struct search_symbols_data): New type. (search_symbols_file_matches): New function. (search_symbols_name_matches): Likewise. (search_symbols): Use expand_symtabs_matching method. (struct add_name_data): Rename from add_macro_name_data. (add_macro_name): Update. (add_partial_symbol_name): New function. (default_make_symbol_completion_list): Use map_partial_symbol_names. (struct add_partial_symbol_name): New type. (maybe_add_partial_symtab_filename): New function. (make_source_files_completion_list): Use map_partial_symbol_filenames. (expand_line_sal): Use expand_symtabs_with_filename method. * symmisc.c: Include psymtab.h. (print_objfile_statistics): Use print_stats method. (dump_objfile): Use dump method. (dump_psymtab, maintenance_print_psymbols) (maintenance_info_psymtabs, maintenance_check_symtabs) (extend_psymbol_list): Remove. * symfile.h (struct quick_symbol_functions): New struct. (struct sym_fns) <qf>: New field. (sort_pst_symbols): Remove. (increment_reading_symtab): Declare. * symfile.c: Include psymtab.h. (compare_psymbols, sort_pst_symbols): Remove. (psymtab_to_symtab): Remove. (increment_reading_symtab): New function. (symbol_file_add_with_addrs_or_offsets): Use expand_all_symtabs method. (set_initial_language): Use find_main_filename. (allocate_psymtab, discard_psymtab, cashier_psymtab): Remove. (free_named_symtabs): Remove unused code. (start_psymtab_common, add_psymbol_to_bcache) (append_psymbol_to_list, add_psymbol_to_list, init_psymbol_list): Remove. * stack.c: Include psymtab.h, symfile.h. (backtrace_command_1): Use find_pc_sect_symtab_via_partial. * source.h (psymtab_to_fullname): Don't declare. * source.c: Include psymtab.h. (select_source_symtab): Use find_last_source_symtab method. (forget_cached_source_info): Use forget_cached_source_info method. (find_and_open_source): No longer static. (psymtab_to_fullname): Remove. * somread.c: Include psymtab.h. (som_sym_fns): Update. * psympriv.h: New file. * psymtab.h: New file. * psymtab.c: New file. * objfiles.h: (ALL_OBJFILE_PSYMTABS): Remove. (ALL_PSYMTABS, ALL_PSPACE_PSYMTABS): Likewise. * objfiles.c: Include psymtab.h. (objfile_relocate1): Use relocate method. (objfile_has_partial_symbols): Use has_symbols method. * mipsread.c: Include psymtab.h. (ecoff_sym_fns): Update. * mi/mi-cmd-file.c: Include psymtab.h. (print_partial_file_name): New function. (mi_cmd_file_list_exec_source_files): Use map_partial_symbol_filenames. * mdebugread.c: Include psympriv.h. * machoread.c: Include psympriv.h. (macho_sym_fns): Update. * m2-exp.y (yylex): Use lookup_symtab. * elfread.c: Include psympriv.h. (elf_sym_fns): Update. * dwarf2read.c: Include psympriv.h. * dbxread.c: Include psympriv.h. (aout_sym_fns): Update. * cp-support.c: Include psymtab.h. (read_in_psymtabs): Remove. (make_symbol_overload_list_qualified): Use expand_symtabs_for_function method. * coffread.c: Include psympriv.h. (coff_sym_fns): Update. * blockframe.c: Include psymtab.h. (find_pc_partial_function): Use find_pc_sect_symtab method. * ada-lang.h (ada_update_initial_language): Update. * ada-lang.c: Include psymtab.h. (ada_update_initial_language): Remove 'main_pst' argument. (ada_lookup_partial_symbol): Remove. (struct ada_psym_data): New type. (ada_add_psyms): New function. (ada_add_non_local_symbols): Use map_ada_symtabs method. (struct add_partial_datum): New type. (ada_add_partial_symbol_completions): New function. (ada_make_symbol_completion_list): Use map_partial_symbol_names. (ada_exception_support_info_sniffer): Update. * Makefile.in (SFILES): Add psymtab.c. (COMMON_OBS): Add psymtab.o. (HFILES_NO_SRCDIR): Add psymtab.h, psympriv.h. gdb/doc * gdbint.texinfo (Symbol Handling): Update.
Diffstat (limited to 'gdb/psymtab.c')
-rw-r--r--gdb/psymtab.c1751
1 files changed, 1751 insertions, 0 deletions
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
new file mode 100644
index 0000000..35f410b
--- /dev/null
+++ b/gdb/psymtab.c
@@ -0,0 +1,1751 @@
+/* Partial symbol tables.
+
+ Copyright (C) 2009, 2010 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "psympriv.h"
+#include "objfiles.h"
+#include "gdb_assert.h"
+#include "block.h"
+#include "filenames.h"
+#include "source.h"
+#include "addrmap.h"
+#include "gdbtypes.h"
+#include "bcache.h"
+#include "ui-out.h"
+#include "command.h"
+#include "readline/readline.h"
+#include "gdb_regex.h"
+
+#ifndef DEV_TTY
+#define DEV_TTY "/dev/tty"
+#endif
+
+/* A fast way to get from a psymtab to its symtab (after the first time). */
+#define PSYMTAB_TO_SYMTAB(pst) \
+ ((pst) -> symtab != NULL ? (pst) -> symtab : psymtab_to_symtab (pst))
+
+/* Lookup a partial symbol. */
+static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
+ const char *, int,
+ domain_enum);
+
+static char *psymtab_to_fullname (struct partial_symtab *ps);
+
+static struct partial_symbol *find_pc_sect_psymbol (struct partial_symtab *,
+ CORE_ADDR,
+ struct obj_section *);
+
+static struct partial_symbol *fixup_psymbol_section (struct partial_symbol
+ *psym,
+ struct objfile *objfile);
+
+static struct symtab *psymtab_to_symtab (struct partial_symtab *pst);
+
+/* Lookup the partial symbol table of a source file named NAME.
+ *If* there is no '/' in the name, a match after a '/'
+ in the psymtab filename will also work. */
+
+static struct partial_symtab *
+lookup_partial_symtab (struct objfile *objfile, const char *name,
+ const char *full_path, const char *real_path)
+{
+ struct partial_symtab *pst;
+
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (FILENAME_CMP (name, pst->filename) == 0)
+ {
+ return (pst);
+ }
+
+ /* If the user gave us an absolute path, try to find the file in
+ this symtab and use its absolute path. */
+ if (full_path != NULL)
+ {
+ psymtab_to_fullname (pst);
+ if (pst->fullname != NULL
+ && FILENAME_CMP (full_path, pst->fullname) == 0)
+ {
+ return pst;
+ }
+ }
+
+ if (real_path != NULL)
+ {
+ char *rp = NULL;
+ psymtab_to_fullname (pst);
+ if (pst->fullname != NULL)
+ {
+ rp = gdb_realpath (pst->fullname);
+ make_cleanup (xfree, rp);
+ }
+ if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
+ {
+ return pst;
+ }
+ }
+ }
+
+ /* Now, search for a matching tail (only if name doesn't have any dirs) */
+
+ if (lbasename (name) == name)
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
+ return (pst);
+ }
+
+ return (NULL);
+}
+
+static int
+lookup_symtab_via_partial_symtab (struct objfile *objfile, const char *name,
+ const char *full_path, const char *real_path,
+ struct symtab **result)
+{
+ struct partial_symtab *ps;
+
+ ps = lookup_partial_symtab (objfile, name, full_path, real_path);
+ if (!ps)
+ return 0;
+
+ if (ps->readin)
+ error (_("Internal: readin %s pst for `%s' found when no symtab found."),
+ ps->filename, name);
+
+ *result = PSYMTAB_TO_SYMTAB (ps);
+ return 1;
+}
+
+/* Find which partial symtab contains PC and SECTION starting at psymtab PST.
+ We may find a different psymtab than PST. See FIND_PC_SECT_PSYMTAB. */
+
+static struct partial_symtab *
+find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section,
+ struct partial_symtab *pst,
+ struct minimal_symbol *msymbol)
+{
+ struct objfile *objfile = pst->objfile;
+ struct partial_symtab *tpst;
+ struct partial_symtab *best_pst = pst;
+ CORE_ADDR best_addr = pst->textlow;
+
+ /* An objfile that has its functions reordered might have
+ many partial symbol tables containing the PC, but
+ we want the partial symbol table that contains the
+ function containing the PC. */
+ if (!(objfile->flags & OBJF_REORDERED) &&
+ section == 0) /* can't validate section this way */
+ return pst;
+
+ if (msymbol == NULL)
+ return (pst);
+
+ /* The code range of partial symtabs sometimes overlap, so, in
+ the loop below, we need to check all partial symtabs and
+ find the one that fits better for the given PC address. We
+ select the partial symtab that contains a symbol whose
+ address is closest to the PC address. By closest we mean
+ that find_pc_sect_symbol returns the symbol with address
+ that is closest and still less than the given PC. */
+ for (tpst = pst; tpst != NULL; tpst = tpst->next)
+ {
+ if (pc >= tpst->textlow && pc < tpst->texthigh)
+ {
+ struct partial_symbol *p;
+ CORE_ADDR this_addr;
+
+ /* NOTE: This assumes that every psymbol has a
+ corresponding msymbol, which is not necessarily
+ true; the debug info might be much richer than the
+ object's symbol table. */
+ p = find_pc_sect_psymbol (tpst, pc, section);
+ if (p != NULL
+ && SYMBOL_VALUE_ADDRESS (p)
+ == SYMBOL_VALUE_ADDRESS (msymbol))
+ return tpst;
+
+ /* Also accept the textlow value of a psymtab as a
+ "symbol", to provide some support for partial
+ symbol tables with line information but no debug
+ symbols (e.g. those produced by an assembler). */
+ if (p != NULL)
+ this_addr = SYMBOL_VALUE_ADDRESS (p);
+ else
+ this_addr = tpst->textlow;
+
+ /* Check whether it is closer than our current
+ BEST_ADDR. Since this symbol address is
+ necessarily lower or equal to PC, the symbol closer
+ to PC is the symbol which address is the highest.
+ This way we return the psymtab which contains such
+ best match symbol. This can help in cases where the
+ symbol information/debuginfo is not complete, like
+ for instance on IRIX6 with gcc, where no debug info
+ is emitted for statics. (See also the nodebug.exp
+ testcase.) */
+ if (this_addr > best_addr)
+ {
+ best_addr = this_addr;
+ best_pst = tpst;
+ }
+ }
+ }
+ return best_pst;
+}
+
+/* Find which partial symtab contains PC and SECTION. Return 0 if
+ none. We return the psymtab that contains a symbol whose address
+ exactly matches PC, or, if we cannot find an exact match, the
+ psymtab that contains a symbol whose address is closest to PC. */
+static struct partial_symtab *
+find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc,
+ struct obj_section *section,
+ struct minimal_symbol *msymbol)
+{
+ struct partial_symtab *pst;
+
+ /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
+ than the later used TEXTLOW/TEXTHIGH one. */
+
+ if (objfile->psymtabs_addrmap != NULL)
+ {
+ pst = addrmap_find (objfile->psymtabs_addrmap, pc);
+ if (pst != NULL)
+ {
+ /* FIXME: addrmaps currently do not handle overlayed sections,
+ so fall back to the non-addrmap case if we're debugging
+ overlays and the addrmap returned the wrong section. */
+ if (overlay_debugging && msymbol && section)
+ {
+ struct partial_symbol *p;
+ /* NOTE: This assumes that every psymbol has a
+ corresponding msymbol, which is not necessarily
+ true; the debug info might be much richer than the
+ object's symbol table. */
+ p = find_pc_sect_psymbol (pst, pc, section);
+ if (!p
+ || SYMBOL_VALUE_ADDRESS (p)
+ != SYMBOL_VALUE_ADDRESS (msymbol))
+ goto next;
+ }
+
+ /* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as
+ PSYMTABS_ADDRMAP we used has already the best 1-byte
+ granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into
+ a worse chosen section due to the TEXTLOW/TEXTHIGH ranges
+ overlap. */
+
+ return pst;
+ }
+ }
+
+ next:
+
+ /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
+ which still have no corresponding full SYMTABs read. But it is not
+ present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
+ so far. */
+
+ /* Check even OBJFILE with non-zero PSYMTABS_ADDRMAP as only several of
+ its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying
+ debug info type in single OBJFILE. */
+
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ if (pc >= pst->textlow && pc < pst->texthigh)
+ {
+ struct partial_symtab *best_pst;
+
+ best_pst = find_pc_sect_psymtab_closer (pc, section, pst, msymbol);
+ if (best_pst != NULL)
+ return best_pst;
+ }
+
+ return NULL;
+}
+
+static struct symtab *
+find_pc_sect_symtab_from_partial (struct objfile *objfile,
+ struct minimal_symbol *msymbol,
+ CORE_ADDR pc, struct obj_section *section,
+ int warn_if_readin)
+{
+ struct partial_symtab *ps = find_pc_sect_psymtab (objfile, pc, section,
+ msymbol);
+ if (ps)
+ {
+ if (warn_if_readin && ps->readin)
+ /* Might want to error() here (in case symtab is corrupt and
+ will cause a core dump), but maybe we can successfully
+ continue, so let's not. */
+ warning (_("\
+(Internal error: pc %s in read in psymtab, but not in symtab.)\n"),
+ paddress (get_objfile_arch (ps->objfile), pc));
+ return PSYMTAB_TO_SYMTAB (ps);
+ }
+ return NULL;
+}
+
+/* Find which partial symbol within a psymtab matches PC and SECTION.
+ Return 0 if none. */
+
+static struct partial_symbol *
+find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
+ struct obj_section *section)
+{
+ struct partial_symbol *best = NULL, *p, **pp;
+ CORE_ADDR best_pc;
+
+ gdb_assert (psymtab != NULL);
+
+ /* Cope with programs that start at address 0 */
+ best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0;
+
+ /* Search the global symbols as well as the static symbols, so that
+ find_pc_partial_function doesn't use a minimal symbol and thus
+ cache a bad endaddr. */
+ for (pp = psymtab->objfile->global_psymbols.list + psymtab->globals_offset;
+ (pp - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset)
+ < psymtab->n_global_syms);
+ pp++)
+ {
+ p = *pp;
+ if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
+ && SYMBOL_CLASS (p) == LOC_BLOCK
+ && pc >= SYMBOL_VALUE_ADDRESS (p)
+ && (SYMBOL_VALUE_ADDRESS (p) > best_pc
+ || (psymtab->textlow == 0
+ && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
+ {
+ if (section) /* match on a specific section */
+ {
+ fixup_psymbol_section (p, psymtab->objfile);
+ if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
+ continue;
+ }
+ best_pc = SYMBOL_VALUE_ADDRESS (p);
+ best = p;
+ }
+ }
+
+ for (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
+ (pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
+ < psymtab->n_static_syms);
+ pp++)
+ {
+ p = *pp;
+ if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
+ && SYMBOL_CLASS (p) == LOC_BLOCK
+ && pc >= SYMBOL_VALUE_ADDRESS (p)
+ && (SYMBOL_VALUE_ADDRESS (p) > best_pc
+ || (psymtab->textlow == 0
+ && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
+ {
+ if (section) /* match on a specific section */
+ {
+ fixup_psymbol_section (p, psymtab->objfile);
+ if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
+ continue;
+ }
+ best_pc = SYMBOL_VALUE_ADDRESS (p);
+ best = p;
+ }
+ }
+
+ return best;
+}
+
+static struct partial_symbol *
+fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
+{
+ CORE_ADDR addr;
+
+ if (!psym)
+ return NULL;
+
+ if (SYMBOL_OBJ_SECTION (psym))
+ return psym;
+
+ gdb_assert (objfile);
+
+ switch (SYMBOL_CLASS (psym))
+ {
+ case LOC_STATIC:
+ case LOC_LABEL:
+ case LOC_BLOCK:
+ addr = SYMBOL_VALUE_ADDRESS (psym);
+ break;
+ default:
+ /* Nothing else will be listed in the minsyms -- no use looking
+ it up. */
+ return psym;
+ }
+
+ fixup_section (&psym->ginfo, addr, objfile);
+
+ return psym;
+}
+
+static struct symtab *
+lookup_symbol_aux_psymtabs (struct objfile *objfile,
+ int block_index, const char *name,
+ const domain_enum domain)
+{
+ struct partial_symtab *ps;
+ const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
+
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, psymtab_index, domain))
+ return PSYMTAB_TO_SYMTAB (ps);
+ }
+
+ return NULL;
+}
+
+/* Look, in partial_symtab PST, for symbol whose natural name is NAME.
+ Check the global symbols if GLOBAL, the static symbols if not. */
+
+struct partial_symbol *
+lookup_partial_symbol (struct partial_symtab *pst, const char *name,
+ int global, domain_enum domain)
+{
+ struct partial_symbol *temp;
+ struct partial_symbol **start, **psym;
+ struct partial_symbol **top, **real_top, **bottom, **center;
+ int length = (global ? pst->n_global_syms : pst->n_static_syms);
+ int do_linear_search = 1;
+
+ if (length == 0)
+ {
+ return (NULL);
+ }
+ start = (global ?
+ pst->objfile->global_psymbols.list + pst->globals_offset :
+ pst->objfile->static_psymbols.list + pst->statics_offset);
+
+ if (global) /* This means we can use a binary search. */
+ {
+ do_linear_search = 0;
+
+ /* Binary search. This search is guaranteed to end with center
+ pointing at the earliest partial symbol whose name might be
+ correct. At that point *all* partial symbols with an
+ appropriate name will be checked against the correct
+ domain. */
+
+ bottom = start;
+ top = start + length - 1;
+ real_top = top;
+ while (top > bottom)
+ {
+ center = bottom + (top - bottom) / 2;
+ if (!(center < top))
+ internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+ if (!do_linear_search
+ && (SYMBOL_LANGUAGE (*center) == language_java))
+ {
+ do_linear_search = 1;
+ }
+ if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0)
+ {
+ top = center;
+ }
+ else
+ {
+ bottom = center + 1;
+ }
+ }
+ if (!(top == bottom))
+ internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+
+ while (top <= real_top
+ && SYMBOL_MATCHES_SEARCH_NAME (*top, name))
+ {
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
+ SYMBOL_DOMAIN (*top), domain))
+ return (*top);
+ top++;
+ }
+ }
+
+ /* Can't use a binary search or else we found during the binary search that
+ we should also do a linear search. */
+
+ if (do_linear_search)
+ {
+ for (psym = start; psym < start + length; psym++)
+ {
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
+ SYMBOL_DOMAIN (*psym), domain)
+ && SYMBOL_MATCHES_SEARCH_NAME (*psym, name))
+ return (*psym);
+ }
+ }
+
+ return (NULL);
+}
+
+/* Get the symbol table that corresponds to a partial_symtab.
+ This is fast after the first time you do it. In fact, there
+ is an even faster macro PSYMTAB_TO_SYMTAB that does the fast
+ case inline. */
+
+static struct symtab *
+psymtab_to_symtab (struct partial_symtab *pst)
+{
+ /* If it's been looked up before, return it. */
+ if (pst->symtab)
+ return pst->symtab;
+
+ /* If it has not yet been read in, read it. */
+ if (!pst->readin)
+ {
+ struct cleanup *back_to = increment_reading_symtab ();
+ (*pst->read_symtab) (pst);
+ do_cleanups (back_to);
+ }
+
+ return pst->symtab;
+}
+
+static void
+relocate_psymtabs (struct objfile *objfile,
+ struct section_offsets *new_offsets,
+ struct section_offsets *delta)
+{
+ struct partial_symbol **psym;
+ struct partial_symtab *p;
+
+ ALL_OBJFILE_PSYMTABS (objfile, p)
+ {
+ p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
+ p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
+ }
+
+ for (psym = objfile->global_psymbols.list;
+ psym < objfile->global_psymbols.next;
+ psym++)
+ {
+ fixup_psymbol_section (*psym, objfile);
+ if (SYMBOL_SECTION (*psym) >= 0)
+ SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
+ SYMBOL_SECTION (*psym));
+ }
+ for (psym = objfile->static_psymbols.list;
+ psym < objfile->static_psymbols.next;
+ psym++)
+ {
+ fixup_psymbol_section (*psym, objfile);
+ if (SYMBOL_SECTION (*psym) >= 0)
+ SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
+ SYMBOL_SECTION (*psym));
+ }
+}
+
+static struct symtab *
+find_last_source_symtab_from_partial (struct objfile *ofp)
+{
+ struct symtab *result;
+ struct partial_symtab *ps;
+ struct partial_symtab *cs_pst = 0;
+
+ ALL_OBJFILE_PSYMTABS (ofp, ps)
+ {
+ const char *name = ps->filename;
+ int len = strlen (name);
+ if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
+ || strcmp (name, "<<C++-namespaces>>") == 0)))
+ cs_pst = ps;
+ }
+
+ if (cs_pst)
+ {
+ if (cs_pst->readin)
+ {
+ internal_error (__FILE__, __LINE__,
+ _("select_source_symtab: "
+ "readin pst found and no symtabs."));
+ }
+ else
+ return PSYMTAB_TO_SYMTAB (cs_pst);
+ }
+ return NULL;
+}
+
+static void
+forget_cached_source_info_partial (struct objfile *objfile)
+{
+ struct partial_symtab *pst;
+
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (pst->fullname != NULL)
+ {
+ xfree (pst->fullname);
+ pst->fullname = NULL;
+ }
+ }
+}
+
+static void
+print_partial_symbols (struct gdbarch *gdbarch,
+ struct partial_symbol **p, int count, char *what,
+ struct ui_file *outfile)
+{
+ fprintf_filtered (outfile, " %s partial symbols:\n", what);
+ while (count-- > 0)
+ {
+ fprintf_filtered (outfile, " `%s'", SYMBOL_LINKAGE_NAME (*p));
+ if (SYMBOL_DEMANGLED_NAME (*p) != NULL)
+ {
+ fprintf_filtered (outfile, " `%s'", SYMBOL_DEMANGLED_NAME (*p));
+ }
+ fputs_filtered (", ", outfile);
+ switch (SYMBOL_DOMAIN (*p))
+ {
+ case UNDEF_DOMAIN:
+ fputs_filtered ("undefined domain, ", outfile);
+ break;
+ case VAR_DOMAIN:
+ /* This is the usual thing -- don't print it */
+ break;
+ case STRUCT_DOMAIN:
+ fputs_filtered ("struct domain, ", outfile);
+ break;
+ case LABEL_DOMAIN:
+ fputs_filtered ("label domain, ", outfile);
+ break;
+ default:
+ fputs_filtered ("<invalid domain>, ", outfile);
+ break;
+ }
+ switch (SYMBOL_CLASS (*p))
+ {
+ case LOC_UNDEF:
+ fputs_filtered ("undefined", outfile);
+ break;
+ case LOC_CONST:
+ fputs_filtered ("constant int", outfile);
+ break;
+ case LOC_STATIC:
+ fputs_filtered ("static", outfile);
+ break;
+ case LOC_REGISTER:
+ fputs_filtered ("register", outfile);
+ break;
+ case LOC_ARG:
+ fputs_filtered ("pass by value", outfile);
+ break;
+ case LOC_REF_ARG:
+ fputs_filtered ("pass by reference", outfile);
+ break;
+ case LOC_REGPARM_ADDR:
+ fputs_filtered ("register address parameter", outfile);
+ break;
+ case LOC_LOCAL:
+ fputs_filtered ("stack parameter", outfile);
+ break;
+ case LOC_TYPEDEF:
+ fputs_filtered ("type", outfile);
+ break;
+ case LOC_LABEL:
+ fputs_filtered ("label", outfile);
+ break;
+ case LOC_BLOCK:
+ fputs_filtered ("function", outfile);
+ break;
+ case LOC_CONST_BYTES:
+ fputs_filtered ("constant bytes", outfile);
+ break;
+ case LOC_UNRESOLVED:
+ fputs_filtered ("unresolved", outfile);
+ break;
+ case LOC_OPTIMIZED_OUT:
+ fputs_filtered ("optimized out", outfile);
+ break;
+ case LOC_COMPUTED:
+ fputs_filtered ("computed at runtime", outfile);
+ break;
+ default:
+ fputs_filtered ("<invalid location>", outfile);
+ break;
+ }
+ fputs_filtered (", ", outfile);
+ fputs_filtered (paddress (gdbarch, SYMBOL_VALUE_ADDRESS (*p)), outfile);
+ fprintf_filtered (outfile, "\n");
+ p++;
+ }
+}
+
+static void
+dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
+ struct ui_file *outfile)
+{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ int i;
+
+ fprintf_filtered (outfile, "\nPartial symtab for source file %s ",
+ psymtab->filename);
+ fprintf_filtered (outfile, "(object ");
+ gdb_print_host_address (psymtab, outfile);
+ fprintf_filtered (outfile, ")\n\n");
+ fprintf_unfiltered (outfile, " Read from object file %s (",
+ objfile->name);
+ gdb_print_host_address (objfile, outfile);
+ fprintf_unfiltered (outfile, ")\n");
+
+ if (psymtab->readin)
+ {
+ fprintf_filtered (outfile,
+ " Full symtab was read (at ");
+ gdb_print_host_address (psymtab->symtab, outfile);
+ fprintf_filtered (outfile, " by function at ");
+ gdb_print_host_address (psymtab->read_symtab, outfile);
+ fprintf_filtered (outfile, ")\n");
+ }
+
+ fprintf_filtered (outfile, " Relocate symbols by ");
+ for (i = 0; i < psymtab->objfile->num_sections; ++i)
+ {
+ if (i != 0)
+ fprintf_filtered (outfile, ", ");
+ wrap_here (" ");
+ fputs_filtered (paddress (gdbarch,
+ ANOFFSET (psymtab->section_offsets, i)),
+ outfile);
+ }
+ fprintf_filtered (outfile, "\n");
+
+ fprintf_filtered (outfile, " Symbols cover text addresses ");
+ fputs_filtered (paddress (gdbarch, psymtab->textlow), outfile);
+ fprintf_filtered (outfile, "-");
+ fputs_filtered (paddress (gdbarch, psymtab->texthigh), outfile);
+ fprintf_filtered (outfile, "\n");
+ fprintf_filtered (outfile, " Depends on %d other partial symtabs.\n",
+ psymtab->number_of_dependencies);
+ for (i = 0; i < psymtab->number_of_dependencies; i++)
+ {
+ fprintf_filtered (outfile, " %d ", i);
+ gdb_print_host_address (psymtab->dependencies[i], outfile);
+ fprintf_filtered (outfile, " %s\n",
+ psymtab->dependencies[i]->filename);
+ }
+ if (psymtab->n_global_syms > 0)
+ {
+ print_partial_symbols (gdbarch,
+ objfile->global_psymbols.list
+ + psymtab->globals_offset,
+ psymtab->n_global_syms, "Global", outfile);
+ }
+ if (psymtab->n_static_syms > 0)
+ {
+ print_partial_symbols (gdbarch,
+ objfile->static_psymbols.list
+ + psymtab->statics_offset,
+ psymtab->n_static_syms, "Static", outfile);
+ }
+ fprintf_filtered (outfile, "\n");
+}
+
+static void
+print_psymtab_stats_for_objfile (struct objfile *objfile)
+{
+ int i;
+ struct partial_symtab *ps;
+ i = 0;
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ if (ps->readin == 0)
+ i++;
+ }
+ printf_filtered (_(" Number of psym tables (not yet expanded): %d\n"), i);
+}
+
+static void
+dump_psymtabs_for_objfile (struct objfile *objfile)
+{
+ struct partial_symtab *psymtab;
+
+ if (objfile->psymtabs)
+ {
+ printf_filtered ("Psymtabs:\n");
+ for (psymtab = objfile->psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab->next)
+ {
+ printf_filtered ("%s at ",
+ psymtab->filename);
+ gdb_print_host_address (psymtab, gdb_stdout);
+ printf_filtered (", ");
+ if (psymtab->objfile != objfile)
+ {
+ printf_filtered ("NOT ON CHAIN! ");
+ }
+ wrap_here (" ");
+ }
+ printf_filtered ("\n\n");
+ }
+}
+
+/* Look through the partial symtabs for all symbols which begin
+ by matching FUNC_NAME. Make sure we read that symbol table in. */
+
+static void
+read_symtabs_for_function (struct objfile *objfile, const char *func_name)
+{
+ struct partial_symtab *ps;
+
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ if (ps->readin)
+ continue;
+
+ if ((lookup_partial_symbol (ps, func_name, 1, VAR_DOMAIN)
+ != NULL)
+ || (lookup_partial_symbol (ps, func_name, 0, VAR_DOMAIN)
+ != NULL))
+ psymtab_to_symtab (ps);
+ }
+}
+
+static void
+expand_partial_symbol_tables (struct objfile *objfile)
+{
+ struct partial_symtab *psymtab;
+
+ for (psymtab = objfile->psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab->next)
+ {
+ psymtab_to_symtab (psymtab);
+ }
+}
+
+static void
+read_psymtabs_with_filename (struct objfile *objfile, const char *filename)
+{
+ struct partial_symtab *p;
+
+ ALL_OBJFILE_PSYMTABS (objfile, p)
+ {
+ if (strcmp (filename, p->filename) == 0)
+ PSYMTAB_TO_SYMTAB (p);
+ }
+}
+
+static void
+map_symbol_names_psymtab (struct objfile *objfile,
+ void (*fun) (const char *, void *), void *data)
+{
+ struct partial_symtab *ps;
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ struct partial_symbol **psym;
+
+ /* If the psymtab's been read in we'll get it when we search
+ through the blockvector. */
+ if (ps->readin)
+ continue;
+
+ for (psym = objfile->global_psymbols.list + ps->globals_offset;
+ psym < (objfile->global_psymbols.list + ps->globals_offset
+ + ps->n_global_syms);
+ psym++)
+ {
+ /* If interrupted, then quit. */
+ QUIT;
+ (*fun) (SYMBOL_NATURAL_NAME (*psym), data);
+ }
+
+ for (psym = objfile->static_psymbols.list + ps->statics_offset;
+ psym < (objfile->static_psymbols.list + ps->statics_offset
+ + ps->n_static_syms);
+ psym++)
+ {
+ QUIT;
+ (*fun) (SYMBOL_NATURAL_NAME (*psym), data);
+ }
+ }
+}
+
+static void
+map_symbol_filenames_psymtab (struct objfile *objfile,
+ void (*fun) (const char *, const char *,
+ void *),
+ void *data)
+{
+ struct partial_symtab *ps;
+
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ const char *fullname;
+
+ if (ps->readin)
+ continue;
+
+ fullname = psymtab_to_fullname (ps);
+ (*fun) (fullname, ps->filename, data);
+ }
+}
+
+int find_and_open_source (const char *filename,
+ const char *dirname,
+ char **fullname);
+
+/* Finds the fullname that a partial_symtab represents.
+
+ If this functions finds the fullname, it will save it in ps->fullname
+ and it will also return the value.
+
+ If this function fails to find the file that this partial_symtab represents,
+ NULL will be returned and ps->fullname will be set to NULL. */
+static char *
+psymtab_to_fullname (struct partial_symtab *ps)
+{
+ int r;
+
+ if (!ps)
+ return NULL;
+
+ /* Don't check ps->fullname here, the file could have been
+ deleted/moved/..., look for it again */
+ r = find_and_open_source (ps->filename, ps->dirname, &ps->fullname);
+
+ if (r >= 0)
+ {
+ close (r);
+ return ps->fullname;
+ }
+
+ return NULL;
+}
+
+static char *
+find_symbol_file_from_partial (struct objfile *objfile, const char *name)
+{
+ struct partial_symtab *pst;
+
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (lookup_partial_symbol (pst, name, 1, VAR_DOMAIN))
+ return pst->filename;
+ }
+ return NULL;
+}
+
+/* Look, in partial_symtab PST, for symbol NAME in given namespace.
+ Check the global symbols if GLOBAL, the static symbols if not.
+ Do wild-card match if WILD. */
+
+static struct partial_symbol *
+ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name,
+ int global, domain_enum namespace, int wild,
+ int (*wild_match) (const char *, int, const char *),
+ int (*is_name_suffix) (const char *))
+{
+ struct partial_symbol **start;
+ int name_len = strlen (name);
+ int length = (global ? pst->n_global_syms : pst->n_static_syms);
+ int i;
+
+ if (length == 0)
+ {
+ return (NULL);
+ }
+
+ start = (global ?
+ pst->objfile->global_psymbols.list + pst->globals_offset :
+ pst->objfile->static_psymbols.list + pst->statics_offset);
+
+ if (wild)
+ {
+ for (i = 0; i < length; i += 1)
+ {
+ struct partial_symbol *psym = start[i];
+
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
+ SYMBOL_DOMAIN (psym), namespace)
+ && (*wild_match) (name, name_len, SYMBOL_LINKAGE_NAME (psym)))
+ return psym;
+ }
+ return NULL;
+ }
+ else
+ {
+ if (global)
+ {
+ int U;
+ i = 0;
+ U = length - 1;
+ while (U - i > 4)
+ {
+ int M = (U + i) >> 1;
+ struct partial_symbol *psym = start[M];
+ if (SYMBOL_LINKAGE_NAME (psym)[0] < name[0])
+ i = M + 1;
+ else if (SYMBOL_LINKAGE_NAME (psym)[0] > name[0])
+ U = M - 1;
+ else if (strcmp (SYMBOL_LINKAGE_NAME (psym), name) < 0)
+ i = M + 1;
+ else
+ U = M;
+ }
+ }
+ else
+ i = 0;
+
+ while (i < length)
+ {
+ struct partial_symbol *psym = start[i];
+
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
+ SYMBOL_DOMAIN (psym), namespace))
+ {
+ int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym), name_len);
+
+ if (cmp < 0)
+ {
+ if (global)
+ break;
+ }
+ else if (cmp == 0
+ && (*is_name_suffix) (SYMBOL_LINKAGE_NAME (psym)
+ + name_len))
+ return psym;
+ }
+ i += 1;
+ }
+
+ if (global)
+ {
+ int U;
+ i = 0;
+ U = length - 1;
+ while (U - i > 4)
+ {
+ int M = (U + i) >> 1;
+ struct partial_symbol *psym = start[M];
+ if (SYMBOL_LINKAGE_NAME (psym)[0] < '_')
+ i = M + 1;
+ else if (SYMBOL_LINKAGE_NAME (psym)[0] > '_')
+ U = M - 1;
+ else if (strcmp (SYMBOL_LINKAGE_NAME (psym), "_ada_") < 0)
+ i = M + 1;
+ else
+ U = M;
+ }
+ }
+ else
+ i = 0;
+
+ while (i < length)
+ {
+ struct partial_symbol *psym = start[i];
+
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
+ SYMBOL_DOMAIN (psym), namespace))
+ {
+ int cmp;
+
+ cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (psym)[0];
+ if (cmp == 0)
+ {
+ cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (psym), 5);
+ if (cmp == 0)
+ cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym) + 5,
+ name_len);
+ }
+
+ if (cmp < 0)
+ {
+ if (global)
+ break;
+ }
+ else if (cmp == 0
+ && (*is_name_suffix) (SYMBOL_LINKAGE_NAME (psym)
+ + name_len + 5))
+ return psym;
+ }
+ i += 1;
+ }
+ }
+ return NULL;
+}
+
+static void
+map_ada_symtabs (struct objfile *objfile,
+ int (*wild_match) (const char *, int, const char *),
+ int (*is_name_suffix) (const char *),
+ void (*callback) (struct objfile *, struct symtab *, void *),
+ const char *name, int global, domain_enum namespace, int wild,
+ void *data)
+{
+ struct partial_symtab *ps;
+
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ QUIT;
+ if (ps->readin
+ || ada_lookup_partial_symbol (ps, name, global, namespace, wild,
+ wild_match, is_name_suffix))
+ {
+ struct symtab *s = PSYMTAB_TO_SYMTAB (ps);
+ if (s == NULL || !s->primary)
+ continue;
+ (*callback) (objfile, s, data);
+ }
+ }
+}
+
+static void
+expand_symtabs_matching_via_partial (struct objfile *objfile,
+ int (*file_matcher) (const char *, void *),
+ int (*name_matcher) (const char *, void *),
+ domain_enum kind,
+ void *data)
+{
+ struct partial_symtab *ps;
+
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ struct partial_symbol **psym;
+ struct partial_symbol **bound, **gbound, **sbound;
+ int keep_going = 1;
+
+ if (ps->readin)
+ continue;
+
+ if (! (*file_matcher) (ps->filename, data))
+ continue;
+
+ gbound = objfile->global_psymbols.list + ps->globals_offset + ps->n_global_syms;
+ sbound = objfile->static_psymbols.list + ps->statics_offset + ps->n_static_syms;
+ bound = gbound;
+
+ /* Go through all of the symbols stored in a partial
+ symtab in one loop. */
+ psym = objfile->global_psymbols.list + ps->globals_offset;
+ while (keep_going)
+ {
+ if (psym >= bound)
+ {
+ if (bound == gbound && ps->n_static_syms != 0)
+ {
+ psym = objfile->static_psymbols.list + ps->statics_offset;
+ bound = sbound;
+ }
+ else
+ keep_going = 0;
+ continue;
+ }
+ else
+ {
+ QUIT;
+
+ if ((*name_matcher) (SYMBOL_NATURAL_NAME (*psym), data)
+ && ((kind == VARIABLES_DOMAIN
+ && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (*psym) != LOC_BLOCK)
+ || (kind == FUNCTIONS_DOMAIN
+ && SYMBOL_CLASS (*psym) == LOC_BLOCK)
+ || (kind == TYPES_DOMAIN
+ && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)))
+ {
+ PSYMTAB_TO_SYMTAB (ps);
+ keep_going = 0;
+ }
+ }
+ psym++;
+ }
+ }
+}
+
+static int
+objfile_has_psyms (struct objfile *objfile)
+{
+ return objfile->psymtabs != NULL;
+}
+
+const struct quick_symbol_functions psym_functions =
+{
+ objfile_has_psyms,
+ find_last_source_symtab_from_partial,
+ forget_cached_source_info_partial,
+ lookup_symtab_via_partial_symtab,
+ lookup_symbol_aux_psymtabs,
+ print_psymtab_stats_for_objfile,
+ dump_psymtabs_for_objfile,
+ relocate_psymtabs,
+ read_symtabs_for_function,
+ expand_partial_symbol_tables,
+ read_psymtabs_with_filename,
+ find_symbol_file_from_partial,
+ map_ada_symtabs,
+ expand_symtabs_matching_via_partial,
+ find_pc_sect_symtab_from_partial,
+ map_symbol_names_psymtab,
+ map_symbol_filenames_psymtab
+};
+
+
+
+/* This compares two partial symbols by names, using strcmp_iw_ordered
+ for the comparison. */
+
+static int
+compare_psymbols (const void *s1p, const void *s2p)
+{
+ struct partial_symbol *const *s1 = s1p;
+ struct partial_symbol *const *s2 = s2p;
+
+ return strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*s1),
+ SYMBOL_SEARCH_NAME (*s2));
+}
+
+void
+sort_pst_symbols (struct partial_symtab *pst)
+{
+ /* Sort the global list; don't sort the static list */
+
+ qsort (pst->objfile->global_psymbols.list + pst->globals_offset,
+ pst->n_global_syms, sizeof (struct partial_symbol *),
+ compare_psymbols);
+}
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ FILENAME is the name of the symbol-file we are reading from. */
+
+struct partial_symtab *
+start_psymtab_common (struct objfile *objfile,
+ struct section_offsets *section_offsets,
+ const char *filename,
+ CORE_ADDR textlow, struct partial_symbol **global_syms,
+ struct partial_symbol **static_syms)
+{
+ struct partial_symtab *psymtab;
+
+ psymtab = allocate_psymtab (filename, objfile);
+ psymtab->section_offsets = section_offsets;
+ psymtab->textlow = textlow;
+ psymtab->texthigh = psymtab->textlow; /* default */
+ psymtab->globals_offset = global_syms - objfile->global_psymbols.list;
+ psymtab->statics_offset = static_syms - objfile->static_psymbols.list;
+ return (psymtab);
+}
+
+/* Helper function, initialises partial symbol structure and stashes
+ it into objfile's bcache. Note that our caching mechanism will
+ use all fields of struct partial_symbol to determine hash value of the
+ structure. In other words, having two symbols with the same name but
+ different domain (or address) is possible and correct. */
+
+static const struct partial_symbol *
+add_psymbol_to_bcache (char *name, int namelength, int copy_name,
+ domain_enum domain,
+ enum address_class class,
+ long val, /* Value as a long */
+ CORE_ADDR coreaddr, /* Value as a CORE_ADDR */
+ enum language language, struct objfile *objfile,
+ int *added)
+{
+ /* psymbol is static so that there will be no uninitialized gaps in the
+ structure which might contain random data, causing cache misses in
+ bcache. */
+ static struct partial_symbol psymbol;
+
+ /* However, we must ensure that the entire 'value' field has been
+ zeroed before assigning to it, because an assignment may not
+ write the entire field. */
+ memset (&psymbol.ginfo.value, 0, sizeof (psymbol.ginfo.value));
+ /* val and coreaddr are mutually exclusive, one of them *will* be zero */
+ if (val != 0)
+ {
+ SYMBOL_VALUE (&psymbol) = val;
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
+ }
+ SYMBOL_SECTION (&psymbol) = 0;
+ SYMBOL_LANGUAGE (&psymbol) = language;
+ PSYMBOL_DOMAIN (&psymbol) = domain;
+ PSYMBOL_CLASS (&psymbol) = class;
+
+ SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
+
+ /* Stash the partial symbol away in the cache */
+ return bcache_full (&psymbol, sizeof (struct partial_symbol),
+ objfile->psymbol_cache, added);
+}
+
+/* Helper function, adds partial symbol to the given partial symbol
+ list. */
+
+static void
+append_psymbol_to_list (struct psymbol_allocation_list *list,
+ const struct partial_symbol *psym,
+ struct objfile *objfile)
+{
+ if (list->next >= list->list + list->size)
+ extend_psymbol_list (list, objfile);
+ *list->next++ = (struct partial_symbol *) psym;
+ OBJSTAT (objfile, n_psyms++);
+}
+
+/* Add a symbol with a long value to a psymtab.
+ Since one arg is a struct, we pass in a ptr and deref it (sigh).
+ Return the partial symbol that has been added. */
+
+/* NOTE: carlton/2003-09-11: The reason why we return the partial
+ symbol is so that callers can get access to the symbol's demangled
+ name, which they don't have any cheap way to determine otherwise.
+ (Currenly, dwarf2read.c is the only file who uses that information,
+ though it's possible that other readers might in the future.)
+ Elena wasn't thrilled about that, and I don't blame her, but we
+ couldn't come up with a better way to get that information. If
+ it's needed in other situations, we could consider breaking up
+ SYMBOL_SET_NAMES to provide access to the demangled name lookup
+ cache. */
+
+const struct partial_symbol *
+add_psymbol_to_list (char *name, int namelength, int copy_name,
+ domain_enum domain,
+ enum address_class class,
+ struct psymbol_allocation_list *list,
+ long val, /* Value as a long */
+ CORE_ADDR coreaddr, /* Value as a CORE_ADDR */
+ enum language language, struct objfile *objfile)
+{
+ const struct partial_symbol *psym;
+
+ int added;
+
+ /* Stash the partial symbol away in the cache */
+ psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
+ val, coreaddr, language, objfile, &added);
+
+ /* Do not duplicate global partial symbols. */
+ if (list == &objfile->global_psymbols
+ && !added)
+ return psym;
+
+ /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+ append_psymbol_to_list (list, psym, objfile);
+ return psym;
+}
+
+/* Initialize storage for partial symbols. */
+
+void
+init_psymbol_list (struct objfile *objfile, int total_symbols)
+{
+ /* Free any previously allocated psymbol lists. */
+
+ if (objfile->global_psymbols.list)
+ {
+ xfree (objfile->global_psymbols.list);
+ }
+ if (objfile->static_psymbols.list)
+ {
+ xfree (objfile->static_psymbols.list);
+ }
+
+ /* Current best guess is that approximately a twentieth
+ of the total symbols (in a debugging file) are global or static
+ oriented symbols */
+
+ objfile->global_psymbols.size = total_symbols / 10;
+ objfile->static_psymbols.size = total_symbols / 10;
+
+ if (objfile->global_psymbols.size > 0)
+ {
+ objfile->global_psymbols.next =
+ objfile->global_psymbols.list = (struct partial_symbol **)
+ xmalloc ((objfile->global_psymbols.size
+ * sizeof (struct partial_symbol *)));
+ }
+ if (objfile->static_psymbols.size > 0)
+ {
+ objfile->static_psymbols.next =
+ objfile->static_psymbols.list = (struct partial_symbol **)
+ xmalloc ((objfile->static_psymbols.size
+ * sizeof (struct partial_symbol *)));
+ }
+}
+
+struct partial_symtab *
+allocate_psymtab (const char *filename, struct objfile *objfile)
+{
+ struct partial_symtab *psymtab;
+
+ if (objfile->free_psymtabs)
+ {
+ psymtab = objfile->free_psymtabs;
+ objfile->free_psymtabs = psymtab->next;
+ }
+ else
+ psymtab = (struct partial_symtab *)
+ obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct partial_symtab));
+
+ memset (psymtab, 0, sizeof (struct partial_symtab));
+ psymtab->filename = obsavestring (filename, strlen (filename),
+ &objfile->objfile_obstack);
+ psymtab->symtab = NULL;
+
+ /* Prepend it to the psymtab list for the objfile it belongs to.
+ Psymtabs are searched in most recent inserted -> least recent
+ inserted order. */
+
+ psymtab->objfile = objfile;
+ psymtab->next = objfile->psymtabs;
+ objfile->psymtabs = psymtab;
+#if 0
+ {
+ struct partial_symtab **prev_pst;
+ psymtab->objfile = objfile;
+ psymtab->next = NULL;
+ prev_pst = &(objfile->psymtabs);
+ while ((*prev_pst) != NULL)
+ prev_pst = &((*prev_pst)->next);
+ (*prev_pst) = psymtab;
+ }
+#endif
+
+ return (psymtab);
+}
+
+void
+discard_psymtab (struct partial_symtab *pst)
+{
+ struct partial_symtab **prev_pst;
+
+ /* From dbxread.c:
+ Empty psymtabs happen as a result of header files which don't
+ have any symbols in them. There can be a lot of them. But this
+ check is wrong, in that a psymtab with N_SLINE entries but
+ nothing else is not empty, but we don't realize that. Fixing
+ that without slowing things down might be tricky. */
+
+ /* First, snip it out of the psymtab chain */
+
+ prev_pst = &(pst->objfile->psymtabs);
+ while ((*prev_pst) != pst)
+ prev_pst = &((*prev_pst)->next);
+ (*prev_pst) = pst->next;
+
+ /* Next, put it on a free list for recycling */
+
+ pst->next = pst->objfile->free_psymtabs;
+ pst->objfile->free_psymtabs = pst;
+}
+
+/* Increase the space allocated for LISTP, which is probably
+ global_psymbols or static_psymbols. This space will eventually
+ be freed in free_objfile(). */
+
+void
+extend_psymbol_list (struct psymbol_allocation_list *listp,
+ struct objfile *objfile)
+{
+ int new_size;
+ if (listp->size == 0)
+ {
+ new_size = 255;
+ listp->list = (struct partial_symbol **)
+ xmalloc (new_size * sizeof (struct partial_symbol *));
+ }
+ else
+ {
+ new_size = listp->size * 2;
+ listp->list = (struct partial_symbol **)
+ xrealloc ((char *) listp->list,
+ new_size * sizeof (struct partial_symbol *));
+ }
+ /* Next assumes we only went one over. Should be good if
+ program works correctly */
+ listp->next = listp->list + listp->size;
+ listp->size = new_size;
+}
+
+
+
+void
+maintenance_print_psymbols (char *args, int from_tty)
+{
+ char **argv;
+ struct ui_file *outfile;
+ struct cleanup *cleanups;
+ char *symname = NULL;
+ char *filename = DEV_TTY;
+ struct objfile *objfile;
+ struct partial_symtab *ps;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error (_("print-psymbols takes an output file name and optional symbol file name"));
+ }
+ argv = gdb_buildargv (args);
+ cleanups = make_cleanup_freeargv (argv);
+
+ if (argv[0] != NULL)
+ {
+ filename = argv[0];
+ /* If a second arg is supplied, it is a source file name to match on */
+ if (argv[1] != NULL)
+ {
+ symname = argv[1];
+ }
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (xfree, filename);
+
+ outfile = gdb_fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup_ui_file_delete (outfile);
+
+ immediate_quit++;
+ ALL_PSYMTABS (objfile, ps)
+ if (symname == NULL || strcmp (symname, ps->filename) == 0)
+ dump_psymtab (objfile, ps, outfile);
+ immediate_quit--;
+ do_cleanups (cleanups);
+}
+
+/* List all the partial symbol tables whose names match REGEXP (optional). */
+void
+maintenance_info_psymtabs (char *regexp, int from_tty)
+{
+ struct program_space *pspace;
+ struct objfile *objfile;
+
+ if (regexp)
+ re_comp (regexp);
+
+ ALL_PSPACES (pspace)
+ ALL_PSPACE_OBJFILES (pspace, objfile)
+ {
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct partial_symtab *psymtab;
+
+ /* We don't want to print anything for this objfile until we
+ actually find a symtab whose name matches. */
+ int printed_objfile_start = 0;
+
+ ALL_OBJFILE_PSYMTABS (objfile, psymtab)
+ {
+ QUIT;
+
+ if (! regexp
+ || re_exec (psymtab->filename))
+ {
+ if (! printed_objfile_start)
+ {
+ printf_filtered ("{ objfile %s ", objfile->name);
+ wrap_here (" ");
+ printf_filtered ("((struct objfile *) %s)\n",
+ host_address_to_string (objfile));
+ printed_objfile_start = 1;
+ }
+
+ printf_filtered (" { psymtab %s ", psymtab->filename);
+ wrap_here (" ");
+ printf_filtered ("((struct partial_symtab *) %s)\n",
+ host_address_to_string (psymtab));
+
+ printf_filtered (" readin %s\n",
+ psymtab->readin ? "yes" : "no");
+ printf_filtered (" fullname %s\n",
+ psymtab->fullname ? psymtab->fullname : "(null)");
+ printf_filtered (" text addresses ");
+ fputs_filtered (paddress (gdbarch, psymtab->textlow),
+ gdb_stdout);
+ printf_filtered (" -- ");
+ fputs_filtered (paddress (gdbarch, psymtab->texthigh),
+ gdb_stdout);
+ printf_filtered ("\n");
+ printf_filtered (" globals ");
+ if (psymtab->n_global_syms)
+ {
+ printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
+ host_address_to_string (psymtab->objfile->global_psymbols.list
+ + psymtab->globals_offset),
+ psymtab->n_global_syms);
+ }
+ else
+ printf_filtered ("(none)\n");
+ printf_filtered (" statics ");
+ if (psymtab->n_static_syms)
+ {
+ printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
+ host_address_to_string (psymtab->objfile->static_psymbols.list
+ + psymtab->statics_offset),
+ psymtab->n_static_syms);
+ }
+ else
+ printf_filtered ("(none)\n");
+ printf_filtered (" dependencies ");
+ if (psymtab->number_of_dependencies)
+ {
+ int i;
+
+ printf_filtered ("{\n");
+ for (i = 0; i < psymtab->number_of_dependencies; i++)
+ {
+ struct partial_symtab *dep = psymtab->dependencies[i];
+
+ /* Note the string concatenation there --- no comma. */
+ printf_filtered (" psymtab %s "
+ "((struct partial_symtab *) %s)\n",
+ dep->filename,
+ host_address_to_string (dep));
+ }
+ printf_filtered (" }\n");
+ }
+ else
+ printf_filtered ("(none)\n");
+ printf_filtered (" }\n");
+ }
+ }
+
+ if (printed_objfile_start)
+ printf_filtered ("}\n");
+ }
+}
+
+/* Check consistency of psymtabs and symtabs. */
+
+void
+maintenance_check_symtabs (char *ignore, int from_tty)
+{
+ struct symbol *sym;
+ struct partial_symbol **psym;
+ struct symtab *s = NULL;
+ struct partial_symtab *ps;
+ struct blockvector *bv;
+ struct objfile *objfile;
+ struct block *b;
+ int length;
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ s = PSYMTAB_TO_SYMTAB (ps);
+ if (s == NULL)
+ continue;
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ psym = ps->objfile->static_psymbols.list + ps->statics_offset;
+ length = ps->n_static_syms;
+ while (length--)
+ {
+ sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
+ SYMBOL_DOMAIN (*psym));
+ if (!sym)
+ {
+ printf_filtered ("Static symbol `");
+ puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
+ printf_filtered ("' only found in ");
+ puts_filtered (ps->filename);
+ printf_filtered (" psymtab\n");
+ }
+ psym++;
+ }
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ psym = ps->objfile->global_psymbols.list + ps->globals_offset;
+ length = ps->n_global_syms;
+ while (length--)
+ {
+ sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
+ SYMBOL_DOMAIN (*psym));
+ if (!sym)
+ {
+ printf_filtered ("Global symbol `");
+ puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
+ printf_filtered ("' only found in ");
+ puts_filtered (ps->filename);
+ printf_filtered (" psymtab\n");
+ }
+ psym++;
+ }
+ if (ps->texthigh < ps->textlow)
+ {
+ printf_filtered ("Psymtab ");
+ puts_filtered (ps->filename);
+ printf_filtered (" covers bad range ");
+ fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
+ printf_filtered (" - ");
+ fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
+ printf_filtered ("\n");
+ continue;
+ }
+ if (ps->texthigh == 0)
+ continue;
+ if (ps->textlow < BLOCK_START (b) || ps->texthigh > BLOCK_END (b))
+ {
+ printf_filtered ("Psymtab ");
+ puts_filtered (ps->filename);
+ printf_filtered (" covers ");
+ fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
+ printf_filtered (" - ");
+ fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
+ printf_filtered (" but symtab covers only ");
+ fputs_filtered (paddress (gdbarch, BLOCK_START (b)), gdb_stdout);
+ printf_filtered (" - ");
+ fputs_filtered (paddress (gdbarch, BLOCK_END (b)), gdb_stdout);
+ printf_filtered ("\n");
+ }
+ }
+}
+
+
+
+void
+map_partial_symbol_names (void (*fun) (const char *, void *), void *data)
+{
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ {
+ if (objfile->sf)
+ objfile->sf->qf->map_symbol_names (objfile, fun, data);
+ }
+}
+
+void
+map_partial_symbol_filenames (void (*fun) (const char *, const char *,
+ void *),
+ void *data)
+{
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ {
+ if (objfile->sf)
+ objfile->sf->qf->map_symbol_filenames (objfile, fun, data);
+ }
+}