* configure.in (sparc64): Set arch to v9-64.
[deliverable/binutils-gdb.git] / binutils / ieee.c
index ee2cd1a9f81aa15721a7b7dda5a998ac1ee85b22..2756ba138eaa011ce534553a5f872af19b57b869 100644 (file)
@@ -154,10 +154,16 @@ struct ieee_info
   const bfd_byte *pend;
   /* The block stack.  */
   struct ieee_blockstack blockstack;
+  /* Whether we have seen a BB1 or BB2.  */
+  boolean saw_filename;
   /* The variables.  */
   struct ieee_vars vars;
+  /* The global variables, after a global typedef block.  */
+  struct ieee_vars *global_vars;
   /* The types.  */
   struct ieee_types types;
+  /* The global types, after a global typedef block.  */
+  struct ieee_types *global_types;
   /* The list of tagged structs.  */
   struct ieee_tag *tags;
 };
@@ -891,6 +897,7 @@ parse_ieee (dhandle, abfd, bytes, len)
   info.bytes = bytes;
   info.pend = bytes + len;
   info.blockstack.bsp = info.blockstack.stack;
+  info.saw_filename = false;
   info.vars.alloc = 0;
   info.vars.vars = NULL;
   info.types.alloc = 0;
@@ -999,6 +1006,29 @@ parse_ieee_bb (info, pp)
        return false;
       if (! debug_set_filename (info->dhandle, namcopy))
        return false;
+      info->saw_filename = true;
+
+      /* Discard any variables or types we may have seen before.  */
+      if (info->vars.vars != NULL)
+       free (info->vars.vars);
+      info->vars.vars = NULL;
+      info->vars.alloc = 0;
+      if (info->types.types != NULL)
+       free (info->types.types);
+      info->types.types = NULL;
+      info->types.alloc = 0;
+
+      /* Initialize the types to the global types.  */
+      if (info->global_types != NULL)
+       {
+         info->types.alloc = info->global_types->alloc;
+         info->types.types = ((struct ieee_type *)
+                              xmalloc (info->types.alloc
+                                       * sizeof (*info->types.types)));
+         memcpy (info->types.types, info->global_types->types,
+                 info->types.alloc * sizeof (*info->types.types));
+       }
+
       break;
 
     case 2:
@@ -1006,6 +1036,7 @@ parse_ieee_bb (info, pp)
         empty, but we don't check. */
       if (! debug_set_filename (info->dhandle, "*global*"))
        return false;
+      info->saw_filename = true;
       break;
 
     case 3:
@@ -1145,8 +1176,8 @@ parse_ieee_bb (info, pp)
       break;
 
     case 10:
-      /* BB10: Assembler module scope.  We completely ignore all this
-        information.  FIXME.  */
+      /* BB10: Assembler module scope.  In the normal case, we
+        completely ignore all this information.  FIXME.  */
       {
        const char *inam, *vstr;
        unsigned long inamlen, vstrlen;
@@ -1154,6 +1185,16 @@ parse_ieee_bb (info, pp)
        boolean present;
        unsigned int i;
 
+       if (! info->saw_filename)
+         {
+           namcopy = savestring (name, namlen);
+           if (namcopy == NULL)
+             return false;
+           if (! debug_set_filename (info->dhandle, namcopy))
+             return false;
+           info->saw_filename = true;
+         }
+
        if (! ieee_read_id (info, pp, &inam, &inamlen)
            || ! ieee_read_number (info, pp, &tool_type)
            || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present))
@@ -1227,6 +1268,37 @@ parse_ieee_be (info, pp)
 
   switch (info->blockstack.bsp->kind)
     {
+    case 2:
+      /* When we end the global typedefs block, we copy out the the
+         contents of info->vars.  This is because the variable indices
+         may be reused in the local blocks.  However, we need to
+         preserve them so that we can locate a function returning a
+         reference variable whose type is named in the global typedef
+         block.  */
+      info->global_vars = ((struct ieee_vars *)
+                          xmalloc (sizeof *info->global_vars));
+      info->global_vars->alloc = info->vars.alloc;
+      info->global_vars->vars = ((struct ieee_var *)
+                                xmalloc (info->vars.alloc
+                                         * sizeof (*info->vars.vars)));
+      memcpy (info->global_vars->vars, info->vars.vars,
+             info->vars.alloc * sizeof (*info->vars.vars));
+
+      /* We also copy out the non builtin parts of info->types, since
+         the types are discarded when we start a new block.  */
+      info->global_types = ((struct ieee_types *)
+                           xmalloc (sizeof *info->global_types));
+      info->global_types->alloc = info->types.alloc;
+      info->global_types->types = ((struct ieee_type *)
+                                  xmalloc (info->types.alloc
+                                           * sizeof (*info->types.types)));
+      memcpy (info->global_types->types, info->types.types,
+             info->types.alloc * sizeof (*info->types.types));
+      memset (info->global_types->builtins, 0,
+             sizeof (info->global_types->builtins));
+
+      break;
+
     case 4:
     case 6:
       if (! ieee_read_expression (info, pp, &offset))
@@ -1799,16 +1871,31 @@ parse_ieee_ty (info, pp)
     case 'g':
       /* Bitfield type.  */
       {
-       bfd_vma signedp, bitsize;
+       bfd_vma signedp, bitsize, dummy;
+       const bfd_byte *hold;
+       boolean present;
 
        if (! ieee_read_number (info, pp, &signedp)
-           || ! ieee_read_number (info, pp, &bitsize)
-           || ! ieee_read_type_index (info, pp, &type))
+           || ! ieee_read_number (info, pp, &bitsize))
          return false;
 
-       /* FIXME: This is just a guess.  */
-       if (! signedp)
-         type = debug_make_int_type (dhandle, 4, true);
+       /* I think the documentation says that there is a type index,
+           but some actual files do not have one.  */
+       hold = *pp;
+       if (! ieee_read_optional_number (info, pp, &dummy, &present))
+         return false;
+       if (! present)
+         {
+           /* FIXME: This is just a guess.  */
+           type = debug_make_int_type (dhandle, 4,
+                                       signedp ? false : true);
+         }
+       else
+         {
+           *pp = hold;
+           if (! ieee_read_type_index (info, pp, &type))
+             return false;
+         }
        type_bitsize = bitsize;
       }
       break;
@@ -1959,8 +2046,7 @@ parse_ieee_ty (info, pp)
       break;
     }
 
-  /* Record the type in the table.  If the corresponding NN record has
-     a name, name it.  FIXME: Is this always correct?  */
+  /* Record the type in the table.  */
 
   if (type == DEBUG_TYPE_NULL)
     return false;
@@ -2064,8 +2150,38 @@ parse_ieee_atn (info, pp)
       if (varindx >= info->vars.alloc
          || info->vars.vars[varindx].name == NULL)
        {
-         ieee_error (info, atn_start, "undefined variable in ATN");
-         return false;
+         /* The MRI compiler or linker sometimes omits the NN record
+             for a pmisc record.  */
+         if (atn_code == 62)
+           {
+             if (varindx >= info->vars.alloc)
+               {
+                 unsigned int alloc;
+
+                 alloc = info->vars.alloc;
+                 if (alloc == 0)
+                   alloc = 4;
+                 while (varindx >= alloc)
+                   alloc *= 2;
+                 info->vars.vars = ((struct ieee_var *)
+                                    xrealloc (info->vars.vars,
+                                              (alloc
+                                               * sizeof *info->vars.vars)));
+                 memset (info->vars.vars + info->vars.alloc, 0,
+                         ((alloc - info->vars.alloc)
+                          * sizeof *info->vars.vars));
+                 info->vars.alloc = alloc;
+               }
+
+             pvar = info->vars.vars + varindx;
+             pvar->name = "";
+             pvar->namlen = 0;
+           }
+         else
+           {
+             ieee_error (info, atn_start, "undefined variable in ATN");
+             return false;
+           }
        }
 
       pvar = info->vars.vars + varindx;
@@ -3245,60 +3361,79 @@ ieee_read_reference (info, pp)
   pslot = NULL;
   if (flags != 3)
     {
-      int i;
-      struct ieee_var *pv = NULL;
+      int pass;
 
       /* We search from the last variable indices to the first in
-        hopes of finding local variables correctly.  FIXME: This
-        probably won't work in all cases.  On the other hand, I don't
-        know what will.  */
-      for (i = (int) info->vars.alloc - 1; i >= 0; i--)
+        hopes of finding local variables correctly.  We search the
+        local variables on the first pass, and the global variables
+        on the second.  FIXME: This probably won't work in all cases.
+        On the other hand, I don't know what will.  */
+      for (pass = 0; pass < 2; pass++)
        {
-         boolean found;
+         struct ieee_vars *vars;
+         int i;
+         struct ieee_var *pv = NULL;
 
-         pv = info->vars.vars + i;
-
-         if (pv->pslot == NULL
-             || pv->namlen != namlen
-             || strncmp (pv->name, name, namlen) != 0)
-           continue;
+         if (pass == 0)
+           vars = &info->vars;
+         else
+           {
+             vars = info->global_vars;
+             if (vars == NULL)
+               break;
+           }
 
-         found = false;
-         switch (flags)
+         for (i = (int) vars->alloc - 1; i >= 0; i--)
            {
-           default:
-             ieee_error (info, start,
-                         "unrecognized C++ reference type");
-             return false;
+             boolean found;
 
-           case 0:
-             /* Global variable or function.  */
-             if (pv->kind == IEEE_GLOBAL
-                 || pv->kind == IEEE_EXTERNAL
-                 || pv->kind == IEEE_FUNCTION)
-               found = true;
-             break;
+             pv = vars->vars + i;
 
-           case 1:
-             /* Global static variable or function.  */
-             if (pv->kind == IEEE_STATIC
-                 || pv->kind == IEEE_FUNCTION)
-               found = true;
-             break;
+             if (pv->pslot == NULL
+                 || pv->namlen != namlen
+                 || strncmp (pv->name, name, namlen) != 0)
+               continue;
 
-           case 2:
-             /* Local variable.  */
-             if (pv->kind == IEEE_LOCAL)
-               found = true;
-             break;
+             found = false;
+             switch (flags)
+               {
+               default:
+                 ieee_error (info, start,
+                             "unrecognized C++ reference type");
+                 return false;
+
+               case 0:
+                 /* Global variable or function.  */
+                 if (pv->kind == IEEE_GLOBAL
+                     || pv->kind == IEEE_EXTERNAL
+                     || pv->kind == IEEE_FUNCTION)
+                   found = true;
+                 break;
+
+               case 1:
+                 /* Global static variable or function.  */
+                 if (pv->kind == IEEE_STATIC
+                     || pv->kind == IEEE_FUNCTION)
+                   found = true;
+                 break;
+
+               case 2:
+                 /* Local variable.  */
+                 if (pv->kind == IEEE_LOCAL)
+                   found = true;
+                 break;
+               }
+
+             if (found)
+               break;
            }
 
-         if (found)
-           break;
+         if (i >= 0)
+           {
+             pslot = pv->pslot;
+             break;
+           }
        }
-
-      if (i >= 0)
-       pslot = pv->pslot;
     }
   else
     {
@@ -3656,6 +3791,8 @@ struct ieee_defined_enum
   struct ieee_defined_enum *next;
   /* Type index.  */
   unsigned int indx;
+  /* Whether this enum has been defined.  */
+  boolean defined;
   /* Tag.  */
   const char *tag;
   /* Names.  */
@@ -4595,7 +4732,18 @@ write_ieee_debugging_info (abfd, dhandle)
   /* Prepend the global typedef information to the other data.  */
   if (! ieee_buffer_emptyp (&info.global_types))
     {
+      /* The HP debugger seems to have a bug in which it ignores the
+         last entry in the global types, so we add a dummy entry.  */
       if (! ieee_change_buffer (&info, &info.global_types)
+         || ! ieee_write_byte (&info, (int) ieee_nn_record)
+         || ! ieee_write_number (&info, info.name_indx)
+         || ! ieee_write_id (&info, "")
+         || ! ieee_write_byte (&info, (int) ieee_ty_record_enum)
+         || ! ieee_write_number (&info, info.type_indx)
+         || ! ieee_write_byte (&info, 0xce)
+         || ! ieee_write_number (&info, info.name_indx)
+         || ! ieee_write_number (&info, 'P')
+         || ! ieee_write_number (&info, (int) builtin_void + 32)
          || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
        return false;
 
@@ -4937,7 +5085,7 @@ ieee_finish_compilation_unit (info)
 
       /* Coalesce ranges if it seems reasonable.  */
       while (r->next != NULL
-            && high + 64 >= r->next->low
+            && high + 0x1000 >= r->next->low
             && (r->next->high
                 <= (bfd_get_section_vma (info->abfd, s)
                     + bfd_section_size (info->abfd, s))))
@@ -5006,7 +5154,8 @@ ieee_add_bb11_blocks (abfd, sec, data)
          return;
        }
 
-      if (low < r->low)
+      if (low < r->low
+         && r->low - low > 0x100)
        {
          if (! ieee_add_bb11 (info, sec, low, r->low))
            {
@@ -5269,9 +5418,11 @@ ieee_enum_type (p, tag, names, vals)
   struct ieee_handle *info = (struct ieee_handle *) p;
   struct ieee_defined_enum *e;
   boolean localp, simple;
+  unsigned int indx;
   int i;
 
   localp = false;
+  indx = (unsigned int) -1;
   for (e = info->enums; e != NULL; e = e->next)
     {
       if (tag == NULL)
@@ -5287,6 +5438,13 @@ ieee_enum_type (p, tag, names, vals)
            continue;
        }
 
+      if (! e->defined)
+       {
+         /* This enum tag has been seen but not defined.  */
+         indx = e->indx;
+         break;
+       }
+
       if (names != NULL && e->names != NULL)
        {
          for (i = 0; names[i] != NULL && e->names[i] != NULL; i++)
@@ -5299,7 +5457,10 @@ ieee_enum_type (p, tag, names, vals)
        }
 
       if ((names == NULL && e->names == NULL)
-         || (names[i] == NULL && e->names[i] == NULL))
+         || (names != NULL
+             && e->names != NULL
+             && names[i] == NULL
+             && e->names[i] == NULL))
        {
          /* We've seen this enum before.  */
          return ieee_push_type (info, e->indx, 0, true, false);
@@ -5331,8 +5492,8 @@ ieee_enum_type (p, tag, names, vals)
        }
     }
 
-  if (! ieee_define_named_type (info, tag, (unsigned int) -1, 0,
-                               true, localp, (struct ieee_buflist *) NULL)
+  if (! ieee_define_named_type (info, tag, indx, 0, true, localp,
+                               (struct ieee_buflist *) NULL)
       || ! ieee_write_number (info, simple ? 'E' : 'N'))
     return false;
   if (simple)
@@ -5358,16 +5519,20 @@ ieee_enum_type (p, tag, names, vals)
 
   if (! localp)
     {
-      e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
-      memset (e, 0, sizeof *e);
+      if (indx == (unsigned int) -1)
+       {
+         e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+         memset (e, 0, sizeof *e);
+         e->indx = info->type_stack->type.indx;
+         e->tag = tag;
+
+         e->next = info->enums;
+         info->enums = e;
+       }
 
-      e->indx = info->type_stack->type.indx;
-      e->tag = tag;
       e->names = names;
       e->vals = vals;
-
-      e->next = info->enums;
-      info->enums = e;
+      e->defined = true;
     }
 
   return true;
@@ -5558,14 +5723,21 @@ ieee_array_type (p, low, high, stringp)
   struct ieee_handle *info = (struct ieee_handle *) p;
   unsigned int eleindx;
   boolean localp;
+  unsigned int size;
   struct ieee_modified_type *m = NULL;
   struct ieee_modified_array_type *a;
 
   /* IEEE does not store the range, so we just ignore it.  */
   ieee_pop_unused_type (info);
   localp = info->type_stack->type.localp;
+  size = info->type_stack->type.size;
   eleindx = ieee_pop_type (info);
 
+  /* If we don't know the range, treat the size as exactly one
+     element.  */
+  if (low < high)
+    size *= (high - low) + 1;
+
   if (! localp)
     {
       m = ieee_get_modified_info (info, eleindx);
@@ -5575,11 +5747,11 @@ ieee_array_type (p, low, high, stringp)
       for (a = m->arrays; a != NULL; a = a->next)
        {
          if (a->low == low && a->high == high)
-           return ieee_push_type (info, a->indx, 0, false, false);
+           return ieee_push_type (info, a->indx, size, false, false);
        }
     }
 
-  if (! ieee_define_type (info, 0, false, localp)
+  if (! ieee_define_type (info, size, false, localp)
       || ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
       || ! ieee_write_number (info, eleindx))
     return false;
@@ -6520,7 +6692,19 @@ ieee_tag_type (p, name, id, kind)
       for (e = info->enums; e != NULL; e = e->next)
        if (e->tag != NULL && strcmp (e->tag, name) == 0)
          return ieee_push_type (info, e->indx, 0, true, false);
-      abort ();
+
+      e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+      memset (e, 0, sizeof *e);
+
+      e->indx = info->type_indx;
+      ++info->type_indx;
+      e->tag = name;
+      e->defined = false;
+
+      e->next = info->enums;
+      info->enums = e;
+
+      return ieee_push_type (info, e->indx, 0, true, false);
     }
 
   localp = false;
@@ -7410,9 +7594,12 @@ ieee_lineno (p, filename, lineno, addr)
        return false;
     }
 
-  info->pending_lineno_filename = filename;
-  info->pending_lineno = lineno;
-  info->pending_lineno_addr = addr;
+  if (addr < info->highaddr)
+    {
+      info->pending_lineno_filename = filename;
+      info->pending_lineno = lineno;
+      info->pending_lineno_addr = addr;
+    }
 
   return true;
 }
This page took 0.029541 seconds and 4 git commands to generate.