* inftarg.c (child_thread_alive): New function to see if a
[deliverable/binutils-gdb.git] / gdb / mdebugread.c
index c23dac03f1dcad538099c27efca3d6bbde37f835..c4f18890072e559a9b8cb876a1d34361b4c69c1c 100644 (file)
@@ -1,6 +1,6 @@
 /* Read a symbol table in ECOFF format (Third-Eye).
-   Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software
-   Foundation, Inc.
+   Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+   Free Software Foundation, Inc.
    Original version contributed by Alessandro Forin (af@cs.cmu.edu) at
    CMU.  Major work by Per Bothner, John Gilmore and Ian Lance Taylor
    at Cygnus Support.
@@ -97,34 +97,33 @@ typedef struct mips_extra_func_info {
 #ifndef ECOFF_REG_TO_REGNUM
 #define ECOFF_REG_TO_REGNUM(num) (num)
 #endif
-
-/* Each partial symbol table entry contains a pointer to private data
-   for the read_symtab() function to use when expanding a partial
-   symbol table entry to a full symbol table entry.
-
-   For mdebugread this structure contains the index of the FDR that this
-   psymtab represents and a pointer to the BFD that the psymtab was
-   created from.  */
-
-#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private)
-#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx)
-#define CUR_BFD(p) (PST_PRIVATE(p)->cur_bfd)
-#define DEBUG_SWAP(p) (PST_PRIVATE(p)->debug_swap)
-#define DEBUG_INFO(p) (PST_PRIVATE(p)->debug_info)
-#define PENDING_LIST(p) (PST_PRIVATE(p)->pending_list)
+\f
+/* We put a pointer to this structure in the read_symtab_private field
+   of the psymtab.  */
 
 struct symloc
 {
+  /* Index of the FDR that this psymtab represents.  */
   int fdr_idx;
+  /* The BFD that the psymtab was created from.  */
   bfd *cur_bfd;
   const struct ecoff_debug_swap *debug_swap;
   struct ecoff_debug_info *debug_info;
   struct mdebug_pending **pending_list;
-  EXTR *extern_tab;            /* Pointer to external symbols for this file. */
-  int extern_count;            /* Size of extern_tab. */
+  /* Pointer to external symbols for this file.  */
+  EXTR *extern_tab;
+  /* Size of extern_tab.  */
+  int extern_count;
   enum language pst_language;
 };
 
+#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private)
+#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx)
+#define CUR_BFD(p) (PST_PRIVATE(p)->cur_bfd)
+#define DEBUG_SWAP(p) (PST_PRIVATE(p)->debug_swap)
+#define DEBUG_INFO(p) (PST_PRIVATE(p)->debug_info)
+#define PENDING_LIST(p) (PST_PRIVATE(p)->pending_list)
+\f
 /* Things we import explicitly from other modules */
 
 extern int info_verbose;
@@ -274,12 +273,19 @@ static char stabs_symbol[] = STABS_SYMBOL;
    be using our own types thoughout this file, instead of sometimes using
    builtin_type_*.  */
 
-static struct type *mdebug_type_complex;
-static struct type *mdebug_type_double_complex;
 static struct type *mdebug_type_fixed_dec;
 static struct type *mdebug_type_float_dec;
 static struct type *mdebug_type_string;
 
+/* Types for symbols from files compiled without debugging info.  */
+
+static struct type *nodebug_func_symbol_type;
+static struct type *nodebug_var_symbol_type;
+
+/* Nonzero if we have seen ecoff debugging info for a file.  */
+
+static int found_ecoff_debugging_info;
+
 /* Forward declarations */
 
 static int
@@ -292,6 +298,9 @@ parse_partial_symbols PARAMS ((struct objfile *,
 static FDR
 *get_rfd PARAMS ((int, int));
 
+static int
+has_opaque_xref PARAMS ((FDR *, SYMR *));
+
 static int
 cross_ref PARAMS ((int, union aux_ext *, struct type **, enum type_code,
                   char **, int, char *));
@@ -315,7 +324,7 @@ static struct blockvector *
 new_bvect PARAMS ((int));
 
 static int
-parse_symbol PARAMS ((SYMR *, union aux_ext *, char *, int));
+parse_symbol PARAMS ((SYMR *, union aux_ext *, char *, int, struct section_offsets *));
 
 static struct type *
 parse_type PARAMS ((int, union aux_ext *, unsigned int, int *, int, char *));
@@ -337,7 +346,7 @@ static int
 compare_blocks PARAMS ((const void *, const void *));
 
 static struct partial_symtab *
-new_psymtab PARAMS ((char *, struct objfile *));
+new_psymtab PARAMS ((char *, struct objfile *, struct section_offsets *));
 
 static void
 psymtab_to_symtab_1 PARAMS ((struct partial_symtab *, char *));
@@ -354,6 +363,9 @@ add_line PARAMS ((struct linetable *, int, CORE_ADDR, int));
 static struct linetable *
 shrink_linetable PARAMS ((struct linetable *));
 
+static void
+handle_psymbol_enumerators PARAMS ((struct objfile *, FDR *, int));
+
 static char *
 mdebug_next_symbol_text PARAMS ((void));
 \f
@@ -645,11 +657,12 @@ add_pending (fh, sh, t)
    SYMR's handled (normally one).  */
 
 static int
-parse_symbol (sh, ax, ext_sh, bigend)
+parse_symbol (sh, ax, ext_sh, bigend, section_offsets)
      SYMR *sh;
      union aux_ext *ax;
      char *ext_sh;
      int bigend;
+     struct section_offsets *section_offsets;
 {
   const bfd_size_type external_sym_size = debug_swap->external_sym_size;
   void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) =
@@ -671,6 +684,30 @@ parse_symbol (sh, ax, ext_sh, bigend)
   else
     name = debug_info->ss + cur_fdr->issBase + sh->iss;
 
+  switch (sh->sc)
+    {
+    case scText:
+      /* Do not relocate relative values.
+        The value of a stEnd symbol is the displacement from the
+        corresponding start symbol value.
+        The value of a stBlock symbol is the displacement from the
+        procedure address.  */
+      if (sh->st != stEnd && sh->st != stBlock)
+       sh->value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+      break;
+    case scData:
+    case scSData:
+    case scRData:
+    case scPData:
+    case scXData:
+      sh->value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+      break;
+    case scBss:
+    case scSBss:
+      sh->value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+      break;
+    }
+
   switch (sh->st)
     {
     case stNil:
@@ -688,7 +725,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
       class = LOC_STATIC;
       b = top_stack->cur_block;
       s = new_symbol (name);
-      if (sh->sc == scCommon)
+      if (sh->sc == scCommon || sh->sc == scSCommon)
        {
          /* It is a FORTRAN common block.  At least for SGI Fortran the
             address is not in the symbol; we need to fix it later in
@@ -718,10 +755,9 @@ parse_symbol (sh, ax, ext_sh, bigend)
       SYMBOL_CLASS (s) = class;
       add_symbol (s, b);
 
-      /* Type could be missing in a number of cases */
-      if (sh->sc == scUndefined || sh->sc == scNil ||
-         sh->index == 0xfffff)
-       SYMBOL_TYPE (s) = builtin_type_int;     /* undefined? */
+      /* Type could be missing if file is compiled without debugging info.  */
+      if (sh->sc == scUndefined || sh->sc == scNil || sh->index == indexNil)
+       SYMBOL_TYPE (s) = nodebug_var_symbol_type;
       else
        SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name);
       /* Value of a data symbol is its memory address */
@@ -729,6 +765,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
 
     case stParam:              /* arg to procedure, goes into current block */
       max_gdbinfo++;
+      found_ecoff_debugging_info = 1;
       top_stack->numargs++;
 
       /* Special GNU C++ name.  */
@@ -761,12 +798,6 @@ parse_symbol (sh, ax, ext_sh, bigend)
       SYMBOL_VALUE (s) = svalue;
       SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name);
       add_symbol (s, top_stack->cur_block);
-#if 0
-      /* FIXME:  This has not been tested.  See dbxread.c */
-      /* Add the type of this parameter to the function/procedure
-                  type of this block. */
-      add_param_to_type (&top_stack->cur_block->function->type, s);
-#endif
       break;
 
     case stLabel:              /* label, goes into current block */
@@ -806,15 +837,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
       add_symbol (s, b);
 
       /* Make a type for the procedure itself */
-#if 0
-      /* FIXME:  This has not been tested yet!  See dbxread.c */
-      /* Generate a template for the type of this function.  The
-        types of the arguments will be added as we read the symbol
-        table. */
-      memcpy (lookup_function_type (t), SYMBOL_TYPE (s), sizeof (struct type));
-#else
       SYMBOL_TYPE (s) = lookup_function_type (t);
-#endif
 
       /* Create and enter a new lexical context */
       b = new_block (top_stack->maxsyms);
@@ -859,7 +882,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
        goto structured_common;
 
     case stBlock:              /* Either a lexical block, or some type */
-       if (sh->sc != scInfo && sh->sc != scCommon)
+       if (sh->sc != scInfo && sh->sc != scCommon && sh->sc != scSCommon)
          goto case_stBlock_code;       /* Lexical block */
 
        type_code = TYPE_CODE_UNDEF;    /* We have a type.  */
@@ -868,6 +891,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
           unknown-type blocks of info about structured data.  `type_code'
           has been set to the proper TYPE_CODE, if we know it.  */
       structured_common:
+       found_ecoff_debugging_info = 1;
        push_parse_stack ();
        top_stack->blocktype = stBlock;
 
@@ -896,9 +920,9 @@ parse_symbol (sh, ax, ext_sh, bigend)
                    type_code = TYPE_CODE_ENUM;
                  else
                    {
-                     ecoff_swap_tir_in (bigend,
-                                        &ax[tsym.index].a_ti,
-                                        &tir);
+                     (*debug_swap->swap_tir_in) (bigend,
+                                                 &ax[tsym.index].a_ti,
+                                                 &tir);
                      if ((tir.bt == btNil || tir.bt == btVoid)
                          && tir.tq0 == tqNil)
                        type_code = TYPE_CODE_ENUM;
@@ -938,6 +962,13 @@ parse_symbol (sh, ax, ext_sh, bigend)
                   Just ignore it. */
                break;
 
+             case stIndirect:
+               /* Irix5 cc puts out a stIndirect for struct x if it is not
+                  yet defined when it encounters
+                  struct y { struct x *xp; };
+                  Just ignore it. */
+               break;
+
              default:
                complain (&block_member_complaint, tsym.st);
              }
@@ -993,8 +1024,10 @@ parse_symbol (sh, ax, ext_sh, bigend)
        else
          t = pend->t;
 
-       /* Alpha cc unnamed structs do not get a tag name.  */
-       if (sh->iss == 0)
+       /* Do not set the tag name if it is a compiler generated tag name
+          (.Fxx or .xxfake or empty) for unnamed struct/union/enums.
+          Alpha cc puts out an sh->iss of zero for those.  */
+       if (sh->iss == 0 || name[0] == '.' || name[0] == '\0')
          TYPE_TAG_NAME (t) = NULL;
        else
          TYPE_TAG_NAME (t) = obconcat (&current_objfile->symbol_obstack,
@@ -1011,7 +1044,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
          {
            /* This is a non-empty enum. */
 
-           /* c89 has the number of enumerators in the sh.value field,
+           /* DEC c89 has the number of enumerators in the sh.value field,
               not the type length, so we have to compensate for that
               incompatibility quirk.
               This might do the wrong thing for an enum with one or two
@@ -1081,6 +1114,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
       }
 
     case_stBlock_code:
+      found_ecoff_debugging_info = 1;
       /* beginnning of (code) block. Value of symbol
         is the displacement from procedure start */
       push_parse_stack ();
@@ -1104,7 +1138,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
       break;
 
     case stEnd:                /* end (of anything) */
-      if (sh->sc == scInfo || sh->sc == scCommon)
+      if (sh->sc == scInfo || sh->sc == scCommon || sh->sc == scSCommon)
        {
          /* Finished with type */
          top_stack->cur_type = 0;
@@ -1117,6 +1151,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
          struct blockvector *bv = BLOCKVECTOR (top_stack->cur_st);
          struct mips_extra_func_info *e;
          struct block *b;
+         struct type *ftype = top_stack->cur_type;
          int i;
 
          BLOCK_END (top_stack->cur_block) += sh->value;        /* size */
@@ -1129,8 +1164,10 @@ parse_symbol (sh, ax, ext_sh, bigend)
          e = ((struct mips_extra_func_info *)
               obstack_alloc (&current_objfile->symbol_obstack,
                              sizeof (struct mips_extra_func_info)));
+         memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
          SYMBOL_VALUE (s) = (long) e;
          e->numargs = top_stack->numargs;
+         e->pdr.framereg = -1;
          add_symbol (s, top_stack->cur_block);
 
          /* Reallocate symbols, saving memory */
@@ -1149,6 +1186,39 @@ parse_symbol (sh, ax, ext_sh, bigend)
                  BLOCK_END (b_bad) = BLOCK_END (b);
                }
            }
+
+         if (TYPE_NFIELDS (ftype) <= 0)
+           {
+             /* No parameter type information is recorded with the function's
+                type.  Set that from the type of the parameter symbols. */
+             int nparams = top_stack->numargs;
+             int iparams;
+             struct symbol *sym;
+
+             if (nparams > 0)
+               {
+                 TYPE_NFIELDS (ftype) = nparams;
+                 TYPE_FIELDS (ftype) = (struct field *)
+                   TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+                                                   
+                 for (i = iparams = 0; iparams < nparams; i++)
+                   {
+                     sym = BLOCK_SYM (b, i);
+                     switch (SYMBOL_CLASS (sym))
+                       {
+                       case LOC_ARG:
+                       case LOC_REF_ARG:
+                       case LOC_REGPARM:
+                       case LOC_REGPARM_ADDR:
+                         TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
+                         iparams++;
+                         break;
+                       default:
+                         break;
+                       }
+                   }
+               }
+           }
        }
       else if (sh->sc == scText && top_stack->blocktype == stBlock)
        {
@@ -1185,7 +1255,14 @@ parse_symbol (sh, ax, ext_sh, bigend)
       f->bitsize = bitsize;
       break;
 
+    case stIndirect:           /* forward declaration on Irix5 */
+      /* Forward declarations from Irix5 cc are handled by cross_ref,
+        skip them.  */
+      break;
+
     case stTypedef:            /* type definition */
+      found_ecoff_debugging_info = 1;
+
       /* Typedefs for forward declarations and opaque structs from alpha cc
         are handled by cross_ref, skip them.  */
       if (sh->iss == 0)
@@ -1215,8 +1292,13 @@ parse_symbol (sh, ax, ext_sh, bigend)
         generates a cross referencing stTypedef for x and xx.
         The user visible effect of this is that the type of a pointer
         to struct foo sometimes is given as `foo *' instead of `struct foo *'.
-        The problem is fixed with alpha cc.  */
+        The problem is fixed with alpha cc and Irix5 cc.  */
 
+      /* However if the typedef cross references to an opaque aggregate, it
+        is safe to omit it from the symbol table.  */
+
+      if (has_opaque_xref (cur_fdr, sh))
+       break;
       s = new_symbol (name);
       SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
       SYMBOL_CLASS (s) = LOC_TYPEDEF;
@@ -1312,8 +1394,8 @@ parse_type (fd, ax, aux_index, bs, bigend, sym_name)
     0,                         /* btTypedef */
     0,                         /* btRange */
     0,                         /* btSet */
-    &mdebug_type_complex,      /* btComplex */
-    &mdebug_type_double_complex,       /* btDComplex */
+    &builtin_type_complex,     /* btComplex */
+    &builtin_type_double_complex,/* btDComplex */
     0,                         /* btIndirect */
     &mdebug_type_fixed_dec,    /* btFixedDec */
     &mdebug_type_float_dec,    /* btFloatDec */
@@ -1337,6 +1419,10 @@ parse_type (fd, ax, aux_index, bs, bigend, sym_name)
   struct type *tp = 0;
   enum type_code type_code = TYPE_CODE_UNDEF;
 
+  /* Handle undefined types, they have indexNil. */
+  if (aux_index == indexNil)
+    return builtin_type_int;
+
   /* Handle corrupt aux indices.  */
   if (aux_index >= (debug_info->fdr + fd)->caux)
     {
@@ -1346,7 +1432,7 @@ parse_type (fd, ax, aux_index, bs, bigend, sym_name)
   ax += aux_index;
 
   /* Use aux as a type information record, map its basic type.  */
-  ecoff_swap_tir_in (bigend, &ax->a_ti, t);
+  (*debug_swap->swap_tir_in) (bigend, &ax->a_ti, t);
   if (t->bt >= (sizeof (map_bt) / sizeof (*map_bt)))
     {
       complain (&basic_type_complaint, t->bt, sym_name);
@@ -1425,6 +1511,12 @@ parse_type (fd, ax, aux_index, bs, bigend, sym_name)
       if (tp == (struct type *) NULL)
        tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
 
+      /* DEC c89 produces cross references to qualified aggregate types,
+        dereference them.  */
+      while (TYPE_CODE (tp) == TYPE_CODE_PTR
+            || TYPE_CODE (tp) == TYPE_CODE_ARRAY)
+       tp = tp->target_type;
+
       /* Make sure that TYPE_CODE(tp) has an expected type code.
         Any type may be returned from cross_ref if file indirect entries
         are corrupted.  */
@@ -1553,7 +1645,7 @@ parse_type (fd, ax, aux_index, bs, bigend, sym_name)
       if (!t->continued)
        break;
 
-      ecoff_swap_tir_in (bigend, &ax->a_ti, t);
+      (*debug_swap->swap_tir_in) (bigend, &ax->a_ti, t);
       ax++;
     }
 
@@ -1607,7 +1699,7 @@ upgrade_type (fd, tpp, tq, ax, bigend, sym_name)
       off = 0;
 
       /* Determine and record the domain type (type of index) */
-      ecoff_swap_rndx_in (bigend, &ax->a_rndx, &rndx);
+      (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, &rndx);
       id = rndx.index;
       rf = rndx.rfd;
       if (rf == 0xfff)
@@ -1685,13 +1777,15 @@ upgrade_type (fd, tpp, tq, ax, bigend, sym_name)
    to look for the function which contains the MIPS_EFI_SYMBOL_NAME symbol
    in question, or NULL to use top_stack->cur_block.  */
 
-static void parse_procedure PARAMS ((PDR *, struct symtab *, unsigned long));
+static void parse_procedure PARAMS ((PDR *, struct symtab *, unsigned long,
+                                    struct partial_symtab *));
 
 static void
-parse_procedure (pr, search_symtab, first_off)
+parse_procedure (pr, search_symtab, first_off, pst)
      PDR *pr;
      struct symtab *search_symtab;
      unsigned long first_off;
+     struct partial_symtab *pst;
 {
   struct symbol *s, *i;
   struct block *b;
@@ -1704,6 +1798,7 @@ parse_procedure (pr, search_symtab, first_off)
       if (pr->isym == -1)
        {
          /* Static procedure at address pr->adr.  Sigh. */
+         /* FIXME-32x64.  assuming pr->adr fits in long.  */
          complain (&pdr_static_symbol_complaint, (unsigned long) pr->adr);
          return;
        }
@@ -1795,7 +1890,7 @@ parse_procedure (pr, search_symtab, first_off)
       e = (struct mips_extra_func_info *) SYMBOL_VALUE (i);
       e->pdr = *pr;
       e->pdr.isym = (long) s;
-      e->pdr.adr += cur_fdr->adr - first_off;
+      e->pdr.adr += pst->textlow - first_off;
 
       /* Correct incorrect setjmp procedure descriptor from the library
         to make backtrace through setjmp work.  */
@@ -1806,31 +1901,56 @@ parse_procedure (pr, search_symtab, first_off)
          e->pdr.regmask = 0x80000000;
          e->pdr.regoffset = -4;
        }
-
-      /* Fake PC_REGNUM for alpha __sigtramp so that read_next_frame_reg
-        will use the saved user pc from the sigcontext.  */
-      if (STREQ (sh_name, "__sigtramp"))
-       e->pdr.pcreg = PC_REGNUM;
-      /* Make the same patch for Irix.  */
-      if (STREQ (sh_name, "_sigtramp"))
-       e->pdr.pcreg = PC_REGNUM;
     }
+
+  /* It would be reasonable that functions that have been compiled
+     without debugging info have a btNil type for their return value,
+     and functions that are void and are compiled with debugging info
+     have btVoid.
+     gcc and DEC f77 put out btNil types for both cases, so btNil is mapped
+     to TYPE_CODE_VOID in parse_type to get the `compiled with debugging info'
+     case right.
+     The glevel field in cur_fdr could be used to determine the presence
+     of debugging info, but GCC doesn't always pass the -g switch settings
+     to the assembler and GAS doesn't set the glevel field from the -g switch
+     settings.
+     To work around these problems, the return value type of a TYPE_CODE_VOID
+     function is adjusted accordingly if no debugging info was found in the
+     compilation unit.  */
+  if (processing_gcc_compilation == 0
+      && found_ecoff_debugging_info == 0
+      && TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (s))) == TYPE_CODE_VOID)
+    SYMBOL_TYPE (s) = nodebug_func_symbol_type;
+}
+
+/* Relocate the extra function info pointed to by the symbol table.  */
+
+void
+ecoff_relocate_efi (sym, delta)
+     struct symbol *sym;
+     CORE_ADDR delta;
+{
+  struct mips_extra_func_info *e;
+
+  e = (struct mips_extra_func_info *) SYMBOL_VALUE (sym);
+  
+  e->pdr.adr += delta;
 }
 
 /* Parse the external symbol ES. Just call parse_symbol() after
-   making sure we know where the aux are for it. For procedures,
-   parsing of the PDRs has already provided all the needed
-   information, we only parse them if SKIP_PROCEDURES is false,
-   and only if this causes no symbol duplication.
+   making sure we know where the aux are for it.
    BIGEND says whether aux entries are big-endian or little-endian.
 
    This routine clobbers top_stack->cur_block and ->cur_st. */
 
+static void parse_external PARAMS ((EXTR *, int, struct section_offsets *));
+
 static void
-parse_external (es, skip_procedures, bigend)
+parse_external (es, bigend, section_offsets)
      EXTR *es;
-     int skip_procedures;
      int bigend;
+     struct section_offsets *section_offsets;
 {
   union aux_ext *ax;
 
@@ -1885,19 +2005,27 @@ parse_external (es, skip_procedures, bigend)
   switch (es->asym.st)
     {
     case stProc:
-      /* If we have full symbols we do not need more */
-      if (skip_procedures)
-       return;
-      if (mylookup_symbol (debug_info->ssext + es->asym.iss,
-                          top_stack->cur_block,
-                          VAR_NAMESPACE, LOC_BLOCK))
-       break;
-      /* fall through */
+    case stStaticProc:
+      /* There is no need to parse the external procedure symbols.
+        If they are from objects compiled without -g, their index will
+        be indexNil, and the symbol definition from the minimal symbol
+        is preferrable (yielding a function returning int instead of int).
+        If the index points to a local procedure symbol, the local
+        symbol already provides the correct type.
+        Note that the index of the external procedure symbol points
+        to the local procedure symbol in the local symbol table, and
+        _not_ to the auxiliary symbol info.  */
+      break;
     case stGlobal:
     case stLabel:
+      /* Global common symbols are resolved by the runtime loader,
+        ignore them.  */
+      if (es->asym.sc == scCommon || es->asym.sc == scSCommon)
+       break;
+
       /* Note that the case of a symbol with indexNil must be handled
         anyways by parse_symbol().  */
-      parse_symbol (&es->asym, ax, (char *) NULL, bigend);
+      parse_symbol (&es->asym, ax, (char *) NULL, bigend, section_offsets);
       break;
     default:
       break;
@@ -1910,12 +2038,16 @@ parse_external (es, skip_procedures, bigend)
    numbers can go back and forth, apparently we can live
    with that and do not need to reorder our linetables */
 
+static void parse_lines PARAMS ((FDR *, PDR *, struct linetable *, int,
+                                struct partial_symtab *));
+
 static void
-parse_lines (fh, pr, lt, maxlines)
+parse_lines (fh, pr, lt, maxlines, pst)
      FDR *fh;
      PDR *pr;
      struct linetable *lt;
      int maxlines;
+     struct partial_symtab *pst;
 {
   unsigned char *base;
   int j, k;
@@ -1925,8 +2057,6 @@ parse_lines (fh, pr, lt, maxlines)
   if (fh->cbLine == 0)
     return;
 
-  base = debug_info->line + fh->cbLineOffset;
-
   /* Scan by procedure descriptors */
   k = 0;
   for (j = 0; j < fh->cpd; j++, pr++)
@@ -1949,7 +2079,8 @@ parse_lines (fh, pr, lt, maxlines)
        halt = base + fh->cbLine;
       base += pr->cbLineOffset;
 
-      adr = fh->adr + pr->adr - first_off;
+      adr = pst->textlow + pr->adr - first_off;
+
       l = adr >> 2;            /* in words */
       for (lineno = pr->lnLow; base < halt; )
        {
@@ -2022,6 +2153,19 @@ parse_partial_symbols (objfile, section_offsets)
   struct cleanup *old_chain;
   char *name;
   enum language prev_language;
+  asection *text_sect;
+  int relocatable = 0;
+
+  /* Irix 5.2 shared libraries have a fh->adr field of zero, but
+     the shared libraries are prelinked at a high memory address.
+     We have to adjust the start address of the object file for this case,
+     by setting it to the start address of the first procedure in the file.
+     But we should do no adjustments if we are debugging a .o file, where
+     the text section (and fh->adr) really starts at zero.  */
+  text_sect = bfd_get_section_by_name (cur_bfd, ".text");
+  if (text_sect != NULL
+      && (bfd_get_section_flags (cur_bfd, text_sect) & SEC_RELOC))
+    relocatable = 1;
 
   extern_tab = (EXTR *) obstack_alloc (&objfile->psymbol_obstack,
                                       sizeof (EXTR) * hdr->iextMax);
@@ -2059,7 +2203,7 @@ parse_partial_symbols (objfile, section_offsets)
   old_chain = make_cleanup (free, fdr_to_pst);
   fdr_to_pst++;
   {
-    struct partial_symtab *pst = new_psymtab ("", objfile);
+    struct partial_symtab *pst = new_psymtab ("", objfile, section_offsets);
     fdr_to_pst[-1].pst = pst;
     FDR_IDX (pst) = -1;
   }
@@ -2110,6 +2254,7 @@ parse_partial_symbols (objfile, section_offsets)
   for (; ext_in < ext_in_end; ext_in++)
     {
       enum minimal_symbol_type ms_type = mst_text;
+      CORE_ADDR svalue = ext_in->asym.value;
 
       /* The Irix 5 native tools seem to sometimes generate bogus
         external symbols.  */
@@ -2135,29 +2280,58 @@ parse_partial_symbols (objfile, section_offsets)
       switch (ext_in->asym.st)
        {
        case stProc:
+         svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
          break;
        case stStaticProc:
          ms_type = mst_file_text;
+         svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
          break;
        case stGlobal:
-          if (ext_in->asym.sc == scData
+          if (ext_in->asym.sc == scCommon || ext_in->asym.sc == scSCommon)
+           {
+             /* The value of a common symbol is its size, not its address.
+                Ignore it.  */
+             continue;
+           }
+          else if (ext_in->asym.sc == scData
              || ext_in->asym.sc == scSData
-             || ext_in->asym.sc == scRData)
-           ms_type = mst_data;
+             || ext_in->asym.sc == scRData
+             || ext_in->asym.sc == scPData
+             || ext_in->asym.sc == scXData)
+           {
+             ms_type = mst_data;
+             svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+           }
          else
-           ms_type = mst_bss;
+           {
+             ms_type = mst_bss;
+             svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+           }
          break;
        case stLabel:
           if (ext_in->asym.sc == scAbs)
            ms_type = mst_abs;
-          else if (ext_in->asym.sc == scText)
-           ms_type = mst_text;
+          else if (ext_in->asym.sc == scText
+                  || ext_in->asym.sc == scInit
+                  || ext_in->asym.sc == scFini)
+           {
+             ms_type = mst_file_text;
+             svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+           }
           else if (ext_in->asym.sc == scData
                   || ext_in->asym.sc == scSData
-                  || ext_in->asym.sc == scRData)
-           ms_type = mst_data;
+                  || ext_in->asym.sc == scRData
+                  || ext_in->asym.sc == scPData
+                  || ext_in->asym.sc == scXData)
+           {
+             ms_type = mst_file_data;
+             svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+           }
          else
-           ms_type = mst_bss;
+           {
+             ms_type = mst_file_bss;
+             svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+           }
          break;
        case stLocal:
          /* The alpha has the section start addresses in stLocal symbols
@@ -2170,7 +2344,7 @@ parse_partial_symbols (objfile, section_offsets)
          ms_type = mst_unknown;
          complain (&unknown_ext_complaint, name);
        }
-      prim_record_minimal_symbol (name, ext_in->asym.value, ms_type, objfile);
+      prim_record_minimal_symbol (name, svalue, ms_type, objfile);
     }
 
   /* Pass 3 over files, over local syms: fill in static symbols */
@@ -2178,6 +2352,7 @@ parse_partial_symbols (objfile, section_offsets)
     {
       struct partial_symtab *save_pst;
       EXTR *ext_ptr;
+      CORE_ADDR textlow;
 
       cur_fdr = fh = debug_info->fdr + f_idx;
 
@@ -2186,9 +2361,20 @@ parse_partial_symbols (objfile, section_offsets)
          fdr_to_pst[f_idx].pst = NULL;
          continue;
        }
+
+      /* Determine the start address for this object file from the
+        file header and relocate it, except for Irix 5.2 zero fh->adr.  */
+      if (fh->cpd)
+       {
+         textlow = fh->adr;
+         if (relocatable || textlow != 0)
+           textlow += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+       }
+      else
+       textlow = 0;
       pst = start_psymtab_common (objfile, section_offsets,
                                  fdr_name (fh),
-                                 fh->cpd ? fh->adr : 0,
+                                 textlow,
                                  objfile->global_psymbols.next,
                                  objfile->static_psymbols.next);
       pst->read_symtab_private = ((char *)
@@ -2267,9 +2453,21 @@ parse_partial_symbols (objfile, section_offsets)
                {
                  if (sh.st == stProc || sh.st == stStaticProc)
                    {
-                     long procaddr = sh.value;
+                     long procaddr;
                      long isym;
-
+       
+                     sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+                     if (sh.st == stStaticProc)
+                       {
+                         namestring = debug_info->ss + fh->issBase + sh.iss;
+                         prim_record_minimal_symbol_and_info (namestring,
+                                                              sh.value,
+                                                              mst_file_text,
+                                                              NULL,
+                                                              SECT_OFF_TEXT,
+                                                              objfile);
+                       }
+                     procaddr = sh.value;
 
                      isym = AUX_GET_ISYM (fh->fBigendian,
                                           (debug_info->external_aux
@@ -2283,10 +2481,51 @@ parse_partial_symbols (objfile, section_offsets)
                      if (sh.st == stEnd)
                        {
                          long high = procaddr + sh.value;
+
+                         /* Kludge for Irix 5.2 zero fh->adr.  */
+                         if (!relocatable
+                             && (pst->textlow == 0 || procaddr < pst->textlow))
+                           pst->textlow = procaddr;
                          if (high > pst->texthigh)
                            pst->texthigh = high;
                        }
                    }
+                 else if (sh.st == stStatic)
+                   {
+                     switch (sh.sc)
+                       {
+                       case scUndefined:
+                       case scNil:
+                       case scAbs:
+                         break;
+
+                       case scData:
+                       case scSData:
+                       case scRData:
+                       case scPData:
+                       case scXData:
+                         namestring = debug_info->ss + fh->issBase + sh.iss;
+                         sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+                         prim_record_minimal_symbol_and_info (namestring,
+                                                              sh.value,
+                                                              mst_file_data,
+                                                              NULL,
+                                                              SECT_OFF_DATA,
+                                                              objfile);
+                         break;
+
+                       default:
+                         namestring = debug_info->ss + fh->issBase + sh.iss;
+                         sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+                         prim_record_minimal_symbol_and_info (namestring,
+                                                              sh.value,
+                                                              mst_file_bss,
+                                                              NULL,
+                                                              SECT_OFF_BSS,
+                                                              objfile);
+                         break;
+                       }
+                   }
                  continue;
                }
 #define SET_NAMESTRING() \
@@ -2332,25 +2571,63 @@ parse_partial_symbols (objfile, section_offsets)
 
              name = debug_info->ss + fh->issBase + sh.iss;
 
+             switch (sh.sc)
+               {
+               case scText:
+                 /* The value of a stEnd symbol is the displacement from the
+                    corresponding start symbol value, do not relocate it.  */
+                 if (sh.st != stEnd)
+                   sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+                 break;
+               case scData:
+               case scSData:
+               case scRData:
+               case scPData:
+               case scXData:
+                 sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+                 break;
+               case scBss:
+               case scSBss:
+                 sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+                 break;
+               }
+
              switch (sh.st)
                {
                  long high;
                  long procaddr;
                  int new_sdx;
 
-               case stStaticProc:      /* Function */
-                 /* I believe this is used only for file-local functions.
-                    The comment in symconst.h ("load time only static procs")
-                    isn't particularly clear on this point.  */
-                 prim_record_minimal_symbol (name, sh.value, mst_file_text,
-                                             objfile);
+               case stStaticProc:
+                 prim_record_minimal_symbol_and_info (name, sh.value,
+                                                      mst_file_text, NULL,
+                                                      SECT_OFF_TEXT, objfile);
+
                  /* FALLTHROUGH */
 
-               case stProc:    /* Asm labels apparently */
-                 ADD_PSYMBOL_TO_LIST (name, strlen (name),
-                                      VAR_NAMESPACE, LOC_BLOCK,
-                                      objfile->static_psymbols, sh.value,
-                                      psymtab_language, objfile);
+               case stProc:
+                 /* Usually there is a local and a global stProc symbol
+                    for a function. This means that the function name
+                    has already been entered into the mimimal symbol table
+                    while processing the global symbols in pass 2 above.
+                    One notable exception is the PROGRAM name from
+                    f77 compiled executables, it is only put out as
+                    local stProc symbol, and a global MAIN__ stProc symbol
+                    points to it.  It doesn't matter though, as gdb is
+                    still able to find the PROGRAM name via the partial
+                    symbol table, and the MAIN__ symbol via the minimal
+                    symbol table.  */
+                 if (sh.st == stProc)
+                   ADD_PSYMBOL_TO_LIST (name, strlen (name),
+                                        VAR_NAMESPACE, LOC_BLOCK,
+                                        objfile->global_psymbols,
+                                        sh.value, psymtab_language, objfile);
+                 else
+                   ADD_PSYMBOL_TO_LIST (name, strlen (name),
+                                        VAR_NAMESPACE, LOC_BLOCK,
+                                        objfile->static_psymbols,
+                                        sh.value, psymtab_language, objfile);
+
                  /* Skip over procedure to next one. */
                  if (sh.index >= hdr->iauxMax)
                    {
@@ -2381,25 +2658,43 @@ parse_partial_symbols (objfile, section_offsets)
                                  &sh);
                  if (sh.st != stEnd)
                    continue;
+
+                 /* Kludge for Irix 5.2 zero fh->adr.  */
+                 if (!relocatable
+                     && (pst->textlow == 0 || procaddr < pst->textlow))
+                   pst->textlow = procaddr;
+
                  high = procaddr + sh.value;
                  if (high > pst->texthigh)
                    pst->texthigh = high;
                  continue;
 
                case stStatic:  /* Variable */
-                 if (sh.sc == scData || sh.sc == scSData || sh.sc == scRData)
-                   prim_record_minimal_symbol (name, sh.value, mst_file_data,
-                                               objfile);
+                 if (sh.sc == scData
+                     || sh.sc == scSData
+                     || sh.sc == scRData
+                     || sh.sc == scPData
+                     || sh.sc == scXData)
+                   prim_record_minimal_symbol_and_info (name, sh.value,
+                                                        mst_file_data, NULL,
+                                                        SECT_OFF_DATA,
+                                                        objfile);
                  else
-                   prim_record_minimal_symbol (name, sh.value, mst_file_bss,
-                                               objfile);
+                   prim_record_minimal_symbol_and_info (name, sh.value,
+                                                        mst_file_bss, NULL,
+                                                        SECT_OFF_BSS,
+                                                        objfile);
                  class = LOC_STATIC;
                  break;
 
+               case stIndirect:/* Irix5 forward declaration */
+                 /* Skip forward declarations from Irix5 cc */
+                 goto skip;
+
                case stTypedef:/* Typedef */
                  /* Skip typedefs for forward declarations and opaque
-                    structs from alpha cc.  */
-                 if (sh.iss == 0)
+                    structs from alpha and mips cc.  */
+                 if (sh.iss == 0 || has_opaque_xref (fh, &sh))
                    goto skip;
                  class = LOC_TYPEDEF;
                  break;
@@ -2414,7 +2709,8 @@ parse_partial_symbols (objfile, section_offsets)
                case stBlock:   /* { }, str, un, enum*/
                  /* Do not create a partial symbol for cc unnamed aggregates
                     and gcc empty aggregates. */
-                 if ((sh.sc == scInfo || sh.sc == scCommon)
+                 if ((sh.sc == scInfo
+                      || sh.sc == scCommon || sh.sc == scSCommon)
                      && sh.iss != 0
                      && sh.index != cur_sdx + 2)
                    {
@@ -2424,6 +2720,8 @@ parse_partial_symbols (objfile, section_offsets)
                                           sh.value,
                                           psymtab_language, objfile);
                    }
+                 handle_psymbol_enumerators (objfile, fh, sh.st);
+
                  /* Skip over the block */
                  new_sdx = sh.index;
                  if (new_sdx <= cur_sdx)
@@ -2473,6 +2771,7 @@ parse_partial_symbols (objfile, section_offsets)
              enum address_class class;
              SYMR *psh;
              char *name;
+             CORE_ADDR svalue;
 
              if (ext_ptr->ifd != f_idx)
                abort ();
@@ -2482,6 +2781,25 @@ parse_partial_symbols (objfile, section_offsets)
              if (psh->sc == scUndefined || psh->sc == scNil)
                continue;
 
+             svalue = psh->value;
+             switch (psh->sc)
+               {
+               case scText:
+                 svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+                 break;
+               case scData:
+               case scSData:
+               case scRData:
+               case scPData:
+               case scXData:
+                 svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+                 break;
+               case scBss:
+               case scSBss:
+                 svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+                 break;
+               }
+
              switch (psh->st)
                {
                case stNil:
@@ -2490,8 +2808,10 @@ parse_partial_symbols (objfile, section_offsets)
                  continue;
                case stProc:
                case stStaticProc:
-                 class = LOC_BLOCK;
-                 break;
+                 /* External procedure symbols have been entered
+                    into the minimal symbol table in pass 2 above.
+                    Ignore them, as parse_external will ignore them too.  */
+                 continue;
                case stLabel:
                  class = LOC_LABEL;
                  break;
@@ -2500,6 +2820,11 @@ parse_partial_symbols (objfile, section_offsets)
                            debug_info->ssext + psh->iss);
                  /* Fall through, pretend it's global.  */
                case stGlobal:
+                 /* Global common symbols are resolved by the runtime loader,
+                    ignore them.  */
+                 if (psh->sc == scCommon || psh->sc == scSCommon)
+                   continue;
+
                  class = LOC_STATIC;
                  break;
                }
@@ -2507,7 +2832,7 @@ parse_partial_symbols (objfile, section_offsets)
              ADD_PSYMBOL_ADDR_TO_LIST (name, strlen (name),
                                        VAR_NAMESPACE, class,
                                        objfile->global_psymbols,
-                                       (CORE_ADDR) psh->value,
+                                       svalue,
                                        psymtab_language, objfile);
            }
        }
@@ -2524,6 +2849,35 @@ parse_partial_symbols (objfile, section_offsets)
          objfile->ei.entry_file_lowpc = save_pst->textlow;
          objfile->ei.entry_file_highpc = save_pst->texthigh;
        }
+
+      /* The objfile has its functions reordered if this partial symbol
+        table overlaps any other partial symbol table.
+        We cannot assume a reordered objfile if a partial symbol table
+        is contained within another partial symbol table, as partial symbol
+        tables for include files with executable code are contained
+        within the partial symbol table for the including source file,
+        and we do not want to flag the objfile reordered for these cases.
+
+        This strategy works well for Irix-5.2 shared libraries, but we
+        might have to use a more elaborate (and slower) algorithm for
+        other cases.  */
+      save_pst = fdr_to_pst[f_idx].pst;
+      if (save_pst != NULL
+         && save_pst->textlow != 0
+         && !(objfile->flags & OBJF_REORDERED))
+       {
+         ALL_OBJFILE_PSYMTABS (objfile, pst)
+           {
+             if (save_pst != pst
+                 && save_pst->textlow >= pst->textlow
+                 && save_pst->textlow < pst->texthigh
+                 && save_pst->texthigh > pst->texthigh)
+               {
+                 objfile->flags |= OBJF_REORDERED;
+                 break;
+               }
+           }
+       }
     }
 
   /* Now scan the FDRs for dependencies */
@@ -2571,9 +2925,79 @@ parse_partial_symbols (objfile, section_offsets)
          pst->dependencies[pst->number_of_dependencies++] = fdr_to_pst[rh].pst;
        }
     }
+
+  /* Remove the dummy psymtab created for -O3 images above, if it is
+     still empty, to enable the detection of stripped executables.  */
+  if (objfile->psymtabs->next == NULL
+      && objfile->psymtabs->number_of_dependencies == 0
+      && objfile->psymtabs->n_global_syms == 0
+      && objfile->psymtabs->n_static_syms == 0)
+    objfile->psymtabs = NULL;
   do_cleanups (old_chain);
 }
 
+/* If the current psymbol has an enumerated type, we need to add
+   all the the enum constants to the partial symbol table.  */
+
+static void
+handle_psymbol_enumerators (objfile, fh, stype)
+     struct objfile *objfile;
+     FDR *fh;
+     int stype;
+{
+  const bfd_size_type external_sym_size = debug_swap->external_sym_size;
+  void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+    = debug_swap->swap_sym_in;
+  char *ext_sym = ((char *) debug_info->external_sym
+                 + ((fh->isymBase + cur_sdx + 1) * external_sym_size));
+  SYMR sh;
+  TIR tir;
+
+  switch (stype)
+    {
+    case stEnum:
+      break;
+
+    case stBlock:
+      /* It is an enumerated type if the next symbol entry is a stMember
+        and its auxiliary index is indexNil or its auxiliary entry
+        is a plain btNil or btVoid.  */
+      (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+      if (sh.st != stMember)
+       return;
+
+      if (sh.index == indexNil)
+       break;
+      (*debug_swap->swap_tir_in) (fh->fBigendian,
+                                 &(debug_info->external_aux
+                                   + fh->iauxBase + sh.index)->a_ti,
+                                 &tir);
+      if ((tir.bt != btNil && tir.bt != btVoid) || tir.tq0 != tqNil)
+       return;
+      break;
+
+    default:
+      return;
+    }
+
+  for (;;)
+    {
+      char *name;
+
+      (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+      if (sh.st != stMember)
+       break;
+      name = debug_info->ss + cur_fdr->issBase + sh.iss;
+
+      /* Note that the value doesn't matter for enum constants
+        in psymtabs, just in symtabs.  */
+      ADD_PSYMBOL_TO_LIST (name, strlen (name),
+                          VAR_NAMESPACE, LOC_CONST,
+                          objfile->static_psymbols, 0,
+                          psymtab_language, objfile);
+      ext_sym += external_sym_size;
+    }
+}
 
 static char *
 mdebug_next_symbol_text ()
@@ -2732,19 +3156,30 @@ psymtab_to_symtab_1 (pst, filename)
                     obstack_alloc (&current_objfile->symbol_obstack,
                                    sizeof (struct mips_extra_func_info)));
                  struct symbol *s = new_symbol (MIPS_EFI_SYMBOL_NAME);
+
+                 memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
                  SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
                  SYMBOL_CLASS (s) = LOC_CONST;
                  SYMBOL_TYPE (s) = builtin_type_void;
                  SYMBOL_VALUE (s) = (long) e;
+                 e->pdr.framereg = -1;
                  add_symbol_to_list (s, &local_symbols);
                }
            }
-         else if (sh.st == stLabel && sh.index != indexNil)
+         else if (sh.st == stLabel)
            {
-             /* Handle encoded stab line number. */
-             record_line (current_subfile, sh.index, valu);
+             if (sh.index == indexNil)
+               {
+                 /* This is what the gcc2_compiled and __gnu_compiled_*
+                    show up as.  So don't complain.  */
+                 ;
+               }
+             else
+               /* Handle encoded stab line number. */
+               record_line (current_subfile, sh.index, valu);
            }
-         else if (sh.st == stProc || sh.st == stStaticProc || sh.st == stEnd)
+         else if (sh.st == stProc || sh.st == stStaticProc
+                  || sh.st == stStatic || sh.st == stEnd)
            /* These are generated by gcc-2.x, do not complain */
            ;
          else
@@ -2757,8 +3192,11 @@ psymtab_to_symtab_1 (pst, filename)
         We must do this before parse_procedure calls lookup_symbol.  */
       sort_symtab_syms (st);
 
-      /* This may not be necessary for stabs symtabs.  FIXME.  */
-      sort_blocks (st);
+      /* There used to be a call to sort_blocks here, but this should not
+        be necessary for stabs symtabs.  And as sort_blocks modifies the
+        start address of the GLOBAL_BLOCK to the FIRST_LOCAL_BLOCK,
+        it did the wrong thing if the first procedure in a file was
+        generated via asm statements.  */
 
       /* Fill in procedure info next.  */
       first_pdr = 1;
@@ -2775,15 +3213,13 @@ psymtab_to_symtab_1 (pst, filename)
              first_off = pr.adr;
              first_pdr = 0;
            }
-         parse_procedure (&pr, st, first_off);
+         parse_procedure (&pr, st, first_off, pst);
        }
     }
   else
     {
       /* This symbol table contains ordinary ecoff entries.  */
 
-      /* FIXME:  doesn't use pst->section_offsets.  */
-
       int f_max;
       int maxlines;
       EXTR *ext_ptr;
@@ -2817,13 +3253,14 @@ psymtab_to_symtab_1 (pst, filename)
       top_stack->cur_st = st;
       top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (st),
                                                STATIC_BLOCK);
-      BLOCK_START (top_stack->cur_block) = fh ? fh->adr : 0;
+      BLOCK_START (top_stack->cur_block) = pst->textlow;
       BLOCK_END (top_stack->cur_block) = 0;
       top_stack->blocktype = stFile;
       top_stack->maxsyms = 2 * f_max;
       top_stack->cur_type = 0;
       top_stack->procadr = 0;
       top_stack->numargs = 0;
+      found_ecoff_debugging_info = 0;
 
       if (fh)
        {
@@ -2842,7 +3279,7 @@ psymtab_to_symtab_1 (pst, filename)
              (*swap_sym_in) (cur_bfd, sym_ptr, &sh);
              c = parse_symbol (&sh,
                                debug_info->external_aux + fh->iauxBase,
-                               sym_ptr, fh->fBigendian);
+                               sym_ptr, fh->fBigendian, pst->section_offsets);
              sym_ptr += c * external_sym_size;
            }
 
@@ -2871,7 +3308,7 @@ psymtab_to_symtab_1 (pst, filename)
                   pdr_ptr += external_pdr_size, pdr_in++)
                (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in);
 
-             parse_lines (fh, pr_block, lines, maxlines);
+             parse_lines (fh, pr_block, lines, maxlines, pst);
              if (lines->nitems < fh->cline)
                lines = shrink_linetable (lines);
 
@@ -2879,7 +3316,7 @@ psymtab_to_symtab_1 (pst, filename)
              pdr_in = pr_block;
              pdr_in_end = pdr_in + fh->cpd;
              for (; pdr_in < pdr_in_end; pdr_in++)
-               parse_procedure (pdr_in, 0, pr_block->adr);
+               parse_procedure (pdr_in, 0, pr_block->adr, pst);
 
              do_cleanups (old_chain);
            }
@@ -2901,7 +3338,7 @@ psymtab_to_symtab_1 (pst, filename)
 
       ext_ptr = PST_PRIVATE (pst)->extern_tab;
       for (i = PST_PRIVATE (pst)->extern_count; --i >= 0; ext_ptr++)
-       parse_external (ext_ptr, 1, fh->fBigendian);
+       parse_external (ext_ptr, fh->fBigendian, pst->section_offsets);
 
       /* If there are undefined symbols, tell the user.
         The alpha has an undefined symbol for every symbol that is
@@ -2917,6 +3354,8 @@ psymtab_to_symtab_1 (pst, filename)
        }
       pop_parse_stack ();
 
+      st->primary = 1;
+
       /* Sort the symbol table now, we are done adding symbols to it.*/
       sort_symtab_syms (st);
 
@@ -2931,6 +3370,38 @@ psymtab_to_symtab_1 (pst, filename)
 \f
 /* Ancillary parsing procedures. */
 
+/* Return 1 if the symbol pointed to by SH has a cross reference
+   to an opaque aggregate type, else 0.  */
+
+static int
+has_opaque_xref (fh, sh)
+     FDR *fh;
+     SYMR *sh;
+{
+  TIR tir;
+  union aux_ext *ax;
+  RNDXR rn[1];
+  unsigned int rf;
+
+  if (sh->index == indexNil)
+    return 0;
+
+  ax = debug_info->external_aux + fh->iauxBase + sh->index;
+  (*debug_swap->swap_tir_in) (fh->fBigendian, &ax->a_ti, &tir);
+  if (tir.bt != btStruct && tir.bt != btUnion && tir.bt != btEnum)
+    return 0;
+
+  ax++;
+  (*debug_swap->swap_rndx_in) (fh->fBigendian, &ax->a_rndx, rn);
+  if (rn->rfd == 0xfff)
+    rf = AUX_GET_ISYM (fh->fBigendian, ax + 1);
+  else
+    rf = rn->rfd;
+  if (rf != -1)
+    return 0;
+  return 1;
+}
+
 /* Lookup the type at relative index RN.  Return it in TPP
    if found and in any event come up with its name PNAME.
    BIGEND says whether aux symbols are big-endian or not (from fh->fBigendian).
@@ -2957,7 +3428,7 @@ cross_ref (fd, ax, tpp, type_code, pname, bigend, sym_name)
 
   *tpp = (struct type *)NULL;
 
-  ecoff_swap_rndx_in (bigend, &ax->a_rndx, rn);
+  (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn);
 
   /* Escape index means 'the next one' */
   if (rn->rfd == 0xfff)
@@ -3015,10 +3486,11 @@ cross_ref (fd, ax, tpp, type_code, pname, bigend, sym_name)
   (*debug_swap->swap_sym_in) (cur_bfd, esh, &sh);
 
   /* Make sure that this type of cross reference can be handled.  */
-  if (sh.sc != scInfo
-      || (sh.st != stBlock && sh.st != stTypedef
-         && sh.st != stStruct && sh.st != stUnion
-         && sh.st != stEnum))
+  if ((sh.sc != scInfo
+       || (sh.st != stBlock && sh.st != stTypedef && sh.st != stIndirect
+          && sh.st != stStruct && sh.st != stUnion
+          && sh.st != stEnum))
+      && (sh.st != stBlock || (sh.sc != scCommon && sh.sc != scSCommon)))
     {
       /* File indirect entry is corrupt.  */
       *pname = "<illegal>";
@@ -3036,7 +3508,7 @@ cross_ref (fd, ax, tpp, type_code, pname, bigend, sym_name)
     {
       /* We have not yet seen this type.  */
 
-      if (sh.iss == 0 && sh.st == stTypedef)
+      if ((sh.iss == 0 && sh.st == stTypedef) || sh.st == stIndirect)
        {
          TIR tir;
 
@@ -3049,15 +3521,15 @@ cross_ref (fd, ax, tpp, type_code, pname, bigend, sym_name)
                due to the missing name.
             b) forward declarations of structs/unions/enums which are defined
                later in this file or in another file in the same compilation
-               unit.  Simply cross reference those again to get the
-               true type.
+               unit. Irix5 cc uses a stIndirect symbol for this.
+               Simply cross reference those again to get the true type.
             The forward references are not entered in the pending list and
             in the symbol table.  */
 
-         ecoff_swap_tir_in (bigend,
-                            &(debug_info->external_aux
-                              + fh->iauxBase + sh.index)->a_ti,
-                            &tir);
+         (*debug_swap->swap_tir_in) (bigend,
+                                     &(debug_info->external_aux
+                                       + fh->iauxBase + sh.index)->a_ti,
+                                     &tir);
          if (tir.tq0 != tqNil)
            complain (&illegal_forward_tq0_complaint, sym_name);
          switch (tir.bt)
@@ -3347,13 +3819,15 @@ new_symtab (name, maxsyms, maxlines, objfile)
 /* Allocate a new partial_symtab NAME */
 
 static struct partial_symtab *
-new_psymtab (name, objfile)
+new_psymtab (name, objfile, section_offsets)
      char *name;
      struct objfile *objfile;
+     struct section_offsets *section_offsets;
 {
   struct partial_symtab *psymtab;
 
   psymtab = allocate_psymtab (name, objfile);
+  psymtab->section_offsets = section_offsets;
 
   /* Keep a backpointer to the file's symbols */
 
@@ -3508,62 +3982,15 @@ elfmdebug_build_psymtabs (objfile, swap, sec, section_offsets)
      struct section_offsets *section_offsets;
 {
   bfd *abfd = objfile->obfd;
-  char *buf;
   struct ecoff_debug_info *info;
 
-  buf = alloca (swap->external_hdr_size);
-  if (bfd_get_section_contents (abfd, sec, buf, (file_ptr) 0,
-                               swap->external_hdr_size) == false)
-    perror_with_name (bfd_get_filename (abfd));
-
   info = ((struct ecoff_debug_info *)
          obstack_alloc (&objfile->psymbol_obstack,
                         sizeof (struct ecoff_debug_info)));
 
-  (*swap->swap_hdr_in) (abfd, buf, &info->symbolic_header);
-
-  /* The offsets in symbolic_header are file offsets, not section
-     offsets.  Strangely, on Irix 5 the information is not entirely
-     within the .mdebug section.  There are parts of an executable
-     file which are not within any ELF section at all.  This means
-     that we must read the information using bfd_read. */
-
-#define READ(ptr, count, off, size, type)                              \
-  do                                                                   \
-    {                                                                  \
-      if (info->symbolic_header.count == 0)                            \
-       info->ptr = (type) NULL;                                        \
-      else                                                             \
-       {                                                               \
-         info->ptr = ((type)                                           \
-                      obstack_alloc (&objfile->psymbol_obstack,        \
-                                     (info->symbolic_header.count      \
-                                      * size)));                       \
-         if (bfd_seek (abfd, info->symbolic_header.off, SEEK_SET) < 0  \
-             || (bfd_read ((PTR) info->ptr, size,                      \
-                           info->symbolic_header.count, abfd)          \
-                 != info->symbolic_header.count * size))               \
-           perror_with_name (bfd_get_filename (abfd));                 \
-       }                                                               \
-    }                                                                  \
-  while (0)
-
-  READ (line, cbLine, cbLineOffset, sizeof (unsigned char), unsigned char *);
-  READ (external_dnr, idnMax, cbDnOffset, swap->external_dnr_size, PTR);
-  READ (external_pdr, ipdMax, cbPdOffset, swap->external_pdr_size, PTR);
-  READ (external_sym, isymMax, cbSymOffset, swap->external_sym_size, PTR);
-  READ (external_opt, ioptMax, cbOptOffset, swap->external_opt_size, PTR);
-  READ (external_aux, iauxMax, cbAuxOffset, sizeof (union aux_ext),
-       union aux_ext *);
-  READ (ss, issMax, cbSsOffset, sizeof (char), char *);
-  READ (ssext, issExtMax, cbSsExtOffset, sizeof (char), char *);
-  READ (external_fdr, ifdMax, cbFdOffset, swap->external_fdr_size, PTR);
-  READ (external_rfd, crfd, cbRfdOffset, swap->external_rfd_size, PTR);
-  READ (external_ext, iextMax, cbExtOffset, swap->external_ext_size, PTR);
-
-#undef READ
-
-  info->fdr = NULL;
+  if (!(*swap->read_debug_info) (abfd, sec, info))
+    error ("Error reading ECOFF debugging information: %s",
+          bfd_errmsg (bfd_get_error ()));
 
   mdebug_build_psymtabs (objfile, swap, info, section_offsets);
 }
@@ -3653,15 +4080,21 @@ fixup_sigtramp ()
        xzalloc (sizeof (struct mips_extra_func_info)));
 
     e->numargs = 0;            /* the kernel thinks otherwise */
-    /* align_longword(sigcontext + SIGFRAME) */
-    e->pdr.frameoffset = 0x150;
+    e->pdr.frameoffset = 32;
     e->pdr.framereg = SP_REGNUM;
-    /* read_next_frame_reg provides the true pc at the time of signal */
+    /* Note that setting pcreg is no longer strictly necessary as
+       mips_frame_saved_pc is now aware of signal handler frames.  */
     e->pdr.pcreg = PC_REGNUM;
     e->pdr.regmask = -2;
-    e->pdr.regoffset = -(41 * sizeof (int));
+    /* Offset to saved r31, in the sigtramp case the saved registers
+       are above the frame in the sigcontext.
+       We have 4 alignment bytes, 12 bytes for onstack, mask and pc,
+       32 * 4 bytes for the general registers, 12 bytes for mdhi, mdlo, ownedfp
+       and 32 * 4 bytes for the floating point registers.  */
+    e->pdr.regoffset = 4 + 12 + 31 * 4;
     e->pdr.fregmask = -1;
-    e->pdr.fregoffset = -(7 * sizeof (int));
+    /* Offset to saved f30 (first saved *double* register).  */
+    e->pdr.fregoffset = 4 + 12 + 32 * 4 + 12 + 30 * 4;
     e->pdr.isym = (long) s;
     e->pdr.adr = sigtramp_address;
 
@@ -3690,17 +4123,6 @@ _initialize_mdebugread ()
               0, "string",
               (struct objfile *) NULL);
 
-  mdebug_type_complex =
-    init_type (TYPE_CODE_ERROR,
-              TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
-              0, "complex",
-              (struct objfile *) NULL);
-  mdebug_type_double_complex =
-    init_type (TYPE_CODE_ERROR,
-              TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
-              0, "double complex",
-              (struct objfile *) NULL);
-
   /* We use TYPE_CODE_INT to print these as integers.  Does this do any
      good?  Would we be better off with TYPE_CODE_ERROR?  Should
      TYPE_CODE_ERROR print things in hex if it knows the size?  */
@@ -3715,4 +4137,11 @@ _initialize_mdebugread ()
               TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
               0, "floating decimal",
               (struct objfile *) NULL);
+
+  nodebug_func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0,
+                                       "<function, no debug info>", NULL);
+  TYPE_TARGET_TYPE (nodebug_func_symbol_type) = builtin_type_int;
+  nodebug_var_symbol_type =
+    init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+              "<variable, no debug info>", NULL);
 }
This page took 0.042193 seconds and 4 git commands to generate.