From 98c0e047bdd9407ada8b5ba18f89418bb6351614 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 19 Aug 1994 16:48:51 +0000 Subject: * Makefile.in (ALLDEPFILES): Add hpread.c. (hpread.o): Add dependencies. * somread.c: Do not include "aout/aout64.h". SOM has nothing to do with a.out. (BYTES_IN_WORD): Delete. (som_symfile_read): Call hpread_build_psymtabs to build any minimal symbols based on the HP C native debug symbols. (som_symfile_finish): Call hpread_symfile_finish. (som_symfile_init): Call hpread_symfile_init. * config/pa/tm-hppa.h (HPREAD_ADJUST_STACK_ADDRESS): Define. * hppa-tdep.c (hpread_adjust_stack_address): New function. * config/pa/hppabsd.mh (NATDEPFILES): Add hpread.o * config/pa/hppahpux.mh (NATDEPFILES): Likewise. * hpread.c: New file. --- gdb/hpread.c | 2044 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2044 insertions(+) create mode 100644 gdb/hpread.c (limited to 'gdb/hpread.c') diff --git a/gdb/hpread.c b/gdb/hpread.c new file mode 100644 index 0000000..f3acc7e --- /dev/null +++ b/gdb/hpread.c @@ -0,0 +1,2044 @@ +/* Read hp debug symbols and convert to internal format, for GDB. + Copyright 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Written by the Center for Software Science at the University of Utah + and by Cygnus Support. */ + +#include "defs.h" +#include "bfd.h" +#include +#include "hpux-symtab.h" +#include "syms.h" +#include "symtab.h" +#include "symfile.h" +#include "objfiles.h" +#include "buildsym.h" +#include "complaints.h" +#include "gdb-stabs.h" +#include "gdbtypes.h" + +/* Private information attached to an objfile which we use to find + and internalize the HP C debug symbols within that objfile. */ + +struct hpread_symfile_info +{ + /* The contents of each of the debug sections (there are 4 of them). */ + char *gntt; + char *lntt; + char *slt; + char *vt; + + /* We keep the size of the $VT$ section for range checking. */ + unsigned int vt_size; + + /* Some routines still need to know the number of symbols in the + main debug sections ($LNTT$ and $GNTT$). */ + unsigned int lntt_symcount; + unsigned int gntt_symcount; + + /* To keep track of all the types we've processed. */ + struct type **type_vector; + int type_vector_length; + + /* Keeps track of the beginning of a range of source lines. */ + SLTPOINTER sl_index; + + /* Some state variables we'll need. */ + int have_module; + int within_function; + + /* Keep track of the current function's address. We may need to look + up something based on this address. */ + unsigned int current_function_value; + +}; + +/* Accessor macros to get at the fields. */ +#define HPUX_SYMFILE_INFO(o) \ + ((struct hpread_symfile_info *)((o)->sym_private)) +#define GNTT(o) (HPUX_SYMFILE_INFO(o)->gntt) +#define LNTT(o) (HPUX_SYMFILE_INFO(o)->lntt) +#define SLT(o) (HPUX_SYMFILE_INFO(o)->slt) +#define VT(o) (HPUX_SYMFILE_INFO(o)->vt) +#define VT_SIZE(o) (HPUX_SYMFILE_INFO(o)->vt_size) +#define LNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->lntt_symcount) +#define GNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->gntt_symcount) +#define TYPE_VECTOR(o) (HPUX_SYMFILE_INFO(o)->type_vector) +#define TYPE_VECTOR_LENGTH(o) (HPUX_SYMFILE_INFO(o)->type_vector_length) +#define SL_INDEX(o) (HPUX_SYMFILE_INFO(o)->sl_index) +#define HAVE_MODULE(o) (HPUX_SYMFILE_INFO(o)->have_module) +#define WITHIN_FUNCTION(o) (HPUX_SYMFILE_INFO(o)->within_function) +#define CURRENT_FUNCTION_VALUE(o) (HPUX_SYMFILE_INFO(o)->current_function_value) + +/* Given the native debug symbol SYM, set NAMEP to the name associated + with the debug symbol. Note we may be called with a debug symbol which + has no associated name, in that case we return an empty string. + + Also note we "know" that the name for any symbol is always in the + same place. Hence we don't have to conditionalize on the symbol type. */ +#define SET_NAMESTRING(SYM, NAMEP, OBJFILE) \ + if (! hpread_has_name ((SYM)->dblock.kind)) \ + *NAMEP = ""; \ + else if (((unsigned)(SYM)->dsfile.name) >= VT_SIZE (OBJFILE)) \ + { \ + complain (&string_table_offset_complaint, (char *) symnum); \ + *NAMEP = ""; \ + } \ + else \ + *NAMEP = (SYM)->dsfile.name + VT (OBJFILE) + +/* Each partial symbol table entry contains a pointer to private data for the + read_symtab() function to use when expanding a partial symbol table entry + to a full symbol table entry. + + For hpuxread this structure contains the offset within the file symbol table + of first local symbol for this file, and length (in bytes) of the section + of the symbol table devoted to this file's symbols (actually, the section + bracketed may contain more than just this file's symbols). + + If ldsymlen is 0, the only reason for this thing's existence is the + dependency list. Nothing else will happen when it is read in. */ + +#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff) +#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen) +#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private)) + +struct symloc +{ + int ldsymoff; + int ldsymlen; +}; + +/* FIXME: Shouldn't this stuff be in a .h file somewhere? */ +/* Nonzero means give verbose info on gdb action. */ +extern int info_verbose; + +/* Complaints about the symbols we have encountered. */ +extern struct complaint string_table_offset_complaint; +extern struct complaint lbrac_unmatched_complaint; +extern struct complaint lbrac_mismatch_complaint; + + +void hpread_symfile_init PARAMS ((struct objfile *)); + +static struct type *hpread_alloc_type + PARAMS ((DNTTPOINTER, struct objfile *)); + +static struct type **hpread_lookup_type + PARAMS ((DNTTPOINTER, struct objfile *)); + +static struct type *hpread_read_enum_type + PARAMS ((DNTTPOINTER, union dnttentry *, struct objfile *)); + +static struct type *hpread_read_set_type + PARAMS ((DNTTPOINTER, union dnttentry *, struct objfile *)); + +static struct type *hpread_read_subrange_type + PARAMS ((DNTTPOINTER, union dnttentry *, struct objfile *)); + +static struct type *hpread_read_struct_type + PARAMS ((DNTTPOINTER, union dnttentry *, struct objfile *)); + +void hpread_build_psymtabs + PARAMS ((struct objfile *, struct section_offsets *, int)); + +void hpread_symfile_finish PARAMS ((struct objfile *)); + +static struct partial_symtab *hpread_start_psymtab + PARAMS ((struct objfile *, struct section_offsets *, char *, CORE_ADDR, int, + struct partial_symbol *, struct partial_symbol *)); + +static struct partial_symtab *hpread_end_psymtab + PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR, + struct partial_symtab **, int)); + +static struct symtab *hpread_expand_symtab + PARAMS ((struct objfile *, int, int, CORE_ADDR, int, + struct section_offsets *, char *)); + +static void hpread_process_one_debug_symbol + PARAMS ((union dnttentry *, char *, struct section_offsets *, + struct objfile *, CORE_ADDR, int, char *, int)); + +static SLTPOINTER hpread_record_lines + PARAMS ((struct subfile *, SLTPOINTER, SLTPOINTER, struct objfile *)); + +static struct type *hpread_read_function_type + PARAMS ((DNTTPOINTER, union dnttentry *, struct objfile *)); + +static struct type * hpread_type_lookup + PARAMS ((DNTTPOINTER, struct objfile *)); + +static unsigned long hpread_get_depth + PARAMS ((SLTPOINTER, struct objfile *)); + +static unsigned long hpread_get_line + PARAMS ((SLTPOINTER, struct objfile *)); + +static ADDRESS hpread_get_location + PARAMS ((SLTPOINTER, struct objfile *)); + +static int hpread_type_translate PARAMS ((DNTTPOINTER)); +static unsigned long hpread_get_textlow PARAMS ((int, int, struct objfile *)); +static union dnttentry *hpread_get_gntt PARAMS ((int, struct objfile *)); +static union dnttentry *hpread_get_lntt PARAMS ((int, struct objfile *)); +static union sltentry *hpread_get_slt PARAMS ((int, struct objfile *)); +static void hpread_psymtab_to_symtab PARAMS ((struct partial_symtab *)); +static void hpread_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *)); +static int hpread_has_name PARAMS ((KINDTYPE)); + + +/* Initialization for reading native HP C debug symbols from OBJFILE. + + It's only purpose in life is to set up the symbol reader's private + per-objfile data structures, and read in the raw contents of the debug + sections (attaching pointers to the debug info into the private data + structures. + + Since BFD doesn't know how to read debug symbols in a format-independent + way (and may never do so...), we have to do it ourselves. Note we may + be called on a file without native HP C debugging symbols. + FIXME, there should be a cleaner peephole into the BFD environment here. */ + +void +hpread_symfile_init (objfile) + struct objfile *objfile; +{ + asection *vt_section, *slt_section, *lntt_section, *gntt_section; + + /* Allocate struct to keep track of the symfile */ + objfile->sym_private = (PTR) + xmmalloc (objfile->md, sizeof (struct hpread_symfile_info)); + memset (objfile->sym_private, 0, sizeof (struct hpread_symfile_info)); + + /* We haven't read in any types yet. */ + TYPE_VECTOR (objfile) = 0; + + /* Read in data from the $GNTT$ subspace. */ + gntt_section = bfd_get_section_by_name (objfile->obfd, "$GNTT$"); + if (!gntt_section) + return; + + GNTT (objfile) + = obstack_alloc (&objfile->symbol_obstack, + bfd_section_size (objfile->obfd, gntt_section)); + + bfd_get_section_contents (objfile->obfd, gntt_section, GNTT (objfile), + 0, bfd_section_size (objfile->obfd, gntt_section)); + + GNTT_SYMCOUNT (objfile) + = bfd_section_size (objfile->obfd, gntt_section) / DNTTBLOCKSIZE; + + /* Read in data from the $LNTT$ subspace. Also keep track of the number + of LNTT symbols. */ + lntt_section = bfd_get_section_by_name (objfile->obfd, "$LNTT$"); + if (!lntt_section) + return; + + LNTT (objfile) + = obstack_alloc (&objfile->symbol_obstack, + bfd_section_size (objfile->obfd, lntt_section)); + + bfd_get_section_contents (objfile->obfd, lntt_section, LNTT (objfile), + 0, bfd_section_size (objfile->obfd, lntt_section)); + + LNTT_SYMCOUNT (objfile) + = bfd_section_size (objfile->obfd, lntt_section) / DNTTBLOCKSIZE; + + /* Read in data from the $SLT$ subspace. $SLT$ contains information + on source line numbers. */ + slt_section = bfd_get_section_by_name (objfile->obfd, "$SLT$"); + if (!slt_section) + return; + + SLT (objfile) = + obstack_alloc (&objfile->symbol_obstack, + bfd_section_size (objfile->obfd, slt_section)); + + bfd_get_section_contents (objfile->obfd, slt_section, SLT (objfile), + 0, bfd_section_size (objfile->obfd, slt_section)); + + /* Read in data from the $VT$ subspace. $VT$ contains things like + names and constants. Keep track of the number of symbols in the VT. */ + vt_section = bfd_get_section_by_name (objfile->obfd, "$VT$"); + if (!vt_section) + return; + + VT_SIZE (objfile) = bfd_section_size (objfile->obfd, vt_section); + + VT (objfile) = + (char *) obstack_alloc (&objfile->symbol_obstack, + VT_SIZE (objfile)); + + bfd_get_section_contents (objfile->obfd, vt_section, VT (objfile), + 0, VT_SIZE (objfile)); +} + +/* Scan and build partial symbols for a symbol file. + + The minimal symbol table (either SOM or HP a.out) has already been + read in; all we need to do is setup partial symbols based on the + native debugging information. + + We assume hpread_symfile_init has been called to initialize the + symbol reader's private data structures. + + SECTION_OFFSETS contains offsets relative to which the symbols in the + various sections are (depending where the sections were actually loaded). + MAINLINE is true if we are reading the main symbol + table (as opposed to a shared lib or dynamically loaded file). */ + +void +hpread_build_psymtabs (objfile, section_offsets, mainline) + struct objfile *objfile; + struct section_offsets *section_offsets; + int mainline; +{ + char *namestring; + int past_first_source_file = 0; + struct cleanup *old_chain; + + int hp_symnum, symcount, i; + + union dnttentry *dn_bufp; + unsigned long valu; + char *p; + int texthigh = 0; + int have_name = 0; + + /* Current partial symtab */ + struct partial_symtab *pst; + + /* List of current psymtab's include files */ + char **psymtab_include_list; + int includes_allocated; + int includes_used; + + /* Index within current psymtab dependency list */ + struct partial_symtab **dependency_list; + int dependencies_used, dependencies_allocated; + + /* Just in case the stabs reader left turds lying around. */ + pending_blocks = 0; + make_cleanup (really_free_pendings, 0); + + pst = (struct partial_symtab *) 0; + + /* We shouldn't use alloca, instead use malloc/free. Doing so avoids + a number of problems with cross compilation and creating useless holes + in the stack when we have to allocate new entries. FIXME. */ + + includes_allocated = 30; + includes_used = 0; + psymtab_include_list = (char **) alloca (includes_allocated * + sizeof (char *)); + + dependencies_allocated = 30; + dependencies_used = 0; + dependency_list = + (struct partial_symtab **) alloca (dependencies_allocated * + sizeof (struct partial_symtab *)); + + old_chain = make_cleanup (free_objfile, objfile); + + last_source_file = 0; + + /* Make two passes, one ofr the GNTT symbols, the other for the + LNTT symbols. */ + for (i = 0; i < 1; i++) + { + int within_function = 0; + + if (i) + symcount = GNTT_SYMCOUNT (objfile); + else + symcount = LNTT_SYMCOUNT (objfile); + + for (hp_symnum = 0; hp_symnum < symcount; hp_symnum++) + { + QUIT; + if (i) + dn_bufp = hpread_get_gntt (hp_symnum, objfile); + else + dn_bufp = hpread_get_lntt (hp_symnum, objfile); + + if (dn_bufp->dblock.extension) + continue; + + /* Only handle things which are necessary for minimal symbols. + everything else is ignored. */ + switch (dn_bufp->dblock.kind) + { + case K_SRCFILE: + { + /* A source file of some kind. Note this may simply + be an included file. */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + + /* Check if this is the source file we are already working + with. */ + if (pst && !strcmp (namestring, pst->filename)) + continue; + + /* Check if this is an include file, if so check if we have + already seen it. Add it to the include list */ + p = strrchr (namestring, '.'); + if (!strcmp (p, ".h")) + { + int j, found; + + found = 0; + for (j = 0; j < includes_used; j++) + if (!strcmp (namestring, psymtab_include_list[j])) + { + found = 1; + break; + } + if (found) + continue; + + /* Add it to the list of includes seen so far and + allocate more include space if necessary. */ + psymtab_include_list[includes_used++] = namestring; + if (includes_used >= includes_allocated) + { + char **orig = psymtab_include_list; + + psymtab_include_list = (char **) + alloca ((includes_allocated *= 2) * + sizeof (char *)); + memcpy ((PTR) psymtab_include_list, (PTR) orig, + includes_used * sizeof (char *)); + } + continue; + } + + + if (HAVE_MODULE (objfile)) + { + if (!have_name) + { + pst->filename = + (char *) obstack_alloc (&pst->objfile->psymbol_obstack, strlen (namestring) + 1); + strcpy (pst->filename, namestring); + have_name = 1; + continue; + } + continue; + } + + /* This is a bonafide new source file. + End the current partial symtab and start a new one. */ + + if (pst && past_first_source_file) + { + texthigh += ANOFFSET (section_offsets, SECT_OFF_TEXT); + hpread_end_psymtab (pst, psymtab_include_list, + includes_used, + hp_symnum * DNTTBLOCKSIZE, texthigh, + dependency_list, dependencies_used); + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + } + else + past_first_source_file = 1; + + valu = hpread_get_textlow (i, hp_symnum, objfile); + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT); + pst = hpread_start_psymtab (objfile, section_offsets, + namestring, valu, + hp_symnum * DNTTBLOCKSIZE, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + texthigh = valu; + continue; + } + + case K_MODULE: + /* A source file. It's still unclear to me what the + real difference between a K_SRCFILE and K_MODULE + is supposed to be. */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + valu = hpread_get_textlow (i, hp_symnum, objfile); + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT); + pst = hpread_start_psymtab (objfile, section_offsets, + namestring, valu, + hp_symnum * DNTTBLOCKSIZE, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + texthigh = valu; + HAVE_MODULE (objfile) = 1; + have_name = 0; + continue; + case K_FUNCTION: + case K_ENTRY: + /* The beginning of a function. K_ENTRY may also denote + a secondary entry point. */ + valu = dn_bufp->dfunc.lowaddr + + ANOFFSET (section_offsets, SECT_OFF_TEXT); + if (dn_bufp->dfunc.hiaddr > texthigh) + texthigh = dn_bufp->dfunc.hiaddr; + SET_NAMESTRING (dn_bufp, &namestring, objfile); + ADD_PSYMBOL_TO_LIST (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_BLOCK, + objfile->static_psymbols, valu, + language_unknown, objfile); + within_function = 1; + continue; + case K_BEGIN: + case K_END: + /* Scope block begin/end. We only care about function + and file blocks right now. */ + if (dn_bufp->dend.endkind == K_MODULE) + { + texthigh += ANOFFSET (section_offsets, SECT_OFF_TEXT); + hpread_end_psymtab (pst, psymtab_include_list, includes_used, + hp_symnum * DNTTBLOCKSIZE, texthigh, + dependency_list, dependencies_used); + pst = (struct partial_symtab *) 0; + includes_used = 0; + dependencies_used = 0; + HAVE_MODULE (objfile) = 0; + have_name = 0; + } + if (dn_bufp->dend.endkind == K_FUNCTION) + within_function = 0; + continue; + case K_SVAR: + case K_DVAR: + case K_TYPEDEF: + case K_TAGDEF: + { + /* Variables, typedefs an the like. */ + enum address_class storage; + enum namespace namespace; + + /* Don't add locals to the partial symbol table. */ + if (within_function + && (dn_bufp->dblock.kind == K_SVAR + || dn_bufp->dblock.kind == K_DVAR)) + continue; + + /* TAGDEFs go into the structure namespace. */ + if (dn_bufp->dblock.kind == K_TAGDEF) + namespace = STRUCT_NAMESPACE; + else + namespace = VAR_NAMESPACE; + + /* What kind of "storage" does this use? */ + if (dn_bufp->dblock.kind == K_SVAR) + storage = LOC_STATIC; + else if (dn_bufp->dblock.kind == K_DVAR + && dn_bufp->ddvar.regvar) + storage = LOC_REGISTER; + else if (dn_bufp->dblock.kind == K_DVAR) + storage = LOC_LOCAL; + else + storage = LOC_UNDEF; + + SET_NAMESTRING (dn_bufp, &namestring, objfile); + if (!pst) + { + pst = hpread_start_psymtab (objfile, section_offsets, + "globals", 0, + hp_symnum * DNTTBLOCKSIZE, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + } + if (dn_bufp->dsvar.public) + { + ADD_PSYMBOL_TO_LIST (namestring, strlen (namestring), + namespace, storage, + objfile->global_psymbols, + dn_bufp->dsvar.location, + language_unknown, objfile); + } + else + { + ADD_PSYMBOL_TO_LIST (namestring, strlen (namestring), + namespace, storage, + objfile->static_psymbols, + dn_bufp->dsvar.location, + language_unknown, objfile); + } + continue; + } + case K_MEMENUM: + case K_CONST: + /* Constants and members of enumerated types. */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + if (!pst) + { + pst = hpread_start_psymtab (objfile, section_offsets, + "globals", 0, + hp_symnum * DNTTBLOCKSIZE, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + } + ADD_PSYMBOL_TO_LIST (namestring, strlen (namestring), + VAR_NAMESPACE, LOC_CONST, + objfile->static_psymbols, 0, + language_unknown, objfile); + continue; + default: + continue; + } + } + } + + /* End any pending partial symbol table. */ + if (pst) + { + hpread_end_psymtab (pst, psymtab_include_list, includes_used, + hp_symnum * DNTTBLOCKSIZE, 0, + dependency_list, dependencies_used); + } + + discard_cleanups (old_chain); +} + +/* Perform any local cleanups required when we are done with a particular + objfile. I.E, we are in the process of discarding all symbol information + for an objfile, freeing up all memory held for it, and unlinking the + objfile struct from the global list of known objfiles. */ + +void +hpread_symfile_finish (objfile) + struct objfile *objfile; +{ + if (objfile->sym_private != NULL) + { + mfree (objfile->md, objfile->sym_private); + } +} + + +/* The remaining functions are all for internal use only. */ + +/* Various small functions to get entries in the debug symbol sections. */ + +static union dnttentry * +hpread_get_lntt (index, objfile) + int index; + struct objfile *objfile; +{ + return (union dnttentry *)&(LNTT (objfile)[index * DNTTBLOCKSIZE]); +} + +static union dnttentry * +hpread_get_gntt (index, objfile) + int index; + struct objfile *objfile; +{ + return (union dnttentry *)&(GNTT (objfile)[index * DNTTBLOCKSIZE]); +} + +static union sltentry * +hpread_get_slt (index, objfile) + int index; + struct objfile *objfile; +{ + return (union sltentry *)&(SLT (objfile)[index * SLTBLOCKSIZE]); +} + +/* Get the low address associated with some symbol (typically the start + of a particular source file or module). Since that information is not + stored as part of the K_MODULE or K_SRCFILE symbol we must infer it from + the existance of K_FUNCTION symbols. */ + +static unsigned long +hpread_get_textlow (global, index, objfile) + int global; + int index; + struct objfile *objfile; +{ + union dnttentry *dn_bufp; + struct minimal_symbol *msymbol; + + /* Look for a K_FUNCTION symbol. */ + do + { + if (global) + dn_bufp = hpread_get_gntt (index++, objfile); + else + dn_bufp = hpread_get_lntt (index++, objfile); + } while (dn_bufp->dblock.kind != K_FUNCTION + && dn_bufp->dblock.kind != K_END); + + /* Avoid going past a K_END when looking for a K_FUNCTION. This + might happen when a sourcefile has no functions. */ + if (dn_bufp->dblock.kind == K_END) + return 0; + + /* The minimal symbols are typically more accurate for some reason. */ + msymbol = lookup_minimal_symbol (dn_bufp->dfunc.name + VT (objfile), + objfile); + if (msymbol) + return SYMBOL_VALUE_ADDRESS (msymbol); + else + return dn_bufp->dfunc.lowaddr; +} + +/* Get the nesting depth for the source line identified by INDEX. */ + +static unsigned long +hpread_get_depth (index, objfile) + SLTPOINTER index; + struct objfile *objfile; +{ + union sltentry *sl_bufp; + + sl_bufp = hpread_get_slt (index, objfile); + return sl_bufp->sspec.backptr.dnttp.index; +} + +/* Get the source line number the the line identified by INDEX. */ + +static unsigned long +hpread_get_line (index, objfile) + SLTPOINTER index; + struct objfile *objfile; +{ + union sltentry *sl_bufp; + + sl_bufp = hpread_get_slt (index, objfile); + return sl_bufp->snorm.line; +} + +static ADDRESS +hpread_get_location (index, objfile) + SLTPOINTER index; + struct objfile *objfile; +{ + union sltentry *sl_bufp; + int i; + + /* code location of special sltentrys is determined from context */ + sl_bufp = hpread_get_slt (index, objfile); + + if (sl_bufp->snorm.sltdesc == SLT_END) + { + /* find previous normal sltentry and get address */ + for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) && + (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++) + sl_bufp = hpread_get_slt (index - i, objfile); + return sl_bufp->snorm.address; + } + + /* find next normal sltentry and get address */ + for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) && + (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++) + sl_bufp = hpread_get_slt (index + i, objfile); + return sl_bufp->snorm.address; +} + + +/* Return 1 if an HP debug symbol of type KIND has a name associated with + it, else return 0. */ + +static int +hpread_has_name (kind) + KINDTYPE kind; +{ + switch (kind) + { + case K_SRCFILE: + case K_MODULE: + case K_FUNCTION: + case K_ENTRY: + case K_IMPORT: + case K_LABEL: + case K_FPARAM: + case K_SVAR: + case K_DVAR: + case K_CONST: + case K_TYPEDEF: + case K_TAGDEF: + case K_MEMENUM: + case K_FIELD: + case K_SA: + return 1; + + case K_BEGIN: + case K_END: + case K_WITH: + case K_COMMON: + case K_POINTER: + case K_ENUM: + case K_SET: + case K_SUBRANGE: + case K_ARRAY: + case K_STRUCT: + case K_UNION: + case K_VARIANT: + case K_FILE: + case K_FUNCTYPE: + case K_COBSTRUCT: + case K_XREF: + case K_MACRO: + default: + return 0; + } +} + +/* Allocate and partially fill a partial symtab. It will be + completely filled at the end of the symbol list. + + SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR + is the address relative to which its symbols are (incremental) or 0 + (normal). */ + +static struct partial_symtab * +hpread_start_psymtab (objfile, section_offsets, + filename, textlow, ldsymoff, global_syms, static_syms) + struct objfile *objfile; + struct section_offsets *section_offsets; + char *filename; + CORE_ADDR textlow; + int ldsymoff; + struct partial_symbol *global_syms; + struct partial_symbol *static_syms; +{ + struct partial_symtab *result = + start_psymtab_common (objfile, section_offsets, + filename, textlow, global_syms, static_syms); + + result->read_symtab_private = (char *) + obstack_alloc (&objfile->psymbol_obstack, sizeof (struct symloc)); + LDSYMOFF (result) = ldsymoff; + result->read_symtab = hpread_psymtab_to_symtab; + + return result; +} + + +/* Close off the current usage of PST. + Returns PST or NULL if the partial symtab was empty and thrown away. + + FIXME: List variables and peculiarities of same. */ + +static struct partial_symtab * +hpread_end_psymtab (pst, include_list, num_includes, capping_symbol_offset, + capping_text, dependency_list, number_dependencies) + struct partial_symtab *pst; + char **include_list; + int num_includes; + int capping_symbol_offset; + CORE_ADDR capping_text; + struct partial_symtab **dependency_list; + int number_dependencies; +{ + int i; + struct objfile *objfile = pst -> objfile; + + if (capping_symbol_offset != -1) + LDSYMLEN(pst) = capping_symbol_offset - LDSYMOFF(pst); + pst->texthigh = capping_text; + + pst->n_global_syms = + objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = + objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset); + + pst->number_of_dependencies = number_dependencies; + if (number_dependencies) + { + pst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + number_dependencies * sizeof (struct partial_symtab *)); + memcpy (pst->dependencies, dependency_list, + number_dependencies * sizeof (struct partial_symtab *)); + } + else + pst->dependencies = 0; + + for (i = 0; i < num_includes; i++) + { + struct partial_symtab *subpst = + allocate_psymtab (include_list[i], objfile); + + subpst->section_offsets = pst->section_offsets; + subpst->read_symtab_private = + (char *) obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct symloc)); + LDSYMOFF(subpst) = + LDSYMLEN(subpst) = + subpst->textlow = + subpst->texthigh = 0; + + /* We could save slight bits of space by only making one of these, + shared by the entire set of include files. FIXME-someday. */ + subpst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct partial_symtab *)); + subpst->dependencies[0] = pst; + subpst->number_of_dependencies = 1; + + subpst->globals_offset = + subpst->n_global_syms = + subpst->statics_offset = + subpst->n_static_syms = 0; + + subpst->readin = 0; + subpst->symtab = 0; + subpst->read_symtab = pst->read_symtab; + } + + sort_pst_symbols (pst); + + /* If there is already a psymtab or symtab for a file of this name, remove it. + (If there is a symtab, more drastic things also happen.) + This happens in VxWorks. */ + free_named_symtabs (pst->filename); + + if (num_includes == 0 + && number_dependencies == 0 + && pst->n_global_syms == 0 + && pst->n_static_syms == 0) + { + /* Throw away this psymtab, it's empty. We can't deallocate it, since + it is on the obstack, but we can forget to chain it on the list. */ + /* 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. */ + struct partial_symtab *prev_pst; + + /* First, snip it out of the psymtab chain */ + + if (pst->objfile->psymtabs == pst) + pst->objfile->psymtabs = pst->next; + else + for (prev_pst = pst->objfile->psymtabs; prev_pst; prev_pst = pst->next) + if (prev_pst->next == pst) + prev_pst->next = pst->next; + + /* Next, put it on a free list for recycling */ + + pst->next = pst->objfile->free_psymtabs; + pst->objfile->free_psymtabs = pst; + + /* Indicate that psymtab was thrown away. */ + pst = (struct partial_symtab *)NULL; + } + return pst; +} + +/* Do the dirty work of reading in the full symbol from a partial symbol + table. */ + +static void +hpread_psymtab_to_symtab_1 (pst) + struct partial_symtab *pst; +{ + struct cleanup *old_chain; + int i; + + /* Get out quick if passed junk. */ + if (!pst) + return; + + /* Complain if we've already read in this symbol table. */ + if (pst->readin) + { + fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + pst->filename); + return; + } + + /* Read in all partial symtabs on which this one is dependent */ + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + fputs_filtered (" ", stdout); + wrap_here (""); + fputs_filtered ("and ", stdout); + wrap_here (""); + printf_filtered ("%s...", pst->dependencies[i]->filename); + wrap_here (""); /* Flush output */ + fflush (stdout); + } + hpread_psymtab_to_symtab_1 (pst->dependencies[i]); + } + + /* If it's real... */ + if (LDSYMLEN (pst)) + { + /* Init stuff necessary for reading in symbols */ + buildsym_init (); + old_chain = make_cleanup (really_free_pendings, 0); + + pst->symtab = + hpread_expand_symtab (pst->objfile, LDSYMOFF (pst), LDSYMLEN (pst), + pst->textlow, pst->texthigh - pst->textlow, + pst->section_offsets, pst->filename); + sort_symtab_syms (pst->symtab); + + do_cleanups (old_chain); + } + + pst->readin = 1; +} + +/* Read in all of the symbols for a given psymtab for real. + Be verbose about it if the user wants that. */ + +static void +hpread_psymtab_to_symtab (pst) + struct partial_symtab *pst; +{ + /* Get out quick if given junk. */ + if (!pst) + return; + + /* Sanity check. */ + if (pst->readin) + { + fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + pst->filename); + return; + } + + if (LDSYMLEN (pst) || pst->number_of_dependencies) + { + /* Print the message now, before reading the string table, + to avoid disconcerting pauses. */ + if (info_verbose) + { + printf_filtered ("Reading in symbols for %s...", pst->filename); + fflush (stdout); + } + + hpread_psymtab_to_symtab_1 (pst); + + /* Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. */ + scan_file_globals (pst->objfile); + + /* Finish up the debug error message. */ + if (info_verbose) + printf_filtered ("done.\n"); + } +} +/* Read in a defined section of a specific object file's symbols. + + DESC is the file descriptor for the file, positioned at the + beginning of the symtab + SYM_OFFSET is the offset within the file of + the beginning of the symbols we want to read + SYM_SIZE is the size of the symbol info to read in. + TEXT_OFFSET is the beginning of the text segment we are reading symbols for + TEXT_SIZE is the size of the text segment read in. + SECTION_OFFSETS are the relocation offsets which get added to each symbol. */ + +static struct symtab * +hpread_expand_symtab (objfile, sym_offset, sym_size, text_offset, text_size, + section_offsets, filename) + struct objfile *objfile; + int sym_offset; + int sym_size; + CORE_ADDR text_offset; + int text_size; + struct section_offsets *section_offsets; + char *filename; +{ + char *namestring; + union dnttentry *dn_bufp; + unsigned max_symnum; + + int sym_index = sym_offset / DNTTBLOCKSIZE; + + current_objfile = objfile; + subfile_stack = 0; + + last_source_file = 0; + + dn_bufp = hpread_get_lntt (sym_index, objfile); + if (!((dn_bufp->dblock.kind == (unsigned char) K_SRCFILE) || + (dn_bufp->dblock.kind == (unsigned char) K_MODULE))) + start_symtab ("globals", NULL, 0); + + max_symnum = sym_size / DNTTBLOCKSIZE; + + /* Read in and process each debug symbol within the specified range. */ + for (symnum = 0; + symnum < max_symnum; + symnum++) + { + QUIT; /* Allow this to be interruptable */ + dn_bufp = hpread_get_lntt (sym_index + symnum, objfile); + + if (dn_bufp->dblock.extension) + continue; + + /* Yow! We call SET_NAMESTRING on things without names! */ + SET_NAMESTRING (dn_bufp, &namestring, objfile); + + hpread_process_one_debug_symbol (dn_bufp, namestring, section_offsets, + objfile, text_offset, text_size, + filename, symnum + sym_index); + } + + current_objfile = NULL; + + return end_symtab (text_offset + text_size, 0, 0, objfile, 0); +} + + +/* Convert basic types from HP debug format into GDB internal format. */ + +static int +hpread_type_translate (typep) + DNTTPOINTER typep; +{ + if (!typep.dntti.immediate) + abort (); + + switch (typep.dntti.type) + { + case T_BOOLEAN: + case T_BOOLEAN_S300_COMPAT: + case T_BOOLEAN_VAX_COMPAT: + return FT_BOOLEAN; + /* Ugh. No way to distinguish between signed and unsigned chars. */ + case T_CHAR: + case T_WIDE_CHAR: + return FT_CHAR; + case T_INT: + if (typep.dntti.bitlength <= 8) + return FT_CHAR; + if (typep.dntti.bitlength <= 16) + return FT_SHORT; + if (typep.dntti.bitlength <= 32) + return FT_INTEGER; + return FT_LONG_LONG; + case T_LONG: + return FT_LONG; + case T_UNS_LONG: + return FT_UNSIGNED_LONG; + case T_UNS_INT: + if (typep.dntti.bitlength <= 8) + return FT_UNSIGNED_CHAR; + if (typep.dntti.bitlength <= 16) + return FT_UNSIGNED_SHORT; + if (typep.dntti.bitlength <= 32) + return FT_UNSIGNED_INTEGER; + return FT_UNSIGNED_LONG_LONG; + case T_REAL: + case T_REAL_3000: + case T_DOUBLE: + if (typep.dntti.bitlength == 64) + return FT_DBL_PREC_FLOAT; + if (typep.dntti.bitlength == 128) + return FT_EXT_PREC_FLOAT; + return FT_FLOAT; + case T_COMPLEX: + case T_COMPLEXS3000: + if (typep.dntti.bitlength == 128) + return FT_DBL_PREC_COMPLEX; + if (typep.dntti.bitlength == 192) + return FT_EXT_PREC_COMPLEX; + return FT_COMPLEX; + case T_STRING200: + case T_LONGSTRING200: + case T_FTN_STRING_SPEC: + case T_MOD_STRING_SPEC: + case T_MOD_STRING_3000: + case T_FTN_STRING_S300_COMPAT: + case T_FTN_STRING_VAX_COMPAT: + return FT_STRING; + default: + abort (); + } +} + +/* Return the type associated with the index found in HP_TYPE. */ + +static struct type ** +hpread_lookup_type (hp_type, objfile) + DNTTPOINTER hp_type; + struct objfile *objfile; +{ + unsigned old_len; + int index = hp_type.dnttp.index; + + if (hp_type.dntti.immediate) + return NULL; + + if (index < LNTT_SYMCOUNT (objfile)) + { + if (index >= TYPE_VECTOR_LENGTH (objfile)) + { + old_len = TYPE_VECTOR_LENGTH (objfile); + if (old_len == 0) + { + TYPE_VECTOR_LENGTH (objfile) = 100; + TYPE_VECTOR (objfile) = (struct type **) + malloc (TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *)); + } + while (index >= TYPE_VECTOR_LENGTH (objfile)) + TYPE_VECTOR_LENGTH (objfile) *= 2; + TYPE_VECTOR (objfile) = (struct type **) + xrealloc ((char *) TYPE_VECTOR (objfile), + (TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *))); + memset (&TYPE_VECTOR (objfile)[old_len], 0, + (TYPE_VECTOR_LENGTH (objfile) - old_len) * + sizeof (struct type *)); + } + return &TYPE_VECTOR (objfile)[index]; + } + else + return NULL; +} + +/* Possibly allocate a GDB internal type so we can internalize HP_TYPE. + Note we'll just return the address of a GDB internal type if we already + have it lying around. */ + +static struct type * +hpread_alloc_type (hp_type, objfile) + DNTTPOINTER hp_type; + struct objfile *objfile; +{ + struct type **type_addr; + + type_addr = hpread_lookup_type (hp_type, objfile); + if (*type_addr == 0) + *type_addr = alloc_type (objfile); + + TYPE_CPLUS_SPECIFIC (*type_addr) + = (struct cplus_struct_type *) &cplus_struct_default; + return *type_addr; +} + +/* Read a native enumerated type and return it in GDB internal form. */ + +static struct type * +hpread_read_enum_type (hp_type, dn_bufp, objfile) + DNTTPOINTER hp_type; + union dnttentry *dn_bufp; + struct objfile *objfile; +{ + struct type *type; + struct pending **symlist, *osyms, *syms; + int o_nsyms, nsyms = 0; + DNTTPOINTER mem; + union dnttentry *memp; + char *name; + long n; + struct symbol *sym; + + type = hpread_alloc_type (hp_type, objfile); + TYPE_LENGTH (type) = 4; + + symlist = &file_symbols; + osyms = *symlist; + o_nsyms = osyms ? osyms->nsyms : 0; + + /* Get a name for each member and add it to our list of members. */ + mem = dn_bufp->denum.firstmem; + while (mem.dnttp.extension && mem.word != DNTTNIL) + { + memp = hpread_get_lntt (mem.dnttp.index, objfile); + + name = VT (objfile) + memp->dmember.name; + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = name; + SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_VALUE (sym) = memp->dmember.value; + add_symbol_to_list (sym, symlist); + nsyms++; + mem = memp->dmember.nextmem; + } + + /* Now that we know more about the enum, fill in more info. */ + TYPE_CODE (type) = TYPE_CODE_ENUM; + TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB; + TYPE_NFIELDS (type) = nsyms; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nsyms); + + /* Find the symbols for the members and put them into the type. + The symbols can be found in the symlist that we put them on + to cause them to be defined. osyms contains the old value + of that symlist; everything up to there was defined by us. + + Note that we preserve the order of the enum constants, so + that in something like "enum {FOO, LAST_THING=FOO}" we print + FOO, not LAST_THING. */ + for (syms = *symlist, n = 0; syms; syms = syms->next) + { + int j = 0; + if (syms == osyms) + j = o_nsyms; + for (; j < syms->nsyms; j++, n++) + { + struct symbol *xsym = syms->symbol[j]; + SYMBOL_TYPE (xsym) = type; + TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym); + TYPE_FIELD_VALUE (type, n) = 0; + TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym); + TYPE_FIELD_BITSIZE (type, n) = 0; + } + if (syms == osyms) + break; + } + + return type; +} + +/* Read and internalize a native function debug symbol. */ + +static struct type * +hpread_read_function_type (hp_type, dn_bufp, objfile) + DNTTPOINTER hp_type; + union dnttentry *dn_bufp; + struct objfile *objfile; +{ + struct type *type, *type1; + struct pending **symlist, *osyms, *syms; + int o_nsyms, nsyms = 0; + DNTTPOINTER param; + union dnttentry *paramp; + char *name; + long n; + struct symbol *sym; + + param = dn_bufp->dfunc.firstparam; + + /* See if we've already read in this type. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_FUNC) + return type; + + /* Nope, so read it in and store it away. */ + type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunc.retval, + objfile)); + memcpy ((char *) type, (char *) type1, sizeof (struct type)); + + symlist = &local_symbols; + osyms = *symlist; + o_nsyms = osyms ? osyms->nsyms : 0; + + /* Now examine each parameter noting its type, location, and a + wealth of other information. */ + while (param.word && param.word != DNTTNIL) + { + paramp = hpread_get_lntt (param.dnttp.index, objfile); + nsyms++; + param = paramp->dfparam.nextparam; + + /* Get the name. */ + name = VT (objfile) + paramp->dfparam.name; + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + (void) memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = name; + + /* Figure out where it lives. */ + if (paramp->dfparam.regparam) + SYMBOL_CLASS (sym) = LOC_REGPARM; + else if (paramp->dfparam.indirect) + SYMBOL_CLASS (sym) = LOC_REF_ARG; + else + SYMBOL_CLASS (sym) = LOC_ARG; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + if (paramp->dfparam.copyparam) + { + SYMBOL_VALUE (sym) = paramp->dfparam.location ; +#ifdef HPREAD_ADJUST_STACK_ADDRESS + SYMBOL_VALUE (sym) + += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile)); +#endif + /* This is likely a pass-by-invisible reference parameter, + Hack on the symbol class to make GDB happy. */ + SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR; + } + else + SYMBOL_VALUE (sym) = paramp->dfparam.location; + + /* Get its type. */ + SYMBOL_TYPE (sym) = hpread_type_lookup (paramp->dfparam.type, objfile); + + /* Add it to the list. */ + add_symbol_to_list (sym, symlist); + } + + /* Note how many parameters we found. */ + TYPE_NFIELDS (type) = nsyms; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, + sizeof (struct field) * nsyms); + + /* Find the symbols for the values and put them into the type. + The symbols can be found in the symlist that we put them on + to cause them to be defined. osyms contains the old value + of that symlist; everything up to there was defined by us. */ + /* Note that we preserve the order of the parameters, so + that in something like "enum {FOO, LAST_THING=FOO}" we print + FOO, not LAST_THING. */ + for (syms = *symlist, n = 0; syms; syms = syms->next) + { + int j = 0; + if (syms == osyms) + j = o_nsyms; + for (; j < syms->nsyms; j++, n++) + { + struct symbol *xsym = syms->symbol[j]; + TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym); + TYPE_FIELD_TYPE (type, n) = SYMBOL_TYPE (xsym); + TYPE_FIELD_BITPOS (type, n) = n; + TYPE_FIELD_BITSIZE (type, n) = 0; + } + if (syms == osyms) + break; + } + return type; +} + +/* Read in and internalize a structure definition. */ + +static struct type * +hpread_read_struct_type (hp_type, dn_bufp, objfile) + DNTTPOINTER hp_type; + union dnttentry *dn_bufp; + struct objfile *objfile; +{ + struct nextfield + { + struct nextfield *next; + struct field field; + }; + + struct type *type; + struct nextfield *list = 0; + struct nextfield *new; + int n, nfields = 0; + DNTTPOINTER field; + union dnttentry *fieldp; + + /* Is it something we've already dealt with? */ + type = hpread_alloc_type (hp_type, objfile); + if ((TYPE_CODE (type) == TYPE_CODE_STRUCT) || + (TYPE_CODE (type) == TYPE_CODE_UNION)) + return type; + + /* Get the basic type correct. */ + if (dn_bufp->dblock.kind == K_STRUCT) + { + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_LENGTH (type) = dn_bufp->dstruct.bitlength / 8; + } + else if (dn_bufp->dblock.kind == K_UNION) + { + TYPE_CODE (type) = TYPE_CODE_UNION; + TYPE_LENGTH (type) = dn_bufp->dunion.bitlength / 8; + } + else + return type; + + + TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB; + + /* Read in and internalize all the fields. */ + field = dn_bufp->dstruct.firstfield; + while (field.word != DNTTNIL && field.dnttp.extension) + { + fieldp = hpread_get_lntt (field.dnttp.index, objfile); + + /* Get space to record the next field's data. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + list->field.name = VT (objfile) + fieldp->dfield.name; + list->field.bitpos = fieldp->dfield.bitoffset; + if (fieldp->dfield.bitlength % 8) + list->field.bitsize = fieldp->dfield.bitlength; + else + list->field.bitsize = 0; + nfields++; + field = fieldp->dfield.nextfield; + list->field.type = hpread_type_lookup (fieldp->dfield.type, objfile); + } + + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nfields); + + /* Copy the saved-up fields into the field vector. */ + for (n = nfields; list; list = list->next) + { + n -= 1; + TYPE_FIELD (type, n) = list->field; + } + return type; +} + +/* Read in and internalize a set debug symbol. */ + +static struct type * +hpread_read_set_type (hp_type, dn_bufp, objfile) + DNTTPOINTER hp_type; + union dnttentry *dn_bufp; + struct objfile *objfile; +{ + struct type *type; + + /* See if it's something we've already deal with. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_SET) + return type; + + /* Nope. Fill in the appropriate fields. */ + TYPE_CODE (type) = TYPE_CODE_SET; + TYPE_LENGTH (type) = dn_bufp->dset.bitlength / 8; + TYPE_NFIELDS (type) = 0; + TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dset.subtype, + objfile); + return type; +} + +/* Read in and internalize an array debug symbol. */ + +static struct type * +hpread_read_array_type (hp_type, dn_bufp, objfile) + DNTTPOINTER hp_type; + union dnttentry *dn_bufp; + struct objfile *objfile; +{ + struct type *type; + union dnttentry save; + save = *dn_bufp; + + /* Why no check here? Because it kept us from properly determining + the size of the array! */ + type = hpread_alloc_type (hp_type, objfile); + + TYPE_CODE (type) = TYPE_CODE_ARRAY; + + /* values are not normalized. */ + if (!((dn_bufp->darray.arrayisbytes && dn_bufp->darray.elemisbytes) + || (!dn_bufp->darray.arrayisbytes && !dn_bufp->darray.elemisbytes))) + abort (); + else if (dn_bufp->darray.arraylength == 0x7fffffff) + { + /* The HP debug format represents char foo[]; as an array with + length 0x7fffffff. Internally GDB wants to represent this + as a pointer. Ugh. */ + TYPE_CODE (type) = TYPE_CODE_PTR; + TYPE_LENGTH (type) = 4; + } + else + TYPE_LENGTH (type) = dn_bufp->darray.arraylength / 8; + + TYPE_NFIELDS (type) = 1; + TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->darray.elemtype, + objfile); + dn_bufp = &save; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (&objfile->type_obstack, sizeof (struct field)); + TYPE_FIELD_TYPE (type, 0) = hpread_type_lookup (dn_bufp->darray.indextype, + objfile); + return type; +} + +/* Read in and internalize a subrange debug symbol. */ +static struct type * +hpread_read_subrange_type (hp_type, dn_bufp, objfile) + DNTTPOINTER hp_type; + union dnttentry *dn_bufp; + struct objfile *objfile; +{ + struct type *type; + + /* Is it something we've already dealt with. */ + type = hpread_alloc_type (hp_type, objfile); + if (TYPE_CODE (type) == TYPE_CODE_RANGE) + return type; + + /* Nope, internalize it. */ + TYPE_CODE (type) = TYPE_CODE_RANGE; + TYPE_LENGTH (type) = dn_bufp->dsubr.bitlength / 8; + TYPE_NFIELDS (type) = 2; + TYPE_FIELDS (type) = (struct field *) obstack_alloc + (&objfile->type_obstack, 2 * sizeof (struct field)); + + if (dn_bufp->dsubr.dyn_low) + TYPE_FIELD_BITPOS (type, 0) = 0; + else + TYPE_FIELD_BITPOS (type, 0) = dn_bufp->dsubr.lowbound; + + if (dn_bufp->dsubr.dyn_high) + TYPE_FIELD_BITPOS (type, 1) = -1; + else + TYPE_FIELD_BITPOS (type, 1) = dn_bufp->dsubr.highbound; + TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dsubr.subtype, + objfile); + return type; +} + +static struct type * +hpread_type_lookup (hp_type, objfile) + DNTTPOINTER hp_type; + struct objfile *objfile; +{ + union dnttentry *dn_bufp; + + /* First see if it's a simple builtin type. */ + if (hp_type.dntti.immediate) + return lookup_fundamental_type (objfile, hpread_type_translate (hp_type)); + + /* Not a builtin type. We'll have to read it in. */ + if (hp_type.dnttp.index < LNTT_SYMCOUNT (objfile)) + dn_bufp = hpread_get_lntt (hp_type.dnttp.index, objfile); + else + return lookup_fundamental_type (objfile, FT_VOID); + + switch (dn_bufp->dblock.kind) + { + case K_SRCFILE: + case K_MODULE: + case K_FUNCTION: + case K_ENTRY: + case K_BEGIN: + case K_END: + case K_IMPORT: + case K_LABEL: + case K_WITH: + case K_COMMON: + case K_FPARAM: + case K_SVAR: + case K_DVAR: + case K_CONST: + /* Opps. Something went very wrong. */ + return lookup_fundamental_type (objfile, FT_VOID); + + case K_TYPEDEF: + { + struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type, + objfile); + char *suffix; + suffix = VT (objfile) + dn_bufp->dtype.name; + + TYPE_CPLUS_SPECIFIC (structtype) + = (struct cplus_struct_type *) &cplus_struct_default; + TYPE_NAME (structtype) = suffix; + return structtype; + } + + case K_TAGDEF: + { + /* Just a little different from above. We have to tack on + an identifier of some kind (struct, union, enum, etc). */ + struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type, + objfile); + char *prefix, *suffix; + suffix = VT (objfile) + dn_bufp->dtype.name; + + /* Lookup the next type in the list. It should be a structure, + union, or enum type. We will need to attach that to our name. */ + if (dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile)) + dn_bufp = hpread_get_lntt (dn_bufp->dtype.type.dnttp.index, objfile); + else + abort (); + + if (dn_bufp->dblock.kind == K_STRUCT) + prefix = "struct "; + else if (dn_bufp->dblock.kind == K_UNION) + prefix = "union "; + else + prefix = "enum "; + + /* Build the correct name. */ + structtype->name + = (char *) obstack_alloc (&objfile->type_obstack, + strlen (prefix) + strlen (suffix) + 1); + TYPE_NAME (structtype) = strcpy (TYPE_NAME (structtype), prefix); + TYPE_NAME (structtype) = strcat (TYPE_NAME (structtype), suffix); + TYPE_TAG_NAME (structtype) = suffix; + + TYPE_CPLUS_SPECIFIC (structtype) + = (struct cplus_struct_type *) &cplus_struct_default; + + return structtype; + } + case K_POINTER: + return lookup_pointer_type (hpread_type_lookup (dn_bufp->dptr.pointsto, + objfile)); + case K_ENUM: + return hpread_read_enum_type (hp_type, dn_bufp, objfile); + case K_MEMENUM: + return lookup_fundamental_type (objfile, FT_VOID); + case K_SET: + return hpread_read_set_type (hp_type, dn_bufp, objfile); + case K_SUBRANGE: + return hpread_read_subrange_type (hp_type, dn_bufp, objfile); + case K_ARRAY: + return hpread_read_array_type (hp_type, dn_bufp, objfile); + case K_STRUCT: + case K_UNION: + return hpread_read_struct_type (hp_type, dn_bufp, objfile); + case K_FIELD: + return hpread_type_lookup (dn_bufp->dfield.type, objfile); + case K_VARIANT: + case K_FILE: + return lookup_fundamental_type (objfile, FT_VOID); + case K_FUNCTYPE: + return lookup_function_type (hpread_type_lookup (dn_bufp->dfunctype.retval, + objfile)); + case K_COBSTRUCT: + case K_XREF: + case K_SA: + case K_MACRO: + default: + return lookup_fundamental_type (objfile, FT_VOID); + } +} + +static SLTPOINTER +hpread_record_lines (subfile, s_idx, e_idx, objfile) + struct subfile *subfile; + SLTPOINTER s_idx, e_idx; + struct objfile *objfile; +{ + union sltentry *sl_bufp; + + while (s_idx <= e_idx) + { + sl_bufp = hpread_get_slt (s_idx, objfile); + /* Only record "normal" entries in the SLT. */ + if (sl_bufp->snorm.sltdesc == SLT_NORMAL + || sl_bufp->snorm.sltdesc == SLT_EXIT) + record_line (subfile, sl_bufp->snorm.line, sl_bufp->snorm.address); + s_idx++; + } + return e_idx; +} + +/* Internalize one native debug symbol. */ + +static void +hpread_process_one_debug_symbol (dn_bufp, name, section_offsets, objfile, + text_offset, text_size, filename, index) + union dnttentry *dn_bufp; + char *name; + struct section_offsets *section_offsets; + struct objfile *objfile; + CORE_ADDR text_offset; + int text_size; + char *filename; + int index; +{ + unsigned long desc; + int type; + CORE_ADDR valu; + int offset = ANOFFSET (section_offsets, SECT_OFF_TEXT); + union dnttentry *dn_temp; + DNTTPOINTER hp_type; + struct symbol *sym; + struct context_stack *new; + char *p; + + /* Allocate one GDB debug symbol and fill in some default values. */ + sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = name; + SYMBOL_LANGUAGE (sym) = language_auto; + SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack); + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_LINE (sym) = 0; + SYMBOL_VALUE (sym) = 0; + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + + hp_type.dnttp.extension = 1; + hp_type.dnttp.immediate = 0; + hp_type.dnttp.global = 0; + hp_type.dnttp.index = index; + + type = dn_bufp->dblock.kind; + + switch (type) + { + case K_SRCFILE: + /* This type of symbol indicates from which source file or include file + the following data comes. If there are no modules it also may + indicate the start of a new source file, in which case we must + finish the symbol table of the previous source file + (if any) and start accumulating a new symbol table. */ + + valu = text_offset + offset; /* Relocate for dynamic loading */ + p = strrchr (name, '.'); + if (!strcmp (p, ".h") || HAVE_MODULE (objfile) + || (last_source_file && !strcmp (name, last_source_file))) + { + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dsfile.address, + objfile); + start_subfile (name, NULL); + break; + } + + if (last_source_file) + { + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dsfile.address, + objfile); + end_symtab (valu + text_size, 0, 0, objfile, 0); + } + + SL_INDEX (objfile) = dn_bufp->dsfile.address; + start_symtab (name, NULL, valu); + break; + + case K_MODULE: + /* This kind of symbol indicates the start of a module or C source + file */ + valu = text_offset + offset; /* Relocate for dynamic loading */ + SL_INDEX (objfile) = dn_bufp->dmodule.address; + start_symtab (filename, NULL, valu); + break; + + case K_FUNCTION: + case K_ENTRY: + /* A function or secondary entry point. */ + valu = dn_bufp->dfunc.lowaddr + offset; + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dfunc.address, + objfile); + + WITHIN_FUNCTION (objfile) = 1; + CURRENT_FUNCTION_VALUE (objfile) = valu; + + /* Stack must be empty now. */ + if (context_stack_depth != 0) + complain (&lbrac_unmatched_complaint, (char *) symnum); + new = push_context (0, valu); + + SYMBOL_CLASS (sym) = LOC_BLOCK; + SYMBOL_TYPE (sym) = hpread_read_function_type (hp_type, dn_bufp, objfile); + if (dn_bufp->dfunc.public) + add_symbol_to_list (sym, &global_symbols); + else + add_symbol_to_list (sym, &file_symbols); + new->name = sym; + + /* Search forward to the next scope beginning. */ + while (dn_bufp->dblock.kind != K_BEGIN) + { + dn_bufp = hpread_get_lntt (++index, objfile); + if (dn_bufp->dblock.extension) + continue; + } + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dbegin.address, + objfile); + SYMBOL_LINE (sym) = hpread_get_line (dn_bufp->dbegin.address, objfile); + record_line (current_subfile, SYMBOL_LINE (sym), valu); + break; + + case K_BEGIN: + /* Begin a new scope. */ + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dbegin.address, + objfile); + valu = hpread_get_location (dn_bufp->dbegin.address, objfile); + valu += offset; /* Relocate for dynamic loading */ + desc = hpread_get_depth (dn_bufp->dbegin.address, objfile); + new = push_context (desc, valu); + break; + + case K_END: + /* End a scope. */ + SL_INDEX (objfile) = hpread_record_lines (current_subfile, + SL_INDEX (objfile), + dn_bufp->dend.address + 1, + objfile); + switch (dn_bufp->dend.endkind) + { + case K_MODULE: + /* Ending a module ends the symbol table for that module. */ + valu = text_offset + text_size + offset; + (void) end_symtab (valu, 0, 0, objfile, 0); + break; + + case K_FUNCTION: + /* Ending a function, well, ends the function's scope. */ + dn_temp = hpread_get_lntt (dn_bufp->dend.beginscope.dnttp.index, + objfile); + valu = dn_temp->dfunc.hiaddr + offset; + new = pop_context (); + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); + WITHIN_FUNCTION (objfile) = 0; + break; + case K_BEGIN: + /* Just ending a local scope. */ + valu = hpread_get_location (dn_bufp->dend.address, objfile); + /* Why in the hell is this needed? */ + valu += offset + 9; /* Relocate for dynamic loading */ + new = pop_context (); + desc = dn_bufp->dend.beginscope.dnttp.index; + if (desc != new->depth) + complain (&lbrac_mismatch_complaint, (char *) symnum); + /* Make a block for the local symbols within. */ + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); + local_symbols = new->locals; + break; + } + break; + case K_LABEL: + SYMBOL_NAMESPACE (sym) = LABEL_NAMESPACE; + break; + case K_FPARAM: + /* Function parameters. */ + if (dn_bufp->dfparam.regparam) + SYMBOL_CLASS (sym) = LOC_REGISTER; + else + SYMBOL_CLASS (sym) = LOC_LOCAL; + if (dn_bufp->dfparam.copyparam) + { + SYMBOL_VALUE (sym) = dn_bufp->dfparam.location; +#ifdef HPREAD_ADJUST_STACK_ADDRESS + SYMBOL_VALUE (sym) + += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile)); +#endif + } + else + SYMBOL_VALUE (sym) = dn_bufp->dfparam.location; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dfparam.type, objfile); + add_symbol_to_list (sym, &local_symbols); + break; + case K_SVAR: + /* Static variables. */ + SYMBOL_CLASS (sym) = LOC_STATIC; + SYMBOL_VALUE_ADDRESS (sym) = dn_bufp->dsvar.location; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dsvar.type, objfile); + if (dn_bufp->dsvar.public) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + case K_DVAR: + /* Dynamic variables. */ + if (dn_bufp->ddvar.regvar) + SYMBOL_CLASS (sym) = LOC_REGISTER; + else + SYMBOL_CLASS (sym) = LOC_LOCAL; + SYMBOL_VALUE (sym) = dn_bufp->ddvar.location; +#ifdef HPREAD_ADJUST_STACK_ADDRESS + SYMBOL_VALUE (sym) + += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile)); +#endif + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->ddvar.type, objfile); + if (dn_bufp->ddvar.public) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + case K_CONST: + /* A constant (pascal?). */ + SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_VALUE (sym) = dn_bufp->dconst.location; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dconst.type, objfile); + if (dn_bufp->dconst.public) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + case K_TYPEDEF: + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile); + if (dn_bufp->dtype.public) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + case K_TAGDEF: + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile); + TYPE_NAME (sym->type) = SYMBOL_NAME (sym); + TYPE_TAG_NAME (sym->type) = SYMBOL_NAME (sym); + if (dn_bufp->dtype.public) + add_symbol_to_list (sym, &global_symbols); + else if (WITHIN_FUNCTION (objfile)) + add_symbol_to_list (sym, &local_symbols); + else + add_symbol_to_list (sym, &file_symbols); + break; + case K_POINTER: + SYMBOL_TYPE (sym) = lookup_pointer_type (hpread_type_lookup + (dn_bufp->dptr.pointsto, + objfile)); + add_symbol_to_list (sym, &file_symbols); + break; + case K_ENUM: + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + SYMBOL_TYPE (sym) = hpread_read_enum_type (hp_type, dn_bufp, objfile); + add_symbol_to_list (sym, &file_symbols); + break; + case K_MEMENUM: + break; + case K_SET: + SYMBOL_TYPE (sym) = hpread_read_set_type (hp_type, dn_bufp, objfile); + add_symbol_to_list (sym, &file_symbols); + break; + case K_SUBRANGE: + SYMBOL_TYPE (sym) = hpread_read_subrange_type (hp_type, dn_bufp, + objfile); + add_symbol_to_list (sym, &file_symbols); + break; + case K_ARRAY: + SYMBOL_TYPE (sym) = hpread_read_array_type (hp_type, dn_bufp, objfile); + add_symbol_to_list (sym, &file_symbols); + break; + case K_STRUCT: + case K_UNION: + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + SYMBOL_TYPE (sym) = hpread_read_struct_type (hp_type, dn_bufp, objfile); + add_symbol_to_list (sym, &file_symbols); + break; + default: + break; + } +} -- cgit v1.1