* mipsread.c (fixup_sigtramp): Initialize pdr.adr, it is used by
[binutils-gdb.git] / gdb / mipsread.c
index 4577339df76ce2f0acac5c306cf023e5bf9fec42..da6f071e0bbaf23d269e9d656f7a6bfe28ad8395 100644 (file)
@@ -45,9 +45,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    This module can read all four of the known byte-order combinations,
    on any type of host.  */
 
-#define        TM_FILE_OVERRIDE
 #include "defs.h"
-#include "mips/tm-mips.h"
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "gdbcore.h"
@@ -58,10 +56,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "stabsread.h"
 #include "complaints.h"
 
+/* These are needed if the tm.h file does not contain the necessary
+   mips specific definitions.  */
+
+#ifndef MIPS_EFI_SYMBOL_NAME
+#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
+#include "coff/sym.h"
+#include "coff/symconst.h"
+typedef struct mips_extra_func_info {
+        long    numargs;
+        PDR     pdr;
+} *mips_extra_func_info_t;
+#ifndef RA_REGNUM
+#define RA_REGNUM 0
+#endif
+#ifndef FP0_REGNUM
+#define FP0_REGNUM 0
+#endif
+#endif
+
 #ifdef USG
 #include <sys/types.h>
-#define L_SET 0
-#define L_INCR 1
 #endif
 
 #include <sys/param.h>
@@ -80,9 +95,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* FIXME: coff/internal.h and aout/aout64.h both define N_ABS.  We
    want the definition from aout/aout64.h.  */
 #undef N_ABS
-/* FIXME: coff/mips.h and aout/aout64.h both define ZMAGIC.  We don't
-   use it.  */
-#undef ZMAGIC
 
 #include "libaout.h"           /* Private BFD a.out information.  */
 #include "aout/aout64.h"
@@ -180,6 +192,9 @@ struct complaint pdr_for_nonsymbol_complaint =
 struct complaint pdr_static_symbol_complaint =
 {"can't handle PDR for static proc at 0x%x", 0, 0};
 
+struct complaint bad_setjmp_pdr_complaint =
+{"fixing bad setjmp PDR from libc", 0, 0};
+
 /* Macros and extra defs */
 
 /* Already-parsed symbols are marked specially */
@@ -330,6 +345,9 @@ static void
 mipscoff_new_init (ignore)
      struct objfile *ignore;
 {
+  sigtramp_address = 0;
+  stabsread_new_init ();
+  buildsym_new_init ();
 }
 
 static void
@@ -410,8 +428,6 @@ mipscoff_psymtab_to_symtab (pst)
       printf_filtered ("Reading in symbols for %s...", pst->filename);
       fflush (stdout);
     }
-  /* Get the BFD and list of pending typedefs */
-  cur_bfd = CUR_BFD (pst);
 
   next_symbol_text_func = mips_next_symbol_text;
 
@@ -655,33 +671,6 @@ free_pending (f_idx)
 
 #endif
 
-static char *
-prepend_tag_kind (tag_name, type_code)
-     char *tag_name;
-     enum type_code type_code;
-{
-  char *prefix;
-  char *result;
-  switch (type_code)
-    {
-    case TYPE_CODE_ENUM:
-      prefix = "enum ";
-      break;
-    case TYPE_CODE_STRUCT:
-      prefix = "struct ";
-      break;
-    case TYPE_CODE_UNION:
-      prefix = "union ";
-      break;
-    default:
-      prefix = "";
-    }
-
-  result = (char *) obstack_alloc (&current_objfile->symbol_obstack,
-                                  strlen (prefix) + strlen (tag_name) + 1);
-  sprintf (result, "%s%s", prefix, tag_name);
-  return result;
-}
 \f
 
 /* Parsing Routines proper. */
@@ -737,7 +726,17 @@ parse_symbol (sh, ax, ext_sh, bigend)
       class = LOC_STATIC;
       b = top_stack->cur_block;
       s = new_symbol (name);
-      SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value;
+      if (sh->sc == scCommon)
+       {
+         /* 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
+            scan_file_globals.  */
+         int bucket = hashname (SYMBOL_NAME (s));
+         SYMBOL_VALUE_CHAIN (s) = global_sym_chain[bucket];
+         global_sym_chain[bucket] = s;
+       }
+      else
+       SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value;
       goto data;
 
     case stLocal:              /* local variable, goes into current block */
@@ -777,14 +776,27 @@ parse_symbol (sh, ax, ext_sh, bigend)
       s = new_symbol (name);
 
       SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
-      if (sh->sc == scRegister)
+      switch (sh->sc)
        {
-         SYMBOL_CLASS (s) = LOC_REGPARM;
+       case scRegister:
+         /* Pass by value in register.  */
+         SYMBOL_CLASS(s) = LOC_REGPARM;
          if (sh->value > 31)
-           sh->value += FP0_REGNUM - 32;
+           sh->value += FP0_REGNUM-32;
+         break;
+       case scVar:
+         /* Pass by reference on stack.  */
+         SYMBOL_CLASS(s) = LOC_REF_ARG;
+         break;
+       case scVarRegister:
+         /* Pass by reference in register.  */
+         SYMBOL_CLASS(s) = LOC_REGPARM_ADDR;
+         break;
+       default:
+         /* Pass by value on stack.  */
+         SYMBOL_CLASS(s) = LOC_ARG;
+         break;
        }
-      else
-       SYMBOL_CLASS (s) = LOC_ARG;
       SYMBOL_VALUE (s) = sh->value;
       SYMBOL_TYPE (s) = parse_type (ax + sh->index, 0, bigend);
       add_symbol (s, top_stack->cur_block);
@@ -883,7 +895,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
        goto structured_common;
 
     case stBlock:              /* Either a lexical block, or some type */
-       if (sh->sc != scInfo)
+       if (sh->sc != scInfo && sh->sc != scCommon)
          goto case_stBlock_code;       /* Lexical block */
 
        type_code = TYPE_CODE_UNDEF;    /* We have a type.  */
@@ -1001,8 +1013,10 @@ parse_symbol (sh, ax, ext_sh, bigend)
        if (pend != (struct mips_pending *) NULL)
          t = pend->t;
        else
-         t = new_type (prepend_tag_kind (name, type_code));
+         t = new_type (NULL);
 
+       TYPE_TAG_NAME (t) = obconcat (&current_objfile->symbol_obstack,
+                                     "", "", name);
        TYPE_CODE (t) = type_code;
        TYPE_LENGTH (t) = sh->value;
        TYPE_NFIELDS (t) = nfields;
@@ -1071,7 +1085,7 @@ parse_symbol (sh, ax, ext_sh, bigend)
       break;
 
     case stEnd:                /* end (of anything) */
-      if (sh->sc == scInfo)
+      if (sh->sc == scInfo || sh->sc == scCommon)
        {
          /* Finished with type */
          top_stack->cur_type = 0;
@@ -1239,7 +1253,6 @@ parse_type (ax, bs, bigend)
   if (map_bt[t->bt])
     {
       tp = *map_bt[t->bt];
-      fmt = "%s";
     }
   else
     {
@@ -1249,27 +1262,21 @@ parse_type (ax, bs, bigend)
        {
        case btAdr:
          tp = lookup_pointer_type (builtin_type_void);
-         fmt = "%s";
          break;
        case btStruct:
          type_code = TYPE_CODE_STRUCT;
-         fmt = "struct %s";
          break;
        case btUnion:
          type_code = TYPE_CODE_UNION;
-         fmt = "union %s";
          break;
        case btEnum:
          type_code = TYPE_CODE_ENUM;
-         fmt = "enum %s";
          break;
        case btRange:
          type_code = TYPE_CODE_RANGE;
-         fmt = "%s";
          break;
        case btSet:
          type_code = TYPE_CODE_SET;
-         fmt = "set %s";
          break;
        case btTypedef:
        default:
@@ -1303,24 +1310,49 @@ parse_type (ax, bs, bigend)
   /* All these types really point to some (common) MIPS type
      definition, and only the type-qualifiers fully identify
      them.  We'll make the same effort at sharing. */
-  if (t->bt == btIndirect ||
-      t->bt == btStruct ||
+  if (t->bt == btStruct ||
       t->bt == btUnion ||
       t->bt == btEnum ||
-      t->bt == btTypedef ||
-      t->bt == btRange ||
+
+      /* btSet (I think) implies that the name is a tag name, not a typedef
+        name.  This apparently is a MIPS extension for C sets.  */
       t->bt == btSet)
     {
-      char name[256], *pn;
+      char *name;
 
       /* Try to cross reference this type */
-      ax += cross_ref (ax, &tp, type_code, &pn, bigend);
+      ax += cross_ref (ax, &tp, type_code, &name, bigend);
+      /* reading .o file ? */
+      if (tp == (struct type *) NULL)
+       tp = init_type (type_code, 0, 0, (char *) NULL,
+                       (struct objfile *) NULL);
+
+      /* Usually, TYPE_CODE(tp) is already type_code.  The main
+        exception is if we guessed wrong re struct/union/enum. */
+      if (TYPE_CODE (tp) != type_code)
+       {
+         complain (&bad_tag_guess_complaint, name);
+         TYPE_CODE (tp) = type_code;
+       }
+      if (TYPE_TAG_NAME (tp) == NULL || !STREQ (TYPE_TAG_NAME (tp), name))
+       TYPE_TAG_NAME (tp) = obsavestring (name, strlen (name),
+                                          &current_objfile->type_obstack);
+    }
+
+  /* All these types really point to some (common) MIPS type
+     definition, and only the type-qualifiers fully identify
+     them.  We'll make the same effort at sharing. */
+  if (t->bt == btIndirect ||
+      t->bt == btRange)
+    {
+      char *name;
+
+      /* Try to cross reference this type */
+      ax += cross_ref (ax, &tp, type_code, &name, bigend);
       /* reading .o file ? */
       if (tp == (struct type *) NULL)
        tp = init_type (type_code, 0, 0, (char *) NULL,
                        (struct objfile *) NULL);
-      /* SOMEONE OUGHT TO FIX DBXREAD TO DROP "STRUCT" */
-      sprintf (name, fmt, pn);
 
       /* Usually, TYPE_CODE(tp) is already type_code.  The main
         exception is if we guessed wrong re struct/union/enum. */
@@ -1483,12 +1515,16 @@ upgrade_type (tpp, tq, ax, bigend)
    images that have been partially stripped (ld -x) have been deprived
    of local symbols, and we have to cope with them here.  FIRST_OFF is
    the offset of the first procedure for this FDR; we adjust the
-   address by this amount, but I don't know why.  */
+   address by this amount, but I don't know why.  SEARCH_SYMTAB is the symtab
+   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 (pr, have_stabs, first_off)
+parse_procedure (pr, search_symtab, first_off)
      PDR *pr;
-     int have_stabs;
+     struct symtab *search_symtab;
      unsigned long first_off;
 {
   struct symbol *s, *i;
@@ -1529,8 +1565,12 @@ parse_procedure (pr, have_stabs, first_off)
       sh_name = ecoff_data (cur_bfd)->ss + cur_fdr->issBase + sh.iss;
     }
 
-  if (have_stabs)
+  if (search_symtab != NULL)
     {
+#if 0
+      /* This loses both in the case mentioned (want a static, find a global),
+        but also if we are looking up a non-mangled name which happens to
+        match the name of a mangled function.  */
       /* We have to save the cur_fdr across the call to lookup_symbol.
         If the pdr is for a static function and if a global function with
         the same name exists, lookup_symbol will eventually read in the symtab
@@ -1538,6 +1578,13 @@ parse_procedure (pr, have_stabs, first_off)
       FDR *save_cur_fdr = cur_fdr;
       s = lookup_symbol (sh_name, NULL, VAR_NAMESPACE, 0, NULL);
       cur_fdr = save_cur_fdr;
+#else
+      s = mylookup_symbol
+       (sh_name,
+        BLOCKVECTOR_BLOCK (BLOCKVECTOR (search_symtab), STATIC_BLOCK),
+        VAR_NAMESPACE,
+        LOC_BLOCK);
+#endif
     }
   else
     s = mylookup_symbol (sh_name, top_stack->cur_block,
@@ -1581,6 +1628,16 @@ parse_procedure (pr, have_stabs, first_off)
       e->pdr = *pr;
       e->pdr.isym = (long) s;
       e->pdr.adr += cur_fdr->adr - first_off;
+
+      /* Correct incorrect setjmp procedure descriptor from the library
+        to make backtrace through setjmp work.  */
+      if (e->pdr.pcreg == 0 && strcmp (sh_name, "setjmp") == 0)
+       {
+         complain (&bad_setjmp_pdr_complaint, 0);
+         e->pdr.pcreg = RA_REGNUM;
+         e->pdr.regmask = 0x80000000;
+         e->pdr.regoffset = -4;
+       }
     }
 }
 
@@ -2073,7 +2130,7 @@ parse_partial_symbols (objfile, section_offsets)
                case stStruct:
                case stEnum:
                case stBlock:   /* { }, str, un, enum*/
-                 if (sh.sc == scInfo)
+                 if (sh.sc == scInfo || sh.sc == scCommon)
                    {
                      ADD_PSYMBOL_TO_LIST (name, strlen (name),
                                           STRUCT_NAMESPACE, LOC_TYPEDEF,
@@ -2377,8 +2434,15 @@ psymtab_to_symtab_1 (pst, filename)
                             pst->dependencies[i]->filename);
       }
 
+  /* Do nothing if this is a dummy psymtab.  */
+
+  if (pst->n_global_syms == 0 && pst->n_static_syms == 0
+      && pst->textlow == 0 && pst->texthigh == 0)
+    return;
+
   /* Now read the symbols for this symtab */
 
+  cur_bfd = CUR_BFD (pst);
   current_objfile = pst->objfile;
   cur_fd = FDR_IDX (pst);
   fh = (cur_fd == -1) ? (FDR *) NULL : ecoff_data (cur_bfd)->fdr + cur_fd;
@@ -2459,10 +2523,13 @@ psymtab_to_symtab_1 (pst, filename)
              /* Handle encoded stab line number. */
              record_line (current_subfile, sh.index, valu);
            }
+         else if (sh.st == stProc || sh.st == stStaticProc || sh.st == stEnd)
+           /* These are generated by gcc-2.x, do not complain */
+           ;
          else
            complain (&stab_unknown_complaint, name);
        }
-      st = end_symtab (pst->texthigh, 0, 0, pst->objfile);
+      st = end_symtab (pst->texthigh, 0, 0, pst->objfile, SECT_OFF_TEXT);
       end_stabs ();
 
       /* Sort the symbol table now, we are done adding symbols to it.
@@ -2486,7 +2553,7 @@ psymtab_to_symtab_1 (pst, filename)
              first_off = pr.adr;
              first_pdr = 0;
            }
-         parse_procedure (&pr, 1, first_off);
+         parse_procedure (&pr, st, first_off);
        }
     }
   else
@@ -2698,6 +2765,13 @@ cross_ref (ax, tpp, type_code, pname, bigend)
       /* Careful, we might be looking at .o files */
       if (sh.iss == 0)
        *pname = "<undefined>";
+      else if (rn->rfd == 0xfff && rn->index == 0)
+       /* For structs, unions and enums, rn->rfd is 0xfff and the index
+          is a relative symbol number for the type, but an index of 0
+          seems to mean that we don't know.  This is said to fix a problem
+          with "info func opendir" on an SGI showing
+          "struct BSDopendir.c *BSDopendir();".  */
+       *pname = "<unknown>";
       else
        *pname = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss;
 
@@ -2749,7 +2823,7 @@ mylookup_symbol (name, block, namespace, class)
       if (SYMBOL_NAME (sym)[0] == inc
          && SYMBOL_NAMESPACE (sym) == namespace
          && SYMBOL_CLASS (sym) == class
-         && STREQ (SYMBOL_NAME (sym), name))
+         && strcmp (SYMBOL_NAME (sym), name) == 0)
        return sym;
       bot++;
     }
@@ -2819,7 +2893,18 @@ add_block (b, s)
 
 /* Add a new linenumber entry (LINENO,ADR) to a linevector LT.
    MIPS' linenumber encoding might need more than one byte
-   to describe it, LAST is used to detect these continuation lines */
+   to describe it, LAST is used to detect these continuation lines.
+
+   Combining lines with the same line number seems like a bad idea.
+   E.g: There could be a line number entry with the same line number after the
+   prologue and GDB should not ignore it (this is a better way to find
+   a prologue than mips_skip_prologue).
+   But due to the compressed line table format there are line number entries
+   for the same line which are needed to bridge the gap to the next
+   line number entry. These entries have a bogus address info with them
+   and we are unable to tell them from intended duplicate line number
+   entries.
+   This is another reason why -ggdb debugging format is preferable.  */
 
 static int
 add_line (lt, lineno, adr, last)
@@ -3102,19 +3187,20 @@ fixup_sigtramp ()
 
   sigtramp_address = -1;
 
-  /* We know it is sold as sigvec */
+  /* We have to handle the following cases here:
+     a) The Mips library has a sigtramp label within sigvec.
+     b) Irix has a _sigtramp which we want to use, but it also has sigvec.  */
   s = lookup_symbol ("sigvec", 0, VAR_NAMESPACE, 0, NULL);
-
-  /* Most programs do not play with signals */
-  if (s == 0)
-    s = lookup_symbol ("_sigtramp", 0, VAR_NAMESPACE, 0, NULL);
-  else
+  if (s != 0)
     {
       b0 = SYMBOL_BLOCK_VALUE (s);
-
-      /* A label of sigvec, to be more precise */
       s = lookup_symbol ("sigtramp", b0, VAR_NAMESPACE, 0, NULL);
     }
+  if (s == 0)
+    {
+      /* No sigvec or no sigtramp inside sigvec, try _sigtramp.  */
+      s = lookup_symbol ("_sigtramp", 0, VAR_NAMESPACE, 0, NULL);
+    }
 
   /* But maybe this program uses its own version of sigvec */
   if (s == 0)
@@ -3165,12 +3251,14 @@ fixup_sigtramp ()
     /* align_longword(sigcontext + SIGFRAME) */
     e->pdr.frameoffset = 0x150;
     e->pdr.framereg = SP_REGNUM;
-    e->pdr.pcreg = 31;
+    /* read_next_frame_reg provides the true pc at the time of signal */
+    e->pdr.pcreg = PC_REGNUM;
     e->pdr.regmask = -2;
     e->pdr.regoffset = -(41 * sizeof (int));
     e->pdr.fregmask = -1;
-    e->pdr.fregoffset = -(37 * sizeof (int));
+    e->pdr.fregoffset = -(7 * sizeof (int));
     e->pdr.isym = (long) s;
+    e->pdr.adr = sigtramp_address;
 
     current_objfile = st->objfile;     /* Keep new_symbol happy */
     s = new_symbol (MIPS_EFI_SYMBOL_NAME);