+#ifdef DUMPING
+ if (dumping)
+ printf ("Maybe skipping file %s which overlaps with module %s\n",
+ &vt_bits[(long) qFD[curr_fd].sbFile], mod_name_string);
+#endif
+ if (CURR_FILE_END > end_adr)
+ {
+ TELL_OBJFILE;
+ warning ("File \"%s\" [0x%x] crosses end of module \"%s\".",
+ &vt_bits[(long) qFD[curr_fd].sbFile],
+ curr_fd, mod_name_string);
+ end_adr = CURR_FILE_END;
+ }
+ curr_fd++;
+ }
+ curr_fd--; /* back up after going too far */
+ }
+
+ /* Sometimes (compiler bug -- COBOL) the module end address is higher
+ than the start address of the next module, so check for that and
+ adjust accordingly */
+
+ if (VALID_MODULE (curr_md + 1) && (MODULE_START (curr_md + 1) <= end_adr))
+ {
+ TELL_OBJFILE;
+ warning ("Module \"%s\" [0x%x] has ending address after starting address of next module; adjusting ending address down.",
+ mod_name_string, curr_md);
+ end_adr = MODULE_START (curr_md + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */
+ }
+ if (VALID_FILE (curr_fd + 1) && (FILE_START (curr_fd + 1) <= end_adr))
+ {
+ TELL_OBJFILE;
+ warning ("Module \"%s\" [0x%x] has ending address after starting address of next file; adjusting ending address down.",
+ mod_name_string, curr_md);
+ end_adr = FILE_START (curr_fd + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */
+ }
+
+ /* Use one file to get the full name for the module. This
+ situation can arise if there is executable code in a #include
+ file. Each file with code in it gets a qFD. Files which don't
+ contribute code don't get a qFD, even if they include files
+ which do, e.g.:
+
+ body.c: rtn.h:
+ int x; int main() {
+ #include "rtn.h" return x;
+ }
+
+ There will a qFD for "rtn.h",and a qMD for "body.c",
+ but no qMD for "rtn.h" or qFD for "body.c"!
+
+ We pick the name of the last file to overlap with this
+ module. C convention is to put include files first. In a
+ perfect world, we could check names and use the file whose full
+ path name ends with the module name. */
+
+ if (VALID_CURR_FILE)
+ full_name_string = &vt_bits[(long) qFD[curr_fd].sbFile];
+ else
+ full_name_string = mod_name_string;
+
+ /* Check if there are any procedures not handled until now, that
+ begin before the start address we have now, and if so, adjust
+ this psymtab's start address to include them. This handles routines that
+ are in between file or module ranges for some reason (probably
+ indicates a compiler bug */
+
+ if (CURR_PROC_START < start_adr)
+ {
+ TELL_OBJFILE;
+ warning ("Found procedure \"%s\" [0x%x] that is not in any file or module.",
+ &vt_bits[(long) qPD[curr_pd].sbProc], curr_pd);
+ start_adr = CURR_PROC_START;
+ if (CURR_PROC_ISYM < start_sym)
+ start_sym = CURR_PROC_ISYM;
+ }
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Make new psymtab for module %s (%x to %x), using file %s\n",
+ mod_name_string, start_adr, end_adr, full_name_string);
+ }
+#endif
+ /* Create the basic psymtab, connecting it in the list
+ for this objfile and pointing its symbol entries
+ to the current end of the symbol areas in the objfile.
+
+ The "ldsymoff" parameter is the byte offset in the LNTT
+ of the first symbol in this file. Some day we should
+ turn this into an index (fix in hp-symtab-read.c as well).
+ And it's not even the right byte offset, as we're using
+ the size of a union! FIXME! */
+ pst = hpread_start_psymtab (objfile,
+ full_name_string,
+ start_adr, /* Low text address */
+ (start_sym * sizeof (struct dntt_type_block)),
+ /* ldsymoff */
+ global_syms,
+ static_syms);
+
+ /* Set up to only enter each class referenced in this module once. */
+ class_entered = xmalloc (B_BYTES (pxdb_header_p->cd_entries));
+ B_CLRALL (class_entered, pxdb_header_p->cd_entries);
+
+ /* Scan the procedure descriptors for procedures in the current
+ module, based on the starting addresses. */
+
+ syms_in_pst = scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries,
+ start_adr, end_adr, pst, vt_bits, objfile);
+
+ /* Get ending symbol offset */
+
+ end_sym = 0;
+ /* First check for starting index before previous psymtab */
+ if (pst_syms_count && start_sym < pst_syms_array[pst_syms_count - 1].end)
+ {
+ end_sym = find_next_pst_start (start_sym);
+ }
+ /* Look for next start index of a file or module, or procedure */
+ if (!end_sym)
+ {
+ int next_file_isym = find_next_file_isym (start_sym, qFD, curr_fd + 1, pxdb_header_p);
+ int next_module_isym = find_next_module_isym (start_sym, qMD, curr_md + 1, pxdb_header_p);
+ int next_proc_isym = find_next_proc_isym (start_sym, qPD, curr_pd, pxdb_header_p);
+
+ if (next_file_isym && next_module_isym)
+ {
+ /* pick lower of next file or module start index */
+ end_sym = min (next_file_isym, next_module_isym);
+ }
+ else
+ {
+ /* one of them is zero, pick the other */
+ end_sym = max (next_file_isym, next_module_isym);
+ }
+
+ /* As a precaution, check next procedure index too */
+ if (!end_sym)
+ end_sym = next_proc_isym;
+ else
+ end_sym = min (end_sym, next_proc_isym);
+ }
+
+ /* Couldn't find procedure, file, or module, use globals as default */
+ if (!end_sym)
+ end_sym = pxdb_header_p->globals;
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Module psymtab indices: %x to %x\n", start_sym, end_sym);
+ }
+#endif
+
+ pst = hpread_end_psymtab (pst,
+ NULL, /* psymtab_include_list */
+ 0, /* includes_used */
+ end_sym * sizeof (struct dntt_type_block),
+ /* byte index in LNTT of end
+ = capping symbol offset
+ = LDSYMOFF of nextfile */
+ end_adr, /* text high */
+ NULL, /* dependency_list */
+ 0); /* dependencies_used */
+
+ record_pst_syms (start_sym, end_sym);
+
+ if (NULL == pst)
+ warning ("No symbols in psymtab for module \"%s\" [0x%x].", mod_name_string, curr_md);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Made new psymtab for module %s (%x to %x), sym %x to %x.\n",
+ mod_name_string, start_adr, end_adr, CURR_MODULE_ISYM, end_sym);
+ }
+#endif
+
+ /* Prepare for the next psymtab. */
+ global_syms = objfile->global_psymbols.next;
+ static_syms = objfile->static_psymbols.next;
+ xfree (class_entered);
+
+ curr_md++;
+ curr_fd++;
+ } /* psymtab for module */
+ } /* psymtab for non-bogus file or module */
+ } /* End of while loop over all files & modules */
+
+ /* There may be some routines after all files and modules -- these will get
+ inserted in a separate new module of their own */
+ if (VALID_CURR_PROC)
+ {
+ start_adr = CURR_PROC_START;
+ end_adr = qPD[pxdb_header_p->pd_entries - 1].adrEnd;
+ TELL_OBJFILE;
+ warning ("Found functions beyond end of all files and modules [0x%x].", curr_pd);
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Orphan functions at end, PD %d and beyond (%x to %x)\n",
+ curr_pd, start_adr, end_adr);
+ }
+#endif
+ pst = hpread_start_psymtab (objfile,
+ "orphans",
+ start_adr, /* Low text address */
+ (CURR_PROC_ISYM * sizeof (struct dntt_type_block)),
+ /* ldsymoff */
+ global_syms,
+ static_syms);
+
+ scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries,
+ start_adr, end_adr, pst, vt_bits, objfile);
+
+ pst = hpread_end_psymtab (pst,
+ NULL, /* psymtab_include_list */
+ 0, /* includes_used */
+ pxdb_header_p->globals * sizeof (struct dntt_type_block),
+ /* byte index in LNTT of end
+ = capping symbol offset
+ = LDSYMOFF of nextfile */
+ end_adr, /* text high */
+ NULL, /* dependency_list */
+ 0); /* dependencies_used */
+ }
+
+
+#ifdef NEVER_NEVER
+ /* Now build psts for non-module things (in the tail of
+ the LNTT, after the last END MODULE entry).
+
+ If null psts were kept on the chain, this would be
+ a solution. FIXME */
+ pst = hpread_start_psymtab (objfile,
+ "globals",
+ 0,
+ (pxdb_header_p->globals
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ hpread_end_psymtab (pst,
+ NULL, 0,
+ (max_LNTT_sym_index * sizeof (struct dntt_type_block)),
+ 0,
+ NULL, 0);
+#endif
+
+ clear_pst_syms ();
+
+ return 1;
+
+} /* End of hpread_quick_traverse. */
+\f
+
+/* Get appropriate header, based on pxdb type.
+ Return value: 1 if ok, 0 if not */
+int
+hpread_get_header (struct objfile *objfile, PXDB_header_ptr pxdb_header_p)
+{
+ asection *pinfo_section, *debug_section, *header_section;
+
+#ifdef DUMPING
+ /* Turn on for debugging information */
+ static int dumping = 0;
+#endif
+
+ header_section = bfd_get_section_by_name (objfile->obfd, "$HEADER$");
+ if (!header_section)
+ {
+ /* We don't have either PINFO or DEBUG sections. But
+ stuff like "libc.sl" has no debug info. There's no
+ need to warn the user of this, as it may be ok. The
+ caller will figure it out and issue any needed
+ messages. */
+#ifdef DUMPING
+ if (dumping)
+ printf ("==No debug info at all for %s.\n", objfile->name);
+#endif
+
+ return 0;
+ }
+
+ /* We would like either a $DEBUG$ or $PINFO$ section.
+ Once we know which, we can understand the header
+ data (which we have defined to suit the more common
+ $DEBUG$ case). */
+ debug_section = bfd_get_section_by_name (objfile->obfd, "$DEBUG$");
+ pinfo_section = bfd_get_section_by_name (objfile->obfd, "$PINFO$");
+ if (debug_section)
+ {
+ /* The expected case: normal pxdb header. */
+ bfd_get_section_contents (objfile->obfd, header_section,
+ pxdb_header_p, 0, sizeof (PXDB_header));
+
+ if (!pxdb_header_p->pxdbed)
+ {
+ /* This shouldn't happen if we check in "symfile.c". */
+ return 0;
+ } /* DEBUG section */
+ }
+
+ else if (pinfo_section)
+ {
+ /* The DOC case; we need to translate this into a
+ regular header. */
+ DOC_info_PXDB_header doc_header;
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("==OOps, PINFO, let's try to handle this, %s.\n", objfile->name);
+ }
+#endif
+
+ bfd_get_section_contents (objfile->obfd,
+ header_section,
+ &doc_header, 0,
+ sizeof (DOC_info_PXDB_header));
+
+ if (!doc_header.pxdbed)
+ {
+ /* This shouldn't happen if we check in "symfile.c". */
+ warning ("File \"%s\" not processed by pxdb!", objfile->name);
+ return 0;
+ }
+
+ /* Copy relevent fields to standard header passed in. */
+ pxdb_header_p->pd_entries = doc_header.pd_entries;
+ pxdb_header_p->fd_entries = doc_header.fd_entries;
+ pxdb_header_p->md_entries = doc_header.md_entries;
+ pxdb_header_p->pxdbed = doc_header.pxdbed;
+ pxdb_header_p->bighdr = doc_header.bighdr;
+ pxdb_header_p->sa_header = doc_header.sa_header;
+ pxdb_header_p->inlined = doc_header.inlined;
+ pxdb_header_p->globals = doc_header.globals;
+ pxdb_header_p->time = doc_header.time;
+ pxdb_header_p->pg_entries = doc_header.pg_entries;
+ pxdb_header_p->functions = doc_header.functions;
+ pxdb_header_p->files = doc_header.files;
+ pxdb_header_p->cd_entries = doc_header.cd_entries;
+ pxdb_header_p->aa_entries = doc_header.aa_entries;
+ pxdb_header_p->oi_entries = doc_header.oi_entries;
+ pxdb_header_p->version = doc_header.version;
+ } /* PINFO section */
+
+ else
+ {
+#ifdef DUMPING
+ if (dumping)
+ printf ("==No debug info at all for %s.\n", objfile->name);
+#endif
+
+ return 0;
+
+ }
+
+ return 1;
+} /* End of hpread_get_header */
+#endif /* QUICK_LOOK_UP */
+\f
+
+/* Initialization for reading native HP C debug symbols from OBJFILE.
+
+ Its 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 (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. */
+ DNTT_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)
+ / sizeof (struct dntt_type_block);
+
+ /* Read in data from the $LNTT$ subspace. Also keep track of the number
+ of LNTT symbols.
+
+ FIXME: this could be moved into the psymtab-to-symtab expansion
+ code, and save startup time. At the moment this data is
+ still used, though. We'd need a way to tell hp-symtab-read.c
+ whether or not to load the LNTT. */
+ 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)
+ / sizeof (struct dntt_type_block);
+
+ /* 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.
+
+ Note that the minimal table is produced by the linker, and has
+ only global routines in it; the psymtab is based on compiler-
+ generated debug information and has non-global
+ routines in it as well as files and class information.
+
+ We assume hpread_symfile_init has been called to initialize the
+ symbol reader's private data structures.
+
+ 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 (struct objfile *objfile, int mainline)
+{
+
+#ifdef DUMPING
+ /* Turn this on to get debugging output. */
+ static int dumping = 0;
+#endif
+
+ char *namestring;
+ int past_first_source_file = 0;
+ struct cleanup *old_chain;
+
+ int hp_symnum, symcount, i;
+ int scan_start = 0;
+
+ 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. */
+ free_pending_blocks ();
+ 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;
+
+#ifdef QUICK_LOOK_UP
+ {
+ /* Begin code for new-style loading of quick look-up tables. */
+
+ /* elz: this checks whether the file has beeen processed by pxdb.
+ If not we would like to try to read the psymbols in
+ anyway, but it turns out to be not so easy. So this could
+ actually be commented out, but I leave it in, just in case
+ we decide to add support for non-pxdb-ed stuff in the future. */
+ PXDB_header pxdb_header;
+ int found_modules_in_program;
+
+ if (hpread_get_header (objfile, &pxdb_header))
+ {
+ /* Build a minimal table. No types, no global variables,
+ no include files.... */
+#ifdef DUMPING
+ if (dumping)
+ printf ("\nNew method for %s\n", objfile->name);
+#endif
+
+ /* elz: quick_traverse returns true if it found
+ some modules in the main source file, other
+ than those in end.c
+ In C and C++, all the files have MODULES entries
+ in the LNTT, and the quick table traverse is all
+ based on finding these MODULES entries. Without
+ those it cannot work.
+ It happens that F77 programs don't have MODULES
+ so the quick traverse gets confused. F90 programs
+ have modules, and the quick method still works.
+ So, if modules (other than those in end.c) are
+ not found we give up on the quick table stuff,
+ and fall back on the slower method */
+ found_modules_in_program = hpread_quick_traverse (objfile,
+ GNTT (objfile),
+ VT (objfile),
+ &pxdb_header);
+
+ discard_cleanups (old_chain);
+
+ /* Set up to scan the global section of the LNTT.
+
+ This field is not always correct: if there are
+ no globals, it will point to the last record in
+ the regular LNTT, which is usually an END MODULE.
+
+ Since it might happen that there could be a file
+ with just one global record, there's no way to
+ tell other than by looking at the record, so that's
+ done below. */
+ if (found_modules_in_program)
+ scan_start = pxdb_header.globals;
+ }
+#ifdef DUMPING
+ else
+ {
+ if (dumping)
+ printf ("\nGoing on to old method for %s\n", objfile->name);
+ }
+#endif
+ }
+#endif /* QUICK_LOOK_UP */
+
+ /* Make two passes, one over the GNTT symbols, the other for the
+ LNTT symbols.
+
+ JB comment: above isn't true--they only make one pass, over
+ the LNTT. */
+ for (i = 0; i < 1; i++)
+ {
+ int within_function = 0;
+
+ if (i)
+ symcount = GNTT_SYMCOUNT (objfile);
+ else
+ symcount = LNTT_SYMCOUNT (objfile);
+
+
+ for (hp_symnum = scan_start; 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 DNTT_TYPE_SRCFILE:
+ {
+#ifdef QUICK_LOOK_UP
+ if (scan_start == hp_symnum
+ && symcount == hp_symnum + 1)
+ {
+ /* If there are NO globals in an executable,
+ PXDB's index to the globals will point to
+ the last record in the file, which
+ could be this record. (this happened for F77 libraries)
+ ignore it and be done! */
+ continue;
+ }
+#endif /* QUICK_LOOK_UP */
+
+ /* 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 (pst)
+ {
+ 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)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list,
+ includes_used,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ 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, symcount);
+ valu += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+ pst = hpread_start_psymtab (objfile,
+ namestring, valu,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ texthigh = valu;
+ have_name = 1;
+ continue;
+ }
+
+ case DNTT_TYPE_MODULE:
+ /* A source file. It's still unclear to me what the
+ real difference between a DNTT_TYPE_SRCFILE and DNTT_TYPE_MODULE
+ is supposed to be. */
+
+ /* First end the previous psymtab */
+ if (pst)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list, includes_used,
+ ((hp_symnum - 1)
+ * sizeof (struct dntt_type_block)),
+ texthigh,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ have_name = 0;
+ }
+
+ /* Now begin a new module and a new psymtab for it */
+ set_namestring (dn_bufp, &namestring, objfile);
+ valu = hpread_get_textlow (i, hp_symnum, objfile, symcount);
+ valu += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile,
+ namestring, valu,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ texthigh = valu;
+ have_name = 0;
+ }
+ continue;
+
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ /* The beginning of a function. DNTT_TYPE_ENTRY may also denote
+ a secondary entry point. */
+ valu = dn_bufp->dfunc.hiaddr + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT (objfile));
+ if (valu > texthigh)
+ texthigh = valu;
+ valu = dn_bufp->dfunc.lowaddr +
+ ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+ set_namestring (dn_bufp, &namestring, objfile);
+ if (dn_bufp->dfunc.global)
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols, valu,
+ 0, language_unknown, objfile);
+ else
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, valu,
+ 0, language_unknown, objfile);
+ within_function = 1;
+ continue;
+
+ case DNTT_TYPE_DOC_FUNCTION:
+ valu = dn_bufp->ddocfunc.hiaddr + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT (objfile));
+ if (valu > texthigh)
+ texthigh = valu;
+ valu = dn_bufp->ddocfunc.lowaddr +
+ ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+ set_namestring (dn_bufp, &namestring, objfile);
+ if (dn_bufp->ddocfunc.global)
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols, valu,
+ 0, language_unknown, objfile);
+ else
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, valu,
+ 0, language_unknown, objfile);
+ within_function = 1;
+ continue;
+
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ /* We don't check MODULE end here, because there can be
+ symbols beyond the module end which properly belong to the
+ current psymtab -- so we wait till the next MODULE start */
+
+
+#ifdef QUICK_LOOK_UP
+ if (scan_start == hp_symnum
+ && symcount == hp_symnum + 1)
+ {
+ /* If there are NO globals in an executable,
+ PXDB's index to the globals will point to
+ the last record in the file, which is
+ probably an END MODULE, i.e. this record.
+ ignore it and be done! */
+ continue;
+ }
+#endif /* QUICK_LOOK_UP */
+
+ /* Scope block begin/end. We only care about function
+ and file blocks right now. */
+
+ if ((dn_bufp->dend.endkind == DNTT_TYPE_FUNCTION) ||
+ (dn_bufp->dend.endkind == DNTT_TYPE_DOC_FUNCTION))
+ within_function = 0;
+ continue;
+
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_TYPEDEF:
+ case DNTT_TYPE_TAGDEF:
+ {
+ /* Variables, typedefs an the like. */
+ enum address_class storage;
+ namespace_enum namespace;
+
+ /* Don't add locals to the partial symbol table. */
+ if (within_function
+ && (dn_bufp->dblock.kind == DNTT_TYPE_SVAR
+ || dn_bufp->dblock.kind == DNTT_TYPE_DVAR))
+ continue;
+
+ /* TAGDEFs go into the structure namespace. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_TAGDEF)
+ namespace = STRUCT_NAMESPACE;
+ else
+ namespace = VAR_NAMESPACE;
+
+ /* What kind of "storage" does this use? */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_SVAR)
+ storage = LOC_STATIC;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR
+ && dn_bufp->ddvar.regvar)
+ storage = LOC_REGISTER;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR)
+ storage = LOC_LOCAL;
+ else
+ storage = LOC_UNDEF;
+
+ set_namestring (dn_bufp, &namestring, objfile);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile,
+ "globals", 0,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+
+ /* Compute address of the data symbol */
+ valu = dn_bufp->dsvar.location;
+ /* Relocate in case it's in a shared library */
+ if (storage == LOC_STATIC)
+ valu += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+
+ /* Luckily, dvar, svar, typedef, and tagdef all
+ have their "global" bit in the same place, so it works
+ (though it's bad programming practice) to reference
+ "dsvar.global" even though we may be looking at
+ any of the above four types. */
+ if (dn_bufp->dsvar.global)
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ namespace, storage,
+ &objfile->global_psymbols,
+ valu,
+ 0, language_unknown, objfile);
+ }
+ else
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ namespace, storage,
+ &objfile->static_psymbols,
+ valu,
+ 0, language_unknown, objfile);
+ }
+
+ /* For TAGDEF's, the above code added the tagname to the
+ struct namespace. This will cause tag "t" to be found
+ on a reference of the form "(struct t) x". But for
+ C++ classes, "t" will also be a typename, which we
+ want to find on a reference of the form "ptype t".
+ Therefore, we also add "t" to the var namespace.
+ Do the same for enum's due to the way aCC generates
+ debug info for these (see more extended comment
+ in hp-symtab-read.c).
+ We do the same for templates, so that "ptype t"
+ where "t" is a template also works. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_TAGDEF &&
+ dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile))
+ {
+ int global = dn_bufp->dtag.global;
+ /* Look ahead to see if it's a C++ class */
+ dn_bufp = hpread_get_lntt (dn_bufp->dtype.type.dnttp.index, objfile);
+ if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS ||
+ dn_bufp->dblock.kind == DNTT_TYPE_ENUM ||
+ dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE)
+ {
+ if (global)
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, storage,
+ &objfile->global_psymbols,
+ dn_bufp->dsvar.location,
+ 0, language_unknown, objfile);
+ }
+ else
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, storage,
+ &objfile->static_psymbols,
+ dn_bufp->dsvar.location,
+ 0, language_unknown, objfile);
+ }
+ }
+ }
+ }
+ continue;
+
+ case DNTT_TYPE_MEMENUM:
+ case DNTT_TYPE_CONST:
+ /* Constants and members of enumerated types. */
+ set_namestring (dn_bufp, &namestring, objfile);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile,
+ "globals", 0,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+ if (dn_bufp->dconst.global)
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->global_psymbols, 0,
+ 0, language_unknown, objfile);
+ else
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ 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 * sizeof (struct dntt_type_block),
+ 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 (struct objfile *objfile)
+{
+ if (objfile->sym_private != NULL)
+ {
+ xmfree (objfile->md, objfile->sym_private);
+ }
+}
+\f
+
+/* The remaining functions are all for internal use only. */
+
+/* Various small functions to get entries in the debug symbol sections. */
+
+union dnttentry *
+hpread_get_lntt (int index, struct objfile *objfile)
+{
+ return (union dnttentry *)
+ &(LNTT (objfile)[(index * sizeof (struct dntt_type_block))]);
+}
+
+static union dnttentry *
+hpread_get_gntt (int index, struct objfile *objfile)
+{
+ return (union dnttentry *)
+ &(GNTT (objfile)[(index * sizeof (struct dntt_type_block))]);
+}
+
+union sltentry *
+hpread_get_slt (int index, struct objfile *objfile)
+{
+ return (union sltentry *) &(SLT (objfile)[index * sizeof (union sltentry)]);
+}
+
+/* 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 DNTT_TYPE_MODULE or DNTT_TYPE_SRCFILE symbol we
+ must infer it from the existence of DNTT_TYPE_FUNCTION symbols. */
+
+static unsigned long
+hpread_get_textlow (int global, int index, struct objfile *objfile,
+ int symcount)
+{
+ union dnttentry *dn_bufp;
+ struct minimal_symbol *msymbol;
+
+ /* Look for a DNTT_TYPE_FUNCTION symbol. */
+ if (index < symcount) /* symcount is the number of symbols in */
+ { /* the dbinfo, LNTT table */
+ do
+ {
+ if (global)
+ dn_bufp = hpread_get_gntt (index++, objfile);
+ else
+ dn_bufp = hpread_get_lntt (index++, objfile);
+ }
+ while (dn_bufp->dblock.kind != DNTT_TYPE_FUNCTION
+ && dn_bufp->dblock.kind != DNTT_TYPE_DOC_FUNCTION
+ && dn_bufp->dblock.kind != DNTT_TYPE_END
+ && index < symcount);
+ }
+
+ /* Avoid going past a DNTT_TYPE_END when looking for a DNTT_TYPE_FUNCTION. This
+ might happen when a sourcefile has no functions. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_END)
+ return 0;
+
+ /* Avoid going past the end of the LNTT file */
+ if (index == symcount)
+ return 0;
+
+ /* The minimal symbols are typically more accurate for some reason. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTION)
+ msymbol = lookup_minimal_symbol (dn_bufp->dfunc.name + VT (objfile), NULL,
+ objfile);
+ else /* must be a DNTT_TYPE_DOC_FUNCTION */
+ msymbol = lookup_minimal_symbol (dn_bufp->ddocfunc.name + VT (objfile), NULL,
+ objfile);
+
+ if (msymbol)
+ return SYMBOL_VALUE_ADDRESS (msymbol);
+ else
+ return dn_bufp->dfunc.lowaddr;
+}
+
+/* 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 (struct objfile *objfile, char *filename,
+ CORE_ADDR textlow, int ldsymoff,
+ struct partial_symbol **global_syms,
+ struct partial_symbol **static_syms)
+{
+ int offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+ extern void hpread_psymtab_to_symtab ();
+ struct partial_symtab *result =
+ start_psymtab_common (objfile, objfile->section_offsets,
+ filename, textlow, global_syms, static_syms);
+
+ result->textlow += offset;
+ 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;
+}
+\f
+
+/* Close off the current usage of PST.
+ Returns PST or NULL if the partial symtab was empty and thrown away.
+
+ capping_symbol_offset --Byte index in LNTT or GNTT of the
+ last symbol processed during the build
+ of the previous pst.
+
+ FIXME: List variables and peculiarities of same. */
+
+static struct partial_symtab *
+hpread_end_psymtab (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;
+ int offset = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
+
+#ifdef DUMPING
+ /* Turn on to see what kind of a psymtab we've built. */
+ static int dumping = 0;
+#endif
+
+ if (capping_symbol_offset != -1)
+ LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst);
+ else
+ LDSYMLEN (pst) = 0;
+ pst->texthigh = capping_text + offset;
+
+ 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);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("\nPst %s, LDSYMOFF %x (%x), LDSYMLEN %x (%x), globals %d, statics %d\n",
+ pst->filename,
+ LDSYMOFF (pst),
+ LDSYMOFF (pst) / sizeof (struct dntt_type_block),
+ LDSYMLEN (pst),
+ LDSYMLEN (pst) / sizeof (struct dntt_type_block),
+ pst->n_global_syms, pst->n_static_syms);
+ }
+#endif
+
+ 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.
+ It's also wrong if we're using the quick look-up tables, as
+ we can get empty psymtabs from modules with no routines in
+ them. */
+
+ discard_psymtab (pst);
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *) NULL;
+
+ }
+ return pst;
+}
+
+\f
+/* Get the nesting depth for the source line identified by INDEX. */
+
+static unsigned long
+hpread_get_scope_start (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 (sltpointer index, struct objfile *objfile)
+{
+ union sltentry *sl_bufp;
+
+ sl_bufp = hpread_get_slt (index, objfile);
+ return sl_bufp->snorm.line;
+}
+
+/* Find the code address associated with a given sltpointer */
+
+static CORE_ADDR
+hpread_get_location (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_NORMAL_OFFSET) &&
+ (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++)
+ sl_bufp = hpread_get_slt (index - i, objfile);
+ if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET)
+ return sl_bufp->snormoff.address;
+ else
+ 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_NORMAL_OFFSET) &&
+ (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++)
+ sl_bufp = hpread_get_slt (index + i, objfile);
+ if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET)
+ return sl_bufp->snormoff.address;
+ else
+ return sl_bufp->snorm.address;
+}
+\f
+
+/* Return 1 if an HP debug symbol of type KIND has a name associated with
+ * it, else return 0. (This function is not currently used, but I'll
+ * leave it here in case it proves useful later on. - RT).
+ */
+
+int
+hpread_has_name (enum dntt_entry_type kind)
+{
+ switch (kind)
+ {
+ case DNTT_TYPE_SRCFILE:
+ case DNTT_TYPE_MODULE:
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_DOC_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ case DNTT_TYPE_IMPORT:
+ case DNTT_TYPE_LABEL:
+ case DNTT_TYPE_FPARAM:
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_CONST:
+ case DNTT_TYPE_TYPEDEF:
+ case DNTT_TYPE_TAGDEF:
+ case DNTT_TYPE_MEMENUM:
+ case DNTT_TYPE_FIELD:
+ case DNTT_TYPE_SA:
+ case DNTT_TYPE_BLOCKDATA:
+ case DNTT_TYPE_MEMFUNC:
+ case DNTT_TYPE_DOC_MEMFUNC:
+ return 1;
+
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ case DNTT_TYPE_POINTER:
+ case DNTT_TYPE_ENUM:
+ case DNTT_TYPE_SET:
+ case DNTT_TYPE_ARRAY:
+ case DNTT_TYPE_STRUCT:
+ case DNTT_TYPE_UNION:
+ case DNTT_TYPE_VARIANT:
+ case DNTT_TYPE_FILE:
+ case DNTT_TYPE_FUNCTYPE:
+ case DNTT_TYPE_SUBRANGE:
+ case DNTT_TYPE_WITH:
+ case DNTT_TYPE_COMMON:
+ case DNTT_TYPE_COBSTRUCT:
+ case DNTT_TYPE_XREF:
+ case DNTT_TYPE_MACRO:
+ case DNTT_TYPE_CLASS_SCOPE:
+ case DNTT_TYPE_REFERENCE:
+ case DNTT_TYPE_PTRMEM:
+ case DNTT_TYPE_PTRMEMFUNC:
+ case DNTT_TYPE_CLASS:
+ case DNTT_TYPE_GENFIELD:
+ case DNTT_TYPE_VFUNC:
+ case DNTT_TYPE_MEMACCESS:
+ case DNTT_TYPE_INHERITANCE:
+ case DNTT_TYPE_FRIEND_CLASS:
+ case DNTT_TYPE_FRIEND_FUNC:
+ case DNTT_TYPE_MODIFIER:
+ case DNTT_TYPE_OBJECT_ID:
+ case DNTT_TYPE_TEMPLATE:
+ case DNTT_TYPE_TEMPLATE_ARG:
+ case DNTT_TYPE_FUNC_TEMPLATE:
+ case DNTT_TYPE_LINK:
+ /* DNTT_TYPE_DYN_ARRAY_DESC ? */
+ /* DNTT_TYPE_DESC_SUBRANGE ? */
+ /* DNTT_TYPE_BEGIN_EXT ? */
+ /* DNTT_TYPE_INLN ? */
+ /* DNTT_TYPE_INLN_LIST ? */
+ /* DNTT_TYPE_ALIAS ? */
+ default:
+ return 0;
+ }
+}
+
+/* Do the dirty work of reading in the full symbol from a partial symbol
+ table. */
+
+static void
+hpread_psymtab_to_symtab_1 (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_unfiltered (gdb_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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_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. */
+
+void
+hpread_psymtab_to_symtab (struct partial_symtab *pst)
+{
+ /* Get out quick if given junk. */
+ if (!pst)
+ return;
+
+ /* Sanity check. */
+ if (pst->readin)
+ {
+ fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in."
+ " Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ /* elz: setting the flag to indicate that the code of the target
+ was compiled using an HP compiler (aCC, cc)
+ the processing_acc_compilation variable is declared in the
+ file buildsym.h, the HP_COMPILED_TARGET is defined to be equal
+ to 3 in the file tm_hppa.h */
+
+ processing_gcc_compilation = 0;
+
+ 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);
+ gdb_flush (gdb_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 (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 at_module_boundary = 0;
+ /* 1 => at end, -1 => at beginning */
+
+ int sym_index = sym_offset / sizeof (struct dntt_type_block);
+
+ current_objfile = objfile;
+ subfile_stack = 0;
+
+ last_source_file = 0;
+
+ /* Demangling style -- if EDG style already set, don't change it,
+ as HP style causes some problems with the KAI EDG compiler */
+ if (current_demangling_style != edg_demangling)
+ {
+ /* Otherwise, ensure that we are using HP style demangling */
+ set_demangling_style (HP_DEMANGLING_STYLE_STRING);
+ }
+
+ dn_bufp = hpread_get_lntt (sym_index, objfile);
+ if (!((dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_SRCFILE) ||
+ (dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_MODULE)))
+ {
+ start_symtab ("globals", NULL, 0);
+ record_debugformat ("HP");
+ }
+
+ /* The psymtab builder (hp-psymtab-read.c) is the one that
+ * determined the "sym_size" argument (i.e. how many DNTT symbols
+ * are in this symtab), which we use to compute "max_symnum"
+ * (point in DNTT to which we read).
+ *
+ * Perhaps this should be changed so that
+ * process_one_debug_symbol() "knows" when
+ * to stop reading (based on reading from the MODULE to the matching
+ * END), and take out this reliance on a #-syms being passed in...
+ * (I'm worried about the reliability of this number). But I'll
+ * leave it as-is, for now. - RT
+ *
+ * The change above has been made. I've left the "for" loop control
+ * in to prepare for backing this out again. -JB
+ */
+ max_symnum = sym_size / sizeof (struct dntt_type_block);
+ /* No reason to multiply on pst side and divide on sym side... FIXME */
+
+ /* 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,
+ &at_module_boundary
+ );
+
+ /* OLD COMMENTS: This routine is only called for psts. All psts
+ * correspond to MODULES. If we ever do lazy-reading of globals
+ * from the LNTT, then there will be a pst which ends when the
+ * LNTT ends, and not at an END MODULE entry. Then we'll have
+ * to re-visit this break.
+
+ if( at_end_of_module )
+ break;
+
+ */
+
+ /* We no longer break out of the loop when we reach the end of a
+ module. The reason is that with CTTI, the compiler can generate
+ function symbols (for template function instantiations) which are not
+ in any module; typically they show up beyond a module's end, and
+ before the next module's start. We include them in the current
+ module. However, we still don't trust the MAX_SYMNUM value from
+ the psymtab, so we break out if we enter a new module. */
+
+ if (at_module_boundary == -1)
+ break;
+ }
+
+ current_objfile = NULL;
+ hp_som_som_object_present = 1; /* Indicate we've processed an HP SOM SOM file */
+
+ return end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT (objfile));
+}
+\f
+
+
+
+/* Convert basic types from HP debug format into GDB internal format. */
+
+static int
+hpread_type_translate (dnttpointer typep)
+{
+ if (!typep.dntti.immediate)
+ {
+ error ("error in hpread_type_translate\n.");
+ return FT_VOID;
+ }
+
+ switch (typep.dntti.type)
+ {
+ case HP_TYPE_BOOLEAN:
+ case HP_TYPE_BOOLEAN_S300_COMPAT:
+ case HP_TYPE_BOOLEAN_VAX_COMPAT:
+ return FT_BOOLEAN;
+ case HP_TYPE_CHAR: /* C signed char, C++ plain char */
+
+ case HP_TYPE_WIDE_CHAR:
+ return FT_CHAR;
+ case HP_TYPE_INT:
+ if (typep.dntti.bitlength <= 8)
+ return FT_SIGNED_CHAR; /* C++ signed char */
+ if (typep.dntti.bitlength <= 16)
+ return FT_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_INTEGER;
+ return FT_LONG_LONG;
+ case HP_TYPE_LONG:
+ if (typep.dntti.bitlength <= 8)
+ return FT_SIGNED_CHAR; /* C++ signed char. */
+ return FT_LONG;
+ case HP_TYPE_UNSIGNED_LONG:
+ if (typep.dntti.bitlength <= 8)
+ return FT_UNSIGNED_CHAR; /* C/C++ unsigned char */
+ if (typep.dntti.bitlength <= 16)
+ return FT_UNSIGNED_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_UNSIGNED_LONG;
+ return FT_UNSIGNED_LONG_LONG;
+ case HP_TYPE_UNSIGNED_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 HP_TYPE_REAL:
+ case HP_TYPE_REAL_3000:
+ case HP_TYPE_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 HP_TYPE_COMPLEX:
+ case HP_TYPE_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 HP_TYPE_VOID:
+ return FT_VOID;
+ case HP_TYPE_STRING200:
+ case HP_TYPE_LONGSTRING200:
+ case HP_TYPE_FTN_STRING_SPEC:
+ case HP_TYPE_MOD_STRING_SPEC:
+ case HP_TYPE_MOD_STRING_3000:
+ case HP_TYPE_FTN_STRING_S300_COMPAT:
+ case HP_TYPE_FTN_STRING_VAX_COMPAT:
+ return FT_STRING;
+ case HP_TYPE_TEMPLATE_ARG:
+ return FT_TEMPLATE_ARG;
+ case HP_TYPE_TEXT:
+ case HP_TYPE_FLABEL:
+ case HP_TYPE_PACKED_DECIMAL:
+ case HP_TYPE_ANYPOINTER:
+ case HP_TYPE_GLOBAL_ANYPOINTER:
+ case HP_TYPE_LOCAL_ANYPOINTER:
+ default:
+ warning ("hpread_type_translate: unhandled type code.\n");
+ return FT_VOID;
+ }
+}
+
+/* Given a position in the DNTT, return a pointer to the
+ * already-built "struct type" (if any), for the type defined
+ * at that position.
+ */
+
+static struct type **
+hpread_lookup_type (dnttpointer hp_type, struct objfile *objfile)
+{
+ unsigned old_len;
+ int index = hp_type.dnttp.index;
+ int size_changed = 0;
+
+ /* The immediate flag indicates this doesn't actually point to
+ * a type DNTT.
+ */
+ if (hp_type.dntti.immediate)
+ return NULL;
+
+ /* For each objfile, we maintain a "type vector".
+ * This an array of "struct type *"'s with one pointer per DNTT index.
+ * Given a DNTT index, we look in this array to see if we have
+ * already processed this DNTT and if it is a type definition.
+ * If so, then we can locate a pointer to the already-built
+ * "struct type", and not build it again.
+ *
+ * The need for this arises because our DNTT-walking code wanders
+ * around. In particular, it will encounter the same type multiple
+ * times (once for each object of that type). We don't want to
+ * built multiple "struct type"'s for the same thing.
+ *
+ * Having said this, I should point out that this type-vector is
+ * an expensive way to keep track of this. If most DNTT entries are
+ * 3 words, the type-vector will be 1/3 the size of the DNTT itself.
+ * Alternative solutions:
+ * - Keep a compressed or hashed table. Less memory, but more expensive
+ * to search and update.
+ * - (Suggested by JB): Overwrite the DNTT entry itself
+ * with the info. Create a new type code "ALREADY_BUILT", and modify
+ * the DNTT to have that type code and point to the already-built entry.
+ * -RT
+ */
+
+ if (index < LNTT_SYMCOUNT (objfile))
+ {
+ if (index >= DNTT_TYPE_VECTOR_LENGTH (objfile))
+ {
+ old_len = DNTT_TYPE_VECTOR_LENGTH (objfile);
+
+ /* See if we need to allocate a type-vector. */
+ if (old_len == 0)
+ {
+ DNTT_TYPE_VECTOR_LENGTH (objfile) = LNTT_SYMCOUNT (objfile) + GNTT_SYMCOUNT (objfile);
+ DNTT_TYPE_VECTOR (objfile) = (struct type **)
+ xmmalloc (objfile->md, DNTT_TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *));
+ memset (&DNTT_TYPE_VECTOR (objfile)[old_len], 0,
+ (DNTT_TYPE_VECTOR_LENGTH (objfile) - old_len) *
+ sizeof (struct type *));
+ }
+
+ /* See if we need to resize type-vector. With my change to
+ * initially allocate a correct-size type-vector, this code
+ * should no longer trigger.
+ */
+ while (index >= DNTT_TYPE_VECTOR_LENGTH (objfile))
+ {
+ DNTT_TYPE_VECTOR_LENGTH (objfile) *= 2;
+ size_changed = 1;
+ }
+ if (size_changed)
+ {
+ DNTT_TYPE_VECTOR (objfile) = (struct type **)
+ xmrealloc (objfile->md,
+ (char *) DNTT_TYPE_VECTOR (objfile),
+ (DNTT_TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *)));
+
+ memset (&DNTT_TYPE_VECTOR (objfile)[old_len], 0,
+ (DNTT_TYPE_VECTOR_LENGTH (objfile) - old_len) *
+ sizeof (struct type *));
+ }
+
+ }
+ return &DNTT_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 (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);
+
+ /* A hack - if we really are a C++ class symbol, then this default
+ * will get overriden later on.
+ */
+ 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 (dnttpointer hp_type, union dnttentry *dn_bufp,
+ struct objfile *objfile)
+{
+ struct type *type;
+ struct pending **symlist, *osyms, *syms;
+ struct pending *local_list = NULL;
+ int o_nsyms, nsyms = 0;
+ dnttpointer mem;
+ union dnttentry *memp;
+ char *name;
+ long n;
+ struct symbol *sym;
+
+ /* Allocate a GDB type. If we've already read in this enum type,
+ * it'll return the already built GDB type, so stop here.
+ * (Note: I added this check, to conform with what's done for
+ * struct, union, class.
+ * I assume this is OK. - RT)
+ */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_ENUM)
+ return type;
+
+ /* HP C supports "sized enums", where a specifier such as "short" or
+ "char" can be used to get enums of different sizes. So don't assume
+ an enum is always 4 bytes long. pai/1997-08-21 */
+ TYPE_LENGTH (type) = dn_bufp->denum.bitlength / 8;
+
+ 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.
+ * The list of "mem" SOM records we are walking should all be
+ * SOM type DNTT_TYPE_MEMENUM (not checked).
+ */
+ mem = dn_bufp->denum.firstmem;
+ while (mem.word && 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) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+ 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.