New file.
authorJohn Gilmore <gnu@cygnus>
Tue, 12 Nov 1991 15:24:56 +0000 (15:24 +0000)
committerJohn Gilmore <gnu@cygnus>
Tue, 12 Nov 1991 15:24:56 +0000 (15:24 +0000)
gdb/xcoffread.c [new file with mode: 0644]

diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
new file mode 100644 (file)
index 0000000..d3d07ca
--- /dev/null
@@ -0,0 +1,1506 @@
+/* Read AIXcoff symbol tables and convert to internal format, for GDB.
+   Copyright (C) 1986-1991 Free Software Foundation, Inc.
+   Derived from coffread.c, dbxread.c, and a lot of hacking.
+   Contributed by IBM Corporation.
+
+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.  */
+
+#include "defs.h"
+#include "bfd.h"
+#include "param.h"
+
+#include <stdio.h>
+
+/* AIX COFF names have a preceeding dot `.' */
+#define NAMES_HAVE_DOT 1
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include "obstack.h"
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include "symtab.h"
+#include "symfile.h"
+#include "buildsym.h"
+
+#include "internalcoff.h"      /* FIXME, internal data from BFD */
+#include "libcoff.h"           /* FIXME, internal data from BFD */
+#include "coff-rs6000.h"       /* FIXME, raw file-format guts of xcoff */
+
+extern char *index();
+
+static void enter_line_range ();
+static struct symbol *process_xcoff_symbol ();
+static int read_symbol_nvalue ();
+static int read_symbol_lineno ();
+
+
+/* Simplified internal version of coff symbol table information */
+
+struct coff_symbol {
+  char *c_name;
+  int c_symnum;                /* symbol number of this entry */
+  int c_nsyms;         /* 0 if syment only, 1 if syment + auxent */
+  long c_value;
+  int c_sclass;
+  int c_secnum;
+  unsigned int c_type;
+};
+
+/* The COFF line table, in raw form.  */
+static char *linetab = NULL;           /* Its actual contents */
+static long linetab_offset;            /* Its offset in the file */
+static unsigned long linetab_size;     /* Its size */
+
+/* last function's saved coff symbol `cs' */
+
+static struct coff_symbol fcn_cs_saved;
+
+static bfd *symfile_bfd;
+
+/* Core address of start and end of text of current source file.
+   This is calculated from the first function seen after a C_FILE
+   symbol. */
+
+static CORE_ADDR cur_src_start_addr;
+static CORE_ADDR cur_src_end_addr;
+
+/* Core address of the end of the first object file.  */
+
+static CORE_ADDR first_object_file_end;
+
+/* pointer to the string table */
+static char *strtbl;
+
+/* length of the string table */
+static int  strtbl_len;
+
+/* pointer to debug section */
+static char *debugsec;
+
+/* pointer to the a.out symbol table */
+static char *symtbl;
+
+/* initial symbol-table-debug-string vector length */
+
+#define        INITIAL_STABVECTOR_LENGTH       40
+
+struct pending_stabs *global_stabs;
+struct pending_stabs *file_stabs;
+
+/* Nonzero if within a function (so symbols should be local,
+   if nothing says specifically).  */
+
+int within_function;
+
+/* Local variables that hold the shift and mask values for the
+   COFF file that we are currently reading.  These come back to us
+   from BFD, and are referenced by their macro names, as well as
+   internally to the BTYPE, ISPTR, ISFCN, ISARY, ISTAG, and DECREF
+   macros from ../internalcoff.h .  */
+
+static unsigned        local_n_btshft;
+static unsigned        local_n_tmask;
+
+#undef N_BTSHFT
+#define        N_BTSHFT        local_n_btshft
+#undef N_TMASK
+#define        N_TMASK         local_n_tmask
+/* Local variables that hold the sizes in the file of various COFF structures.
+   (We only need to know this to read them from the file -- BFD will then
+   translate the data in them, into `internal_xxx' structs in the right
+   byte order, alignment, etc.)  */
+
+static unsigned        local_symesz;
+
+/* coff_symfile_init()
+   is the coff-specific initialization routine for reading symbols.
+   It is passed a struct sym_fns which contains, among other things,
+   the BFD for the file whose symbols are being read, and a slot for
+   a pointer to "private data" which we fill with cookies and other
+   treats for coff_symfile_read().
+   We will only be called if this is a COFF or COFF-like file.
+   BFD handles figuring out the format of the file, and code in symtab.c
+   uses BFD's determination to vector to us.
+   The ultimate result is a new symtab (or, FIXME, eventually a psymtab).  */
+
+struct coff_symfile_info {
+  file_ptr min_lineno_offset;          /* Where in file lowest line#s are */
+  file_ptr max_lineno_offset;          /* 1+last byte of line#s in file */
+};
+
+
+/* Call sort_syms to sort alphabetically
+   the symbols of each block of each symtab.  */
+
+static int
+compare_symbols (s1, s2)
+struct symbol **s1, **s2;
+{
+  /* Names that are less should come first.  */
+  register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2));
+  if (namediff != 0) 
+    return namediff;
+
+  /* For symbols of the same name, registers should come first.  */
+  return ((SYMBOL_CLASS (*s2) == LOC_REGISTER)
+      - (SYMBOL_CLASS (*s1) == LOC_REGISTER));
+}
+
+
+/* Sort a vector of symbols by their value. */
+
+static void
+sort_syms ()
+{
+  register struct symtab *s;
+  register int i, nbl;
+  register struct blockvector *bv;
+  register struct block *b;
+
+  for (s = symtab_list; s; s = s->next)
+  {
+    bv = BLOCKVECTOR (s);
+    nbl = BLOCKVECTOR_NBLOCKS (bv);
+    for (i = 0; i < nbl; i++)
+    {
+      b = BLOCKVECTOR_BLOCK (bv, i);
+      if (BLOCK_SHOULD_SORT (b))
+       qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+           sizeof (struct symbol *), compare_symbols);
+    }
+  }
+}
+
+
+/* add a given stab string into given stab vector. */
+
+static void
+add_stab_to_list (stabname, stabvector)
+char *stabname;
+struct pending_stabs **stabvector;
+{
+  if ( *stabvector == NULL) {
+    *stabvector = (struct pending_stabs *)
+       xmalloc (sizeof (struct pending_stabs) + 
+                       INITIAL_STABVECTOR_LENGTH * sizeof (char*));
+    (*stabvector)->count = 0;
+    (*stabvector)->length = INITIAL_STABVECTOR_LENGTH;
+  }
+  else if ((*stabvector)->count >= (*stabvector)->length) {
+    (*stabvector)->length += INITIAL_STABVECTOR_LENGTH;
+    *stabvector = (struct pending_stabs *)
+       xrealloc (*stabvector, sizeof (struct pending_stabs) + 
+       (*stabvector)->length * sizeof (char*));
+  }
+  (*stabvector)->stab [(*stabvector)->count++] = stabname;
+}
+
+
+/* for all the stabs in a given stab vector, build appropriate types 
+   and fix their symbols in given symbol vector. */
+
+void
+patch_block_stabs (symbols, stabs)
+struct pending *symbols;
+struct pending_stabs *stabs;
+{
+  int ii;
+
+  if (!stabs)
+    return;
+
+  /* for all the stab entries, find their corresponding symbols and 
+     patch their types! */
+
+  for (ii=0; ii < stabs->count; ++ii) {
+    char *name = stabs->stab[ii];
+    char *pp = (char*) index (name, ':');
+    struct symbol *sym = find_symbol_in_list (symbols, name, pp-name);
+    if (!sym) {
+      printf ("ERROR! stab symbol not found!\n");      /* FIXME */
+    }
+    else {
+      pp += 2;
+
+      if (*(pp-1) == 'F' || *(pp-1) == 'f')
+       SYMBOL_TYPE (sym) = lookup_function_type (read_type (&pp));
+      else
+       SYMBOL_TYPE (sym) = read_type (&pp);
+    }
+  }
+}
+
+/* Enter a given range of lines into the line vector.
+   can be called in the following two ways:
+     enter_line_range (subfile, beginoffset, endoffset, 0, firstLine)  or
+     enter_line_range (subfile, beginoffset, 0, endaddr, firstLine) */
+
+static void
+enter_line_range (subfile, beginoffset, endoffset, endaddr, firstLine)
+  struct subfile *subfile;             /* which sub-file to put line#s in */
+  unsigned   beginoffset, endoffset;   /* offsets to line table */
+  CORE_ADDR  endaddr;
+  unsigned   *firstLine;
+{
+  char         *pp, *limit;
+  CORE_ADDR    addr;
+  struct internal_lineno lptr;
+  unsigned local_linesz = coff_data (symfile_bfd)->local_linesz;
+
+  pp = &linetab [beginoffset - linetab_offset];
+  limit = endoffset ? &linetab [endoffset - linetab_offset]
+                     : &linetab [linetab_size -1];
+
+  while (pp <= limit) {
+
+    /* Swap and align this lineno entry into lptr.  */
+    bfd_coff_swap_lineno_in (symfile_bfd, pp, &lptr);
+
+    /* find the address this line represents */
+    addr = lptr.l_lnno ? 
+      lptr.l_addr.l_paddr : read_symbol_nvalue (symtbl, lptr.l_addr.l_symndx);
+
+    if (endaddr && addr >= endaddr)
+      return;
+
+    if (lptr.l_lnno == 0) {
+      *firstLine = read_symbol_lineno (symtbl, lptr.l_addr.l_symndx);
+      --(*firstLine);
+    }
+    else
+      record_line (subfile, *firstLine + lptr.l_lnno, addr);
+
+    pp += local_linesz;
+  }
+}
+
+
+/* Save the vital information for use when closing off the current file.
+   NAME is the file name the symbols came from, START_ADDR is the first
+   text address for the file, and SIZE is the number of bytes of text.  */
+
+#define complete_symtab(name, start_addr) {    \
+  last_source_file = savestring (name, strlen (name)); \
+  cur_src_start_addr = start_addr;                     \
+}
+
+
+/* Refill the symbol table input buffer
+   and set the variables that control fetching entries from it.
+   Reports an error if no data available.
+   This function can read past the end of the symbol table
+   (into the string table) but this does no harm.  */
+
+/* Reading symbol table has to be fast! Keep the followings as macros, rather
+   than functions. */
+
+#define        RECORD_MISC_FUNCTION(NAME, ADDR, TYPE, ALLOCED) \
+{                                              \
+  char *namestr;                               \
+  if (ALLOCED)                                         \
+    namestr = (NAME) + 1;                      \
+  else {                                       \
+    namestr = obstack_copy0 (symbol_obstack, (NAME) + 1, strlen ((NAME)+1)); \
+    (ALLOCED) = 1;                                             \
+  }                                                            \
+  prim_record_misc_function (namestr, (ADDR), (TYPE));         \
+  last_recorded_fun = (ADDR);                                  \
+}
+
+
+
+/* aixcoff has static blocks marked in `.bs', `.es' pairs. They cannot be
+   nested. At any given time, a symbol can only be in one static block.
+   This is the base address of current static block, zero if non exists. */
+   
+static int static_block_base = 0;
+
+/* true if space for symbol name has been allocated. */
+
+static int symname_alloced = 0;
+
+/* read the whole symbol table of a given bfd. */
+
+void
+read_xcoff_symtab (objfile, nsyms)
+     struct objfile *objfile;  /* Object file we're reading from */
+     int nsyms;                        /* # of symbols */
+{
+  bfd *abfd = objfile->obfd;
+  /* char *symtbl; */          /* Raw symbol table base */
+  char *raw_symbol;            /* Pointer into raw seething symbol table */
+  char *raw_auxptr;            /* Pointer to first raw aux entry for sym */
+  struct internal_syment symbol[1];
+  union internal_auxent main_aux[1];
+  struct coff_symbol cs[1];
+  CORE_ADDR file_start_addr = 0;
+  CORE_ADDR file_end_addr = 0;
+
+  int next_file_symnum = -1;
+  int just_started = 1;
+  int depth = 0;
+  int val;
+  int fcn_first_line;
+  int fcn_last_line;
+  int fcn_start_addr;
+  long fcn_line_offset;
+  size_t size;
+
+  /* fcn_cs_saved is global because process_xcoff_symbol needs it. */
+  union internal_auxent fcn_aux_saved;
+  struct context_stack *new;
+
+  char *filestring = " _start_ ";      /* Name of the current file. */
+  char *last_seen_csect;
+  int last_recorded_fun = 0;           /* last recorded fun. value */
+
+  /* Get the appropriate COFF "constants" related to the file we're handling. */
+  N_TMASK = coff_data (abfd)->local_n_tmask;
+  N_BTSHFT = coff_data (abfd)->local_n_btshft;
+  local_symesz = coff_data (abfd)->local_symesz;
+
+  last_source_file = 0;
+  last_seen_csect = 0;
+  last_recorded_fun = 0;
+
+  start_symtab (filestring, (char *)NULL, file_start_addr);
+  symnum = 0;
+  first_object_file_end = 0;
+
+  /* Allocate space for the entire symbol table at once, and read it
+     all in.  The bfd is already positioned at the beginning of
+     the symbol table.  */
+
+  size = coff_data (abfd)->local_symesz * nsyms;
+  symtbl = xmalloc (size);
+
+  val = bfd_read (symtbl, size, 1, abfd);
+  if (val != size)
+    perror_with_name ("reading symbol table");
+
+  raw_symbol = symtbl;
+
+  while (symnum < nsyms) {
+
+    QUIT;                      /* make this command interruptable.  */
+
+    /* READ_ONE_SYMBOL (symbol, cs, symname_alloced); */
+    /* read one symbol into `cs' structure. After processing the whole symbol
+       table, only string table will be kept in memory, symbol table and debug
+       section of aixcoff will be freed. Thus we can mark symbols with names
+       in string table as `alloced'. */
+    {
+      int ii;
+
+      /* Swap and align the symbol into a reasonable C structure.  */
+      bfd_coff_swap_sym_in (abfd, raw_symbol, symbol);
+
+      cs->c_symnum = symnum;
+      cs->c_nsyms = symbol->n_numaux;
+      if (symbol->n_zeroes) {
+       symname_alloced = 0;
+       /* We must use the original, unswapped, name here so the name field
+          pointed to by cs->c_name will persist throughout xcoffread.  If
+          we use the new field, it gets overwritten for each symbol.  */
+       cs->c_name = ((struct external_syment *)raw_symbol)->e.e_name;
+      } else if (symbol->n_sclass & 0x80) {
+       cs->c_name = debugsec + symbol->n_offset;
+       symname_alloced = 0;
+      } else { /* in string table */
+       cs->c_name = strtbl + (int)symbol->n_offset;
+       symname_alloced = 1;
+      }
+      cs->c_value = symbol->n_value;
+      cs->c_sclass = symbol->n_sclass & 0xff;
+      cs->c_secnum = symbol->n_scnum;
+      cs->c_type = (unsigned)symbol->n_type;
+
+      raw_symbol += coff_data (abfd)->local_symesz;
+      ++symnum;
+
+      raw_auxptr = raw_symbol;         /* Save addr of first aux entry */
+
+      /* Skip all the auxents associated with this symbol.  */
+      for (ii = symbol->n_numaux; ii; --ii ) {
+        raw_symbol += coff_data (abfd)->local_auxesz;
+       ++symnum;
+      }
+    }
+
+    /* if symbol name starts with ".$" or "$", ignore it. */
+    if (cs->c_name[0] == '$' || (cs->c_name[1] == '$' && cs->c_name[0] == '.'))
+      continue;
+
+    if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) {
+      if (last_source_file)
+       end_symtab (cur_src_end_addr, 1, 1, objfile);
+
+      start_symtab ("_globals_", (char *)NULL, (CORE_ADDR)0);
+      cur_src_end_addr = first_object_file_end;
+      /* done with all files, everything from here on is globals */
+    }
+
+    /* if explicitly specified as a function, treat is as one. */
+    if (ISFCN(cs->c_type) && cs->c_sclass != C_TPDEF) {
+      bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+                           main_aux);
+      goto function_entry_point;
+    }
+
+    if ((cs->c_sclass == C_EXT || cs->c_sclass == C_HIDEXT) && cs->c_nsyms == 1)
+    {
+       /* dealing with a symbol with a csect entry. */
+
+#   define     CSECT(PP)       ((PP)->x_csect)
+#   define     CSECT_LEN(PP)   (CSECT(PP).x_scnlen)
+#   define     CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp))
+#   define     CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp))
+#   define     CSECT_SCLAS(PP) (CSECT(PP).x_smclas)
+
+       /* Convert the auxent to something we can access.  */
+        bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+                             main_aux);
+
+       switch (CSECT_SMTYP (main_aux)) {
+
+       case XTY_ER :
+         continue;                     /* ignore all external references. */
+
+       case XTY_SD :                   /* a section description. */
+         {
+           switch (CSECT_SCLAS (main_aux)) {
+
+           case XMC_PR :                       /* a `.text' csect.     */
+             {
+
+               /* A program csect is seen.
+                
+                  We have to allocate one symbol table for each program csect. Normally
+                  gdb prefers one symtab for each compilation unit (CU). In case of AIX, one
+                  CU might include more than one prog csect, and they don't have to be
+                  adjacent in terms of the space they occupy in memory. Thus, one single
+                  CU might get fragmented in the memory and gdb's file start and end address
+                  approach does not work!  */
+
+               if (last_seen_csect) {
+                 complete_symtab (filestring, file_start_addr);
+                 cur_src_end_addr = file_end_addr;
+                 end_symtab (file_end_addr, 1, 1, objfile);
+                 start_symtab ((char *)NULL, (char *)NULL, (CORE_ADDR)0);
+               }
+
+               /* If this is the very first csect seen, basically `__start'. */
+               if (just_started) {
+                 first_object_file_end = cs->c_value + CSECT_LEN (main_aux);
+                 just_started = 0;
+               }
+
+               file_start_addr = cs->c_value;
+               file_end_addr = cs->c_value + CSECT_LEN (main_aux);
+
+               if (cs->c_name && cs->c_name[0] == '.') {
+                 last_seen_csect = cs->c_name;
+                 RECORD_MISC_FUNCTION (cs->c_name, cs->c_value, mf_text, symname_alloced);
+               }
+             }
+             continue;
+
+           case XMC_RW :
+             break;
+
+             /* If the section is not a data description, ignore it. Note that
+                uninitialized data will show up as XTY_CM/XMC_RW pair. */
+
+           case XMC_TC0:
+#ifdef XCOFF_ADD_TOC_TO_LOADINFO
+             XCOFF_ADD_TOC_TO_LOADINFO (cs->c_value);
+#endif
+             /* fall down to default case. */
+
+           case XMC_TC :               /* ignore toc entries   */
+           default     :               /* any other XMC_XXX    */
+             continue;
+           }
+         }
+         break;                        /* switch CSECT_SCLAS() */
+
+       case XTY_LD :
+         
+         /* a function entry point. */
+         if (CSECT_SCLAS (main_aux) == XMC_PR) {
+
+function_entry_point:
+           if (cs->c_value != last_recorded_fun)
+             RECORD_MISC_FUNCTION (cs->c_name, cs->c_value, mf_text, 
+                                                       symname_alloced);
+
+           fcn_line_offset = main_aux->x_sym.x_fcnary.x_fcn.x_lnnoptr;
+           fcn_start_addr = cs->c_value;
+
+           /* save the function header info, which will be used
+              when `.bf' is seen. */
+           fcn_cs_saved = *cs;
+           fcn_aux_saved = *main_aux;
+           continue;
+         }
+
+         /* shared library function entry point. */
+         else if (CSECT_SCLAS (main_aux) == XMC_GL) {
+           if (last_recorded_fun != cs->c_value)
+             RECORD_MISC_FUNCTION (cs->c_name, cs->c_value, mf_text,
+                                                       symname_alloced);
+           continue;
+         }
+         break;
+
+       default :               /* all other XTY_XXXs */
+         break;
+       }                       /* switch CSECT_SMTYP() */
+    }
+
+    switch (cs->c_sclass) {
+
+    case C_FILE:
+
+      /* c_value field contains symnum of next .file entry in table
+        or symnum of first global after last .file. */
+
+      next_file_symnum = cs->c_value;
+
+      /* complete symbol table for last object file containing
+        debugging information. */
+
+      /* Whether or not there was a csect in the previous file, we have 
+        to call `end_symtab' and `start_symtab' to reset type_vector, 
+        line_vector, etc. structures. */
+      complete_symtab (filestring, file_start_addr);
+      cur_src_end_addr = file_end_addr;
+      end_symtab (file_end_addr, 1, 1, objfile);
+      start_symtab (cs->c_name, (char *)NULL, (CORE_ADDR)0);
+      last_seen_csect = 0;
+
+      /* reset file start and end addresses. A compilation unit with no text
+         (only data) should have zero file boundaries. */
+      file_start_addr = file_end_addr = 0;
+
+      filestring = cs->c_name;
+      break;
+
+
+    case C_FCN:
+      if (strcmp (cs->c_name, ".bf") == 0) {
+
+        bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+                             main_aux);
+
+       within_function = 1;
+
+       /* value contains address of first non-init type code */
+       /* main_aux.x_sym.x_misc.x_lnsz.x_lnno
+          contains line number of '{' } */
+       fcn_first_line = main_aux->x_sym.x_misc.x_lnsz.x_lnno;
+
+       /* Linenos are now processed on a file-by-file, not fn-by-fn, basis.
+          Metin did it, I'm not sure why.  FIXME.  -- gnu@cygnus.com */
+       /* mark_first_line (fcn_line_offset, cs->c_symnum); */
+
+       new = push_context (0, fcn_start_addr);
+       new->name = process_xcoff_symbol (&fcn_cs_saved);
+      }
+      else if (strcmp (cs->c_name, ".ef") == 0) {
+
+        bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+                             main_aux);
+
+       /* the value of .ef is the address of epilogue code;
+          not useful for gdb */
+       /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno
+          contains number of lines to '}' */
+
+       fcn_last_line = main_aux->x_sym.x_misc.x_lnsz.x_lnno;
+#if 0
+       enter_linenos (fcn_line_offset, fcn_first_line, 
+                                       fcn_first_line + fcn_last_line);
+#endif
+
+       new = pop_context ();
+       if (context_stack_depth != 0)
+         error ("invalid symbol data; .bf/.ef/.bb/.eb symbol mismatch, at symbol %d.",
+             symnum);
+
+       finish_block (new->name, &local_symbols, new->old_blocks,
+           new->start_addr,
+           fcn_cs_saved.c_value +
+           fcn_aux_saved.x_sym.x_misc.x_fsize);
+       within_function = 0;
+      }
+      break;
+
+    case C_BSTAT       :               /* begin static block   */
+      static_block_base = read_symbol_nvalue (symtbl, cs->c_value);
+      break;
+
+    case C_ESTAT       :               /* end of static block  */
+      static_block_base = 0;
+      break;
+
+    case C_ARG         :               /* These are not implemented. */
+    case C_REGPARM     :
+    case C_TPDEF       :
+    case C_STRTAG      :
+    case C_UNTAG       :
+    case C_ENTAG       :
+      printf ("ERROR: Unimplemented storage class: %d.\n", cs->c_sclass);
+      break;
+
+    case C_HIDEXT      :               /* ignore these.. */
+    case C_LABEL       :
+    case C_NULL                :
+      break;
+
+    case C_BINCL       :               /* beginning of include file */
+       push_subfile ();
+       start_subfile (cs->c_name, (char *)0);
+       fcn_first_line = cs->c_value;   /* Offset to first lineno of file */
+       break;
+
+    case C_EINCL       :               /* end of include file */
+       fcn_last_line = cs->c_value;    /* Offset to last line number */
+       { long dummy = 0;
+       enter_line_range (current_subfile, fcn_first_line, cs->c_value, 0,
+                         &dummy);
+       }
+       start_subfile (pop_subfile (), (char *)0);
+       break;
+
+    case C_BLOCK       :
+      if (strcmp (cs->c_name, ".bb") == 0) {
+       depth++;
+       new = push_context (depth, cs->c_value);
+      }
+      else if (strcmp (cs->c_name, ".eb") == 0) {
+       new = pop_context ();
+       if (depth != new->depth)
+         error ("Invalid symbol data: .bb/.eb symbol mismatch at symbol %d.",
+                        symnum);
+
+       depth--;
+       if (local_symbols && context_stack_depth > 0) {
+         /* Make a block for the local symbols within.  */
+         finish_block (new->name, &local_symbols, new->old_blocks,
+                                 new->start_addr, cs->c_value);
+       }
+       local_symbols = new->locals;
+      }
+      break;
+
+    default            :
+      (void) process_xcoff_symbol (cs);
+      break;
+    }
+
+  } /* while */
+
+  if (last_source_file)
+    end_symtab (cur_src_end_addr, 1, 1, objfile);
+
+  free (symtbl);
+}
+
+#define        SYMBOL_DUP(SYMBOL1, SYMBOL2)    \
+  (SYMBOL2) = (struct symbol *)                \
+       obstack_alloc (symbol_obstack, sizeof (struct symbol)); \
+  *(SYMBOL2) = *(SYMBOL1);
+  
+#define        SYMNAME_ALLOC(NAME, ALLOCED)    \
+  (ALLOCED) ? (NAME) : obstack_copy0 (symbol_obstack, (NAME), strlen (NAME));
+
+
+
+/* process one xcoff symbol. */
+
+static struct symbol *
+process_xcoff_symbol (cs)
+  register struct coff_symbol *cs;
+{
+  struct symbol onesymbol;
+  register struct symbol *sym = &onesymbol;
+  struct symbol *sym2 = NULL;
+  struct type *ttype;
+  char *name, *pp, *qq;
+
+  name = cs->c_name;
+  if (name[0] == '.')
+    ++name;
+
+  bzero (sym, sizeof (struct symbol));
+
+  /* default assumptions */
+  SYMBOL_VALUE (sym) = cs->c_value;
+  SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+  if (ISFCN (cs->c_type)) {
+
+    /* At this point, we don't know the type of the function and assume it 
+       is int. This will be patched with the type from its stab entry later 
+       on in patch_block_stabs () */
+
+    SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
+    SYMBOL_TYPE (sym) = lookup_function_type (builtin_type_int);
+
+    SYMBOL_CLASS (sym) = LOC_BLOCK;
+    SYMBOL_DUP (sym, sym2);
+
+    if (cs->c_sclass == C_EXT)
+      add_symbol_to_list (sym2, &global_symbols);
+    else if (cs->c_sclass == C_HIDEXT || cs->c_sclass == C_STAT)
+      add_symbol_to_list (sym2, &file_symbols);
+  }
+
+  else {
+
+    /* in case we can't figure out the type, default is `int'. */
+    SYMBOL_TYPE (sym) = builtin_type_int;
+
+    switch (cs->c_sclass)
+    {
+    case C_FUN:
+      if (fcn_cs_saved.c_sclass == C_EXT)
+       add_stab_to_list (name, &global_stabs);
+      else
+       add_stab_to_list (name, &file_stabs);
+      break;
+
+    case C_DECL:                       /* a type decleration?? */
+       qq =  (char*) index (name, ':');
+       if (!qq)                        /* skip if there is no ':' */
+         return NULL;
+
+       pp = qq + 2;
+       ttype = SYMBOL_TYPE (sym) = read_type (&pp);
+
+       /* read_type() will return null if type (or tag) definition was
+          unnnecessarily duplicated. Also, if the symbol doesn't have a name,
+          there is no need to keep it in symbol table. */
+
+       if (!ttype || name == qq)
+         return NULL;
+
+       if (qq[1] == 'T')
+         SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+       else if (qq[1] == 't')
+         SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+       else {
+         printf ("ERROR: Unrecognized stab string.\n");
+         return NULL;
+       }
+
+       SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+       SYMBOL_NAME (sym) = obsavestring (name, qq-name);
+
+       if  (SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE)
+           TYPE_NAME (ttype) = concat (
+               TYPE_CODE (ttype) == TYPE_CODE_UNION ? "union " :
+               TYPE_CODE (ttype) == TYPE_CODE_STRUCT? "struct " : "enum ",
+               SYMBOL_NAME (sym), "");
+
+       else if (!TYPE_NAME (ttype))      /* else, regular typedef. */
+           TYPE_NAME (ttype) = SYMBOL_NAME (sym);
+
+       SYMBOL_DUP (sym, sym2);
+       add_symbol_to_list 
+          (sym2, within_function ? &local_symbols : &file_symbols);
+       break;
+
+    case C_GSYM:
+      add_stab_to_list (name, &global_stabs);
+      break;
+
+    case C_PSYM:
+       if (*name == ':' || (pp = (char *) index (name, ':')) == NULL)
+         return NULL;
+       SYMBOL_NAME (sym) = obsavestring (name, pp-name);
+       SYMBOL_CLASS (sym) = LOC_ARG;
+       pp += 2;
+       SYMBOL_TYPE (sym) = read_type (&pp);
+       SYMBOL_DUP (sym, sym2);
+       add_symbol_to_list (sym2, &local_symbols);
+       break;
+
+    case C_STSYM:
+       if (*name == ':' || (pp = (char *) index (name, ':')) == NULL)
+         return NULL;
+       SYMBOL_NAME (sym) = obsavestring (name, pp-name);
+       SYMBOL_CLASS (sym) = LOC_STATIC;
+       SYMBOL_VALUE (sym) += static_block_base;
+       pp += 2;
+       SYMBOL_TYPE (sym) = read_type (&pp);
+       SYMBOL_DUP (sym, sym2);
+       add_symbol_to_list 
+          (sym2, within_function ? &local_symbols : &file_symbols);
+       break;
+
+    case C_LSYM:
+       if (*name == ':' || (pp = (char *) index (name, ':')) == NULL)
+         return NULL;
+       SYMBOL_NAME (sym) = obsavestring (name, pp-name);
+       SYMBOL_CLASS (sym) = LOC_LOCAL;
+       pp += 1;
+       SYMBOL_TYPE (sym) = read_type (&pp);
+       SYMBOL_DUP (sym, sym2);
+       add_symbol_to_list (sym2, &local_symbols);
+       break;
+
+    case C_AUTO:
+      SYMBOL_CLASS (sym) = LOC_LOCAL;
+      SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
+      SYMBOL_DUP (sym, sym2);
+      add_symbol_to_list (sym2, &local_symbols);
+      break;
+
+    case C_EXT:
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+      SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
+      SYMBOL_DUP (sym, sym2);
+      add_symbol_to_list (sym2, &global_symbols);
+      break;
+
+    case C_STAT:
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+      SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
+      SYMBOL_DUP (sym, sym2);
+      add_symbol_to_list 
+          (sym2, within_function ? &local_symbols : &file_symbols);
+      break;
+
+    case C_REG:
+      printf ("ERROR! C_REG is not fully implemented!\n");
+      SYMBOL_CLASS (sym) = LOC_REGISTER;
+      SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
+      SYMBOL_DUP (sym, sym2);
+      add_symbol_to_list (sym2, &local_symbols);
+      break;
+
+    case C_RSYM:
+       pp = (char*) index (name, ':');
+       SYMBOL_CLASS (sym) = LOC_REGISTER;
+       SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (cs->c_value);
+       if (pp) {
+         SYMBOL_NAME (sym) = obsavestring (name, pp-name);
+         pp += 2;
+         if (*pp)
+           SYMBOL_TYPE (sym) = read_type (&pp);
+       }
+       else
+         /* else this is not a stab entry, suppose the type is either
+            `int' or `float', depending on the register class. */
+
+         SYMBOL_TYPE (sym) = (SYMBOL_VALUE (sym) < 32) ? 
+             builtin_type_int : builtin_type_float;
+
+       SYMBOL_DUP (sym, sym2);
+       add_symbol_to_list (sym2, &local_symbols);
+       break;
+
+    default    :
+      printf ("ERROR: Unexpected storage class: %d.\n", cs->c_sclass);
+      return NULL;
+    }
+  }
+  return sym2;
+}
+
+
+static int
+read_symbol_nvalue (symtable, symno)
+     char *symtable;
+     int symno;
+{
+  struct internal_syment symbol[1];
+
+  bfd_coff_swap_sym_in (symfile_bfd, symtable + (symno*local_symesz), symbol);
+  return symbol->n_value;  
+}
+
+
+static int
+read_symbol_lineno (symtable, symno)
+  char *symtable;
+  int symno;
+{
+  struct internal_syment symbol[1];
+  union internal_auxent main_aux[1];
+
+  int ii;
+
+  for (ii = 0; ii < 50; ii++) {
+    bfd_coff_swap_sym_in (symfile_bfd,
+                            symtable + (symno*local_symesz), symbol);
+    if (symbol->n_sclass == C_FCN && 0 == strcmp (symbol->n_name, ".bf"))
+      goto gotit;
+    symno += 1 + symbol->n_numaux+1;
+  }
+
+  printf ("GDB Error: `.bf' not found.\n");
+  return 0;
+
+gotit:
+  /* take aux entry and return its lineno */
+  symno++;
+  bfd_coff_swap_aux_in (symfile_bfd, symtable+(symno*local_symesz),
+                       symbol->n_type, symbol->n_sclass, main_aux);
+
+  return main_aux->x_sym.x_misc.x_lnsz.x_lnno;
+}
+
+/* Support for line number handling */
+
+/* This function is called for every section; it finds the outer limits
+ * of the line table (minimum and maximum file offset) so that the
+ * mainline code can read the whole thing for efficiency.
+ */
+static void
+find_linenos(abfd, asect, vpinfo)
+bfd *abfd;
+sec_ptr asect;
+void *vpinfo; 
+{
+  struct coff_symfile_info *info;
+  int size, count;
+  file_ptr offset, maxoff;
+
+  count = asect->lineno_count;
+
+  if (count == 0)
+    return;
+
+  size   = count * coff_data (symfile_bfd)->local_linesz;
+  info   = (struct coff_symfile_info *)vpinfo;
+  offset = asect->line_filepos;
+  maxoff = offset + size;
+
+  if (offset < info->min_lineno_offset || info->min_lineno_offset == 0)
+    info->min_lineno_offset = offset;
+
+  if (maxoff > info->max_lineno_offset)
+    info->max_lineno_offset = maxoff;
+}
+
+
+/* Read in all the line numbers for fast lookups later.  Leave them in
+   external (unswapped) format in memory; we'll swap them as we enter
+   them into GDB's data structures.  */
+
+static int
+init_lineno (abfd, offset, size)
+     bfd *abfd;
+     long offset;
+     int size;
+{
+  int val;
+
+  if (bfd_seek(abfd, offset, 0) < 0)
+    return -1;
+
+  linetab = (char *) xmalloc(size);
+
+  val = bfd_read(linetab, 1, size, abfd);
+  if (val != size)
+    return -1;
+
+  linetab_offset = offset;
+  linetab_size = size;
+  make_cleanup(free, linetab); /* Be sure it gets de-allocated. */
+  return 0;
+}
+
+
+void
+dump_strtbl ()
+{
+  int ii;
+  printf ("===STRING TABLE DUMP...\n\n");
+  for ( ii=0; ii < strtbl_len; ++ii )
+    printf ("%c", isprint (*(strtbl+ii)) ? *(strtbl+ii) : ' ');
+  printf ("\n");
+}
+
+void
+dump_linetable (ltb)
+     struct linetable *ltb;
+{
+  int ii;
+  for (ii=0; ii < ltb->nitems; ++ii)
+    printf ("line: %d, addr: 0x%x\n", ltb->item[ii].line, ltb->item[ii].pc);
+}
+
+void
+dump_type (typeP)
+     struct type *typeP;
+{
+  printf ("0x%x: name: %s\n", typeP, typeP->name ? typeP->name : "(nil)");
+}
+
+char *dump_namespace ();
+char *dump_addrclass ();
+
+void
+dump_symbol (pp)
+     struct symbol *pp;
+{
+  printf (" sym: %s\t%s,\t%s\ttype: 0x%x, val: 0x%x end: 0x%x\n", 
+      pp->name, dump_namespace (pp->namespace),
+      dump_addrclass (pp->class), pp->type,
+      SYMBOL_CLASS(pp) == LOC_BLOCK ? BLOCK_START(SYMBOL_BLOCK_VALUE(pp))
+      : pp->value.value,
+      SYMBOL_CLASS(pp) == LOC_BLOCK ? BLOCK_END(SYMBOL_BLOCK_VALUE(pp)) : 0);
+}
+
+
+char *
+dump_namespace (ns)
+int ns;
+{
+  static char *ns_name [] = { 
+    "UNDEF_NS", "VAR_NS", "STRUCT_NS", "LABEL_NS"};
+
+  switch (ns) {
+  case UNDEF_NAMESPACE:
+  case VAR_NAMESPACE:
+  case STRUCT_NAMESPACE:
+  case LABEL_NAMESPACE:
+    return ns_name[ns];
+  }
+  return "***ERROR***";
+}
+
+
+char *
+dump_addrclass (ac)
+int ac;                                                /* address class */
+{
+  static char *ac_name [] = {
+    "LOC_UNDEF",
+    "LOC_CONST",
+    "LOC_STATIC",
+    "LOC_REGISTER",
+    "LOC_ARG",
+    "LOC_REF_ARG",
+    "LOC_REGPARM",
+    "LOC_LOCAL",
+    "LOC_TYPEDEF",
+    "LOC_LABEL",
+    "LOC_BLOCK",
+    "LOC_CONST_BYTES",
+    "LOC_LOCAL_ARG",
+  };
+  switch (ac) {
+  case LOC_UNDEF:
+  case LOC_CONST:
+  case LOC_STATIC:
+  case LOC_REGISTER:
+  case LOC_ARG:
+  case LOC_REF_ARG:
+  case LOC_REGPARM:
+  case LOC_LOCAL:
+  case LOC_TYPEDEF:
+  case LOC_LABEL:
+  case LOC_BLOCK:
+  case LOC_CONST_BYTES:
+  case LOC_LOCAL_ARG:
+    return ac_name [ac];
+  }
+  return "***ERROR***";
+}
+
+void
+dump_block (pp)
+     struct block *pp;
+{
+  int ii;
+  printf ("BLOCK..: start: 0x%x, end: 0x%x\n", pp->startaddr, pp->endaddr);
+  for (ii=0; ii < pp->nsyms; ++ii)
+    dump_symbol (pp->sym[ii]);
+}
+
+void
+dump_blockvector (pp)
+     struct blockvector *pp;
+{
+  int ii;
+  for (ii=0; ii < pp->nblocks; ++ii)
+    dump_block (pp->block [ii]);
+}
+
+
+void
+dump_last_symtab (pp)
+     struct symtab *pp;
+{
+  for ( ; pp; pp = pp->next) {
+    if ( pp->next == 0 ) {
+      printf ("SYMTAB NAME: %s\n", pp->filename);
+      dump_blockvector (pp->blockvector);
+    }
+  }
+}
+
+void
+dump_symtabs (pp)
+     struct symtab *pp;
+{
+  for ( ; pp; pp = pp->next) {
+    printf ("SYMTAB NAME: %s\n", pp->filename ? pp->filename : "(nil)");
+/*    if (pp->linetable)
+      dump_linetable (pp->linetable); */
+    dump_blockvector (pp->blockvector);
+  }
+}
+
+void
+dump_symtab_lines (pp)
+     struct symtab *pp;
+{
+  for ( ; pp; pp = pp->next) {
+    printf ("SYMTAB NAME: %s\n", pp->filename ? pp->filename : "(nil)");
+    if (pp->linetable)
+      dump_linetable (pp->linetable);
+    /* dump_blockvector (pp->blockvector); */
+  }
+}
+
+void
+dump_misc_funcs ()
+{
+  int ii;
+  for (ii=0; ii < misc_function_count; ++ii)
+    printf ("name: %s, addr: 0x%x\n", 
+       misc_function_vector[ii].name, 
+       misc_function_vector[ii].address);
+}
+
+
+/* dbx allows the text of a symbol name to be continued into the
+   next symbol name!  When such a continuation is encountered
+   (a \ at the end of the text of a name)
+   call this function to get the continuation.  */
+/* So far, I haven't seen this happenning xlc output. I doubt we'll need this
+   for aixcoff. */
+
+#define        next_symbol_text() \
+  printf ("Gdb Error: symbol names on multiple lines not implemented.\n")
+
+
+/* xlc/dbx combination uses a set of builtin types, starting from -1. return
+   the proper type node fora given builtin type #. */
+
+struct type *
+builtin_type (pp)
+char **pp;
+{
+  int typenums[2];
+
+  if (**pp != '-') {
+    printf ("ERROR!, unknown built-in type!\n");
+    return NULL;
+  }
+  *pp += 1;
+  read_type_number (pp, typenums);
+
+  /* default types are defined in dbxstclass.h. */
+  switch ( typenums[1] ) {
+  case 1: 
+    return builtin_type_int;
+  case 2: 
+    return builtin_type_char;
+  case 3: 
+    return builtin_type_short;
+  case 4: 
+    return builtin_type_long;
+  case 5: 
+    return builtin_type_unsigned_char;
+  case 6: 
+    return builtin_type_char;     /* requires a builtin `signed char' */
+  case 7: 
+    return builtin_type_unsigned_short;
+  case 8: 
+    return builtin_type_unsigned_int;
+  case 9: 
+    return builtin_type_unsigned_int;
+  case 10: 
+    return builtin_type_unsigned_long;
+  case 11: 
+    return builtin_type_void;
+  case 12: 
+    return builtin_type_float;
+  case 13: 
+    return builtin_type_double;
+  case 14: 
+    return builtin_type_double;   /* requires a builtin `long double' */
+  case 15: 
+    return builtin_type_int;      /* requires a builtin `integer' */
+  case 16: 
+    return builtin_type_int;      /* requires builtin `boolean' */
+  case 17: 
+    return builtin_type_float;    /* requires builtin `short real' */
+  case 18: 
+    return builtin_type_float;    /* requires builtin `real' */
+  default :
+    printf ("ERROR! Unknown builtin type -%d\n", typenums[1]);
+    return NULL;
+  }
+}
+
+/* if we now nothing about a function but its address, make a function symbol
+   out of it with the limited knowladge you have. This will be used when
+   somebody refers to a function, which doesn't exist in the symbol table,
+   but in misc_function_vector. */
+
+struct symbol *
+build_function_symbol (ind)
+     int ind;
+{
+  struct symbol *sym =
+  (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
+  SYMBOL_NAME (sym) = misc_function_vector[ind].name;
+  /*   SYMBOL_VALUE (sym) = misc_function_vector[ind].address; */
+  SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+  SYMBOL_CLASS (sym) = LOC_BLOCK;
+  SYMBOL_TYPE (sym) = lookup_function_type (builtin_type_int);
+  SYMBOL_BLOCK_VALUE (sym) = (struct block *)
+      obstack_alloc (symbol_obstack, sizeof (struct block));
+  BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) = misc_function_vector[ind].address;
+  return sym;
+}
+
+
+void
+aixcoff_new_init ()
+{
+  /* Nothin' to do.  */
+}
+
+void
+aixcoff_symfile_init (sf)
+struct sym_fns *sf;
+{
+  bfd *abfd = sf->sym_bfd;
+
+  /* Allocate struct to keep track of the symfile */
+  /* FIXME memory leak */
+  sf->sym_private = xmalloc(sizeof (struct coff_symfile_info));
+
+  /*
+   * Save startup file's range of PC addresses to help
+   * blockframe.c decide where the bottom of the stack is.
+   */
+  if (bfd_get_file_flags(abfd) & EXEC_P) {
+    entry_point = bfd_get_start_address(abfd);
+  } else {
+    entry_point = ~0;
+    /* set the startup file to be an empty range.  */
+    startup_file_start = 0;
+    startup_file_end = 0;
+  }
+}
+
+
+static int
+init_stringtab(abfd, offset)
+     bfd *abfd;
+     long offset;
+{
+  long length;
+  int val;
+  unsigned char lengthbuf[4];
+
+  if (bfd_seek(abfd, offset, 0) < 0)
+    return -1;
+
+  val    = bfd_read((char *)lengthbuf, 1, sizeof lengthbuf, abfd);
+  length = bfd_h_get_32(abfd, lengthbuf);
+
+  /* If no string table is needed, then the file may end immediately
+     after the symbols.  Just return with `strtbl' set to null. */
+
+  if (val != sizeof length || length < sizeof length)
+    return 0;
+
+  /* Allocate string table from symbol_obstack. We will need this table
+     as long as we have its symbol table around. */
+
+  strtbl = (char*) obstack_alloc (symbol_obstack, length);
+  if (strtbl == NULL)
+    return -1;
+
+  bcopy(&length, strtbl, sizeof length);
+  if (length == sizeof length)
+    return 0;
+
+  val = bfd_read(strtbl + sizeof length, 1, length - sizeof length, abfd);
+
+  if (val != length - sizeof length || strtbl[length - 1] != '\0')
+    return -1;
+
+  return 0;
+}
+
+static int
+init_debugsection(abfd)
+     bfd *abfd;
+{
+  register sec_ptr secp;
+  bfd_size_type length;
+
+  if (debugsec) {
+    free(debugsec);
+    debugsec = NULL;
+  }
+
+  secp = bfd_get_section_by_name(abfd, ".debug");
+  if (!secp)
+    return 0;
+
+  if (!(length = bfd_section_size(abfd, secp)))
+    return 0;
+
+  debugsec = (void *) xmalloc ((unsigned)length);
+  if (debugsec == NULL)
+    return -1;
+
+  if (!bfd_get_section_contents(abfd, secp, debugsec, (file_ptr) 0, length)) {
+    printf ("Can't read .debug section from symbol file\n");
+    return -1;
+  }
+  return 0;
+}
+
+static void
+free_debugsection()
+{
+  if (debugsec)
+    free(debugsec);
+  debugsec = NULL;
+}
+
+
+/* aixcoff version of symbol file read. */
+
+void
+aixcoff_symfile_read (sf, addr, mainline)
+  struct sym_fns *sf;
+  CORE_ADDR addr;
+  int mainline;
+{
+  int num_symbols;                             /* # of symbols */
+  int symtab_offset;                           /* symbol table and */
+  int stringtab_offset;                                /* string table file offsets */
+  int val;
+  bfd *abfd;
+  struct coff_symfile_info *info = (void*) sf->sym_private;
+  char *name;
+
+  symfile_bfd = abfd = sf->objfile->obfd;
+  name = sf->objfile->name;
+
+  num_symbols = bfd_get_symcount (abfd);       /* # of symbols */
+  symtab_offset = obj_sym_filepos (abfd);      /* symbol table file offset */
+  stringtab_offset = symtab_offset +
+    num_symbols * coff_data(abfd)->local_symesz;
+
+  info->min_lineno_offset = 0;
+  info->max_lineno_offset = 0;
+  bfd_map_over_sections (abfd, find_linenos, info);
+
+  /* FIXME!  This stuff should move into symfile_init */
+  if (info->min_lineno_offset != 0
+      && info->max_lineno_offset > info->min_lineno_offset) {
+
+    /* only read in the line # table if one exists */
+    val = init_lineno(abfd, info->min_lineno_offset,
+       info->max_lineno_offset - info->min_lineno_offset);
+
+    if (val < 0)
+      error("\"%s\": error reading line numbers\n", name);
+  }
+
+  val = init_stringtab(abfd, stringtab_offset);
+  if (val < 0) {
+    error ("\"%s\": can't get string table", name);
+  }
+
+  if (init_debugsection(abfd) < 0) {
+    error ("Error reading .debug section of `%s'\n", name);
+  }
+
+  /* Position to read the symbol table.  Do not read it all at once. */
+  val = bfd_seek(abfd, (long)symtab_offset, 0);
+  if (val < 0)
+    perror_with_name(name);
+
+  if (bfd_tell(abfd) != symtab_offset)
+    fatal("bfd? BFD!");
+
+  init_misc_bunches ();
+  make_cleanup(discard_misc_bunches, 0);
+
+#ifdef XCOFF_INIT_LOADINFO
+  if (mainline)
+    XCOFF_INIT_LOADINFO ();
+#endif
+
+  /* Now that the executable file is positioned at symbol table,
+     process it and define symbols accordingly. */
+
+  read_xcoff_symtab(sf->objfile, num_symbols);
+
+  make_cleanup(free_debugsection, 0);
+
+  /* Sort symbols alphabetically within each block.  */
+  sort_syms ();
+
+  /* Go over the misc functions and install them in vector.  */
+  condense_misc_bunches (!mainline);
+
+  /* Make a default for file to list.  */
+  select_source_symtab (0);
+}
+
+/* Register our ability to parse symbols for aixcoff BFD files. */
+
+static struct sym_fns aixcoff_sym_fns =
+{
+  "aixcoff-rs6000", 15,
+  aixcoff_new_init, aixcoff_symfile_init,
+  aixcoff_symfile_read, 
+};
+
+void
+_initialize_xcoffread ()
+{
+  add_symtab_fns(&aixcoff_sym_fns);
+}