gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / binutils / stabs.c
index 9aca97afe68c0eaf15c26ee63e757cdcbdebba70..9f043d1191bb317d7303ad6e3b70b865f192da52 100644 (file)
@@ -1,13 +1,12 @@
 /* stabs.c -- Parse stabs debugging information
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GNU Binutils.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    code.  The job it does is somewhat different, because it is not
    trying to identify the correct address for anything.  */
 
-#include <stdio.h>
-
+#include "sysdep.h"
 #include "bfd.h"
-#include "bucomm.h"
 #include "libiberty.h"
 #include "safe-ctype.h"
 #include "demangle.h"
@@ -148,42 +145,51 @@ struct stab_tag
 };
 
 static char *savestring (const char *, int);
-static bfd_vma parse_number (const char **, bfd_boolean *);
+
 static void bad_stab (const char *);
 static void warn_stab (const char *, const char *);
 static bfd_boolean parse_stab_string
-  (void *, struct stab_handle *, int, int, bfd_vma, const char *);
+  (void *, struct stab_handle *, int, int, bfd_vma,
+   const char *, const char *);
 static debug_type parse_stab_type
-  (void *, struct stab_handle *, const char *, const char **, debug_type **);
-static bfd_boolean parse_stab_type_number (const char **, int *);
+  (void *, struct stab_handle *, const char *, const char **,
+   debug_type **, const char *);
+static bfd_boolean parse_stab_type_number
+  (const char **, int *, const char *);
 static debug_type parse_stab_range_type
-  (void *, struct stab_handle *, const char *, const char **, const int *);
-static debug_type parse_stab_sun_builtin_type (void *, const char **);
-static debug_type parse_stab_sun_floating_type (void *, const char **);
-static debug_type parse_stab_enum_type (void *, const char **);
+  (void *, struct stab_handle *, const char *, const char **,
+   const int *, const char *);
+static debug_type parse_stab_sun_builtin_type
+  (void *, const char **, const char *);
+static debug_type parse_stab_sun_floating_type
+  (void *, const char **, const char *);
+static debug_type parse_stab_enum_type
+  (void *, const char **, const char *);
 static debug_type parse_stab_struct_type
   (void *, struct stab_handle *, const char *, const char **,
-   bfd_boolean, const int *);
+   bfd_boolean, const int *, const char *);
 static bfd_boolean parse_stab_baseclasses
-  (void *, struct stab_handle *, const char **, debug_baseclass **);
+  (void *, struct stab_handle *, const char **, debug_baseclass **,
+   const char *);
 static bfd_boolean parse_stab_struct_fields
-  (void *, struct stab_handle *, const char **, debug_field **, bfd_boolean *);
+  (void *, struct stab_handle *, const char **, debug_field **,
+   bfd_boolean *, const char *);
 static bfd_boolean parse_stab_cpp_abbrev
-  (void *, struct stab_handle *, const char **, debug_field *);
+  (void *, struct stab_handle *, const char **, debug_field *, const char *);
 static bfd_boolean parse_stab_one_struct_field
   (void *, struct stab_handle *, const char **, const char *,
-   debug_field *, bfd_boolean *);
+   debug_field *, bfd_boolean *, const char *);
 static bfd_boolean parse_stab_members
   (void *, struct stab_handle *, const char *, const char **, const int *,
-   debug_method **);
+   debug_method **, const char *);
 static debug_type parse_stab_argtypes
   (void *, struct stab_handle *, debug_type, const char *, const char *,
    debug_type, const char *, bfd_boolean, bfd_boolean, const char **);
 static bfd_boolean parse_stab_tilde_field
   (void *, struct stab_handle *, const char **, const int *, debug_type *,
-   bfd_boolean *);
+   bfd_boolean *, const char *);
 static debug_type parse_stab_array_type
-  (void *, struct stab_handle *, const char **, bfd_boolean);
+  (void *, struct stab_handle *, const char **, bfd_boolean, const char *);
 static void push_bincl (struct stab_handle *, const char *, bfd_vma);
 static const char *pop_bincl (struct stab_handle *);
 static bfd_boolean find_excl (struct stab_handle *, const char *, bfd_vma);
@@ -209,6 +215,8 @@ static debug_type stab_demangle_v3_arg
   (void *, struct stab_handle *, struct demangle_component *, debug_type,
    bfd_boolean *);
 
+static int demangle_flags = DMGL_ANSI;
+
 /* Save a string in memory.  */
 
 static char *
@@ -225,7 +233,7 @@ savestring (const char *start, int len)
 /* Read a number from a string.  */
 
 static bfd_vma
-parse_number (const char **pp, bfd_boolean *poverflow)
+parse_number (const char **pp, bfd_boolean *poverflow, const char *p_end)
 {
   unsigned long ul;
   const char *orig;
@@ -234,6 +242,12 @@ parse_number (const char **pp, bfd_boolean *poverflow)
     *poverflow = FALSE;
 
   orig = *pp;
+  if (orig >= p_end)
+    return (bfd_vma) 0;
+
+  /* Stop early if we are passed an empty string.  */
+  if (*orig == 0)
+    return (bfd_vma) 0;
 
   errno = 0;
   ul = strtoul (*pp, (char **) pp, 0);
@@ -408,6 +422,7 @@ bfd_boolean
 parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
            const char *string)
 {
+  const char * string_end;
   struct stab_handle *info = (struct stab_handle *) handle;
 
   /* gcc will emit two N_SO strings per compilation unit, one for the
@@ -436,12 +451,13 @@ parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
       info->file_types = ((struct stab_types **)
                          xmalloc (sizeof *info->file_types));
       info->file_types[0] = NULL;
-
       info->so_string = NULL;
 
       /* Now process whatever type we just got.  */
     }
 
+  string_end = string + strlen (string);
+
   switch (type)
     {
     case N_FN:
@@ -651,7 +667,7 @@ parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
            info->within_function = TRUE;
          }
 
-       if (! parse_stab_string (dhandle, info, type, desc, value, string))
+       if (! parse_stab_string (dhandle, info, type, desc, value, string, string_end))
          return FALSE;
       }
       break;
@@ -679,7 +695,8 @@ parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
 
 static bfd_boolean
 parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
-                  int desc, bfd_vma value, const char *string)
+                  int desc ATTRIBUTE_UNUSED, bfd_vma value,
+                  const char *string, const char * string_end)
 {
   const char *p;
   char *name;
@@ -687,7 +704,6 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
   debug_type dtype;
   bfd_boolean synonym;
   bfd_boolean self_crossref;
-  unsigned int lineno;
   debug_type *slot;
 
   p = strchr (string, ':');
@@ -705,14 +721,6 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
        }
     }
 
-  /* GCC 2.x puts the line number in desc.  SunOS apparently puts in
-     the number of bytes occupied by a type or object, which we
-     ignore.  */
-  if (info->gcc_compiled >= 2)
-    lineno = desc;
-  else
-    lineno = 0;
-
   /* FIXME: Sometimes the special C++ names start with '.'.  */
   name = NULL;
   if (string[0] == '$')
@@ -751,6 +759,11 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
   ++p;
   if (ISDIGIT (*p) || *p == '(' || *p == '-')
     type = 'l';
+  else if (*p == 0)
+    {
+      bad_stab (string);
+      return FALSE;
+    }
   else
     type = *p++;
 
@@ -793,7 +806,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
             e.g. "b:c=e6,0" for "const b = blob1"
             (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;").  */
          dtype = parse_stab_type (dhandle, info, (const char *) NULL,
-                                  &p, (debug_type **) NULL);
+                                  &p, (debug_type **) NULL, string_end);
          if (dtype == DEBUG_TYPE_NULL)
            return FALSE;
          if (*p != ',')
@@ -814,7 +827,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'C':
       /* The name of a caught exception.  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL,
-                              &p, (debug_type **) NULL);
+                              &p, (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! debug_record_label (dhandle, name, dtype, value))
@@ -825,7 +838,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'F':
       /* A function definition.  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
@@ -839,7 +852,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
        {
          ++p;
          if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL)
+                              (debug_type **) NULL, string_end)
              == DEBUG_TYPE_NULL)
            return FALSE;
        }
@@ -848,29 +861,35 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
 
     case 'G':
       {
-       char leading;
-       long c;
        asymbol **ps;
 
        /* A global symbol.  The value must be extracted from the
           symbol table.  */
        dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                                (debug_type **) NULL);
+                                (debug_type **) NULL, string_end);
        if (dtype == DEBUG_TYPE_NULL)
          return FALSE;
-       leading = bfd_get_symbol_leading_char (info->abfd);
-       for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+       if (name != NULL)
          {
-           const char *n;
+           char leading;
+           long c;
 
-           n = bfd_asymbol_name (*ps);
-           if (leading != '\0' && *n == leading)
-             ++n;
-           if (*n == *name && strcmp (n, name) == 0)
-             break;
+           leading = bfd_get_symbol_leading_char (info->abfd);
+           for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+             {
+               const char *n;
+
+               n = bfd_asymbol_name (*ps);
+               if (leading != '\0' && *n == leading)
+                 ++n;
+               if (*n == *name && strcmp (n, name) == 0)
+                 break;
+             }
+
+           if (c > 0)
+             value = bfd_asymbol_value (*ps);
          }
-       if (c > 0)
-         value = bfd_asymbol_value (*ps);
+
        if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
                                    value))
          return FALSE;
@@ -883,7 +902,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'l':
     case 's':
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
@@ -895,7 +914,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
       /* A function parameter.  */
       if (*p != 'F')
        dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                                (debug_type **) NULL);
+                                (debug_type **) NULL, string_end);
       else
        {
        /* pF is a two-letter code that means a function parameter in
@@ -903,7 +922,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
           value.  Translate it into a pointer-to-function type.  */
          ++p;
          dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                                  (debug_type **) NULL);
+                                  (debug_type **) NULL, string_end);
          if (dtype != DEBUG_TYPE_NULL)
            {
              debug_type ftype;
@@ -933,7 +952,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
            {
              ++p;
              if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                                  (debug_type **) NULL)
+                                  (debug_type **) NULL, string_end)
                  == DEBUG_TYPE_NULL)
                return FALSE;
            }
@@ -943,7 +962,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'R':
       /* Parameter which is in a register.  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
@@ -954,7 +973,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'r':
       /* Register variable (either global or local).  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
@@ -968,7 +987,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'S':
       /* Static symbol at top level of file.  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
@@ -978,7 +997,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
 
     case 't':
       /* A typedef.  */
-      dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+      dtype = parse_stab_type (dhandle, info, name, &p, &slot, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (name == NULL)
@@ -997,7 +1016,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
       break;
 
     case 'T':
-      /* Struct, union, or enum tag.  For GNU C++, this can be be followed
+      /* Struct, union, or enum tag.  For GNU C++, this can be followed
         by 't' which means we are typedef'ing it as well.  */
       if (*p != 't')
        {
@@ -1011,7 +1030,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
          ++p;
        }
 
-      dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+      dtype = parse_stab_type (dhandle, info, name, &p, &slot, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (name == NULL)
@@ -1062,7 +1081,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'V':
       /* Static symbol of local scope */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       /* FIXME: gdb checks os9k_stabs here.  */
@@ -1074,7 +1093,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'v':
       /* Reference parameter.  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
@@ -1085,7 +1104,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
     case 'a':
       /* Reference parameter which is in a register.  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
@@ -1099,7 +1118,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
         that Pascal uses it too, but when I tried it Pascal used
         "x:3" (local symbol) instead.  */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, string_end);
       if (dtype == DEBUG_TYPE_NULL)
        return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
@@ -1107,6 +1126,26 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
        return FALSE;
       break;
 
+    case 'Y':
+      /* SUNPro C++ Namespace =Yn0.  */
+      /* Skip the namespace mapping, as it is not used now.  */
+      if (*(++p) == 'n' && *(++p) == '0')
+       {
+         /* =Yn0name; */
+         while (*p != ';')
+           ++p;
+         ++p;
+         return TRUE;
+       }
+      /* TODO SUNPro C++ support:
+         Support default arguments after F,P parameters
+         Ya = Anonymous unions
+         YM,YD = Pointers to class members
+         YT,YI = Templates
+         YR = Run-time type information (RTTI)  */
+
+      /* Fall through.  */
+
     default:
       bad_stab (string);
       return FALSE;
@@ -1124,7 +1163,12 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
    store the slot used if the type is being defined.  */
 
 static debug_type
-parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, debug_type **slotp)
+parse_stab_type (void *                dhandle,
+                struct stab_handle *  info,
+                const char *          type_name,
+                const char **         pp,
+                debug_type **         slotp,
+                const char *          p_end)
 {
   const char *orig;
   int typenums[2];
@@ -1137,6 +1181,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
     *slotp = NULL;
 
   orig = *pp;
+  if (orig >= p_end)
+    return DEBUG_TYPE_NULL;
 
   size = -1;
   stringp = FALSE;
@@ -1154,7 +1200,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
     }
   else
     {
-      if (! parse_stab_type_number (pp, typenums))
+      if (! parse_stab_type_number (pp, typenums, p_end))
        return DEBUG_TYPE_NULL;
 
       if (**pp != '=')
@@ -1217,6 +1263,10 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
              stringp = TRUE;
              break;
 
+           case 0:
+             bad_stab (orig);
+             return DEBUG_TYPE_NULL;
+
            default:
              /* Ignore unrecognized type attributes, so future
                 compilers can invent new ones.  */
@@ -1247,6 +1297,10 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
          case 'e':
            code = DEBUG_KIND_ENUM;
            break;
+         case 0:
+             bad_stab (orig);
+             return DEBUG_TYPE_NULL;
+           
          default:
            /* Complain and keep going, so compilers can invent new
               cross-reference types.  */
@@ -1288,9 +1342,9 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
               fleep:T20=xsfleep:
           which define structures in terms of themselves.  We need to
           tell the caller to avoid building a circular structure.  */
-       if (typename != NULL
-           && strncmp (typename, *pp, p - *pp) == 0
-           && typename[p - *pp] == '\0')
+       if (type_name != NULL
+           && strncmp (type_name, *pp, p - *pp) == 0
+           && type_name[p - *pp] == '\0')
          info->self_crossref = TRUE;
 
        dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
@@ -1320,7 +1374,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
        hold = *pp;
 
        /* Peek ahead at the number to detect void.  */
-       if (! parse_stab_type_number (pp, xtypenums))
+       if (! parse_stab_type_number (pp, xtypenums, p_end))
          return DEBUG_TYPE_NULL;
 
        if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
@@ -1337,7 +1391,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
               This means that we can deal with something like
               t(1,2)=(3,4)=... which the Lucid compiler uses.  */
            dtype = parse_stab_type (dhandle, info, (const char *) NULL,
-                                    pp, (debug_type **) NULL);
+                                    pp, (debug_type **) NULL, p_end);
            if (dtype == DEBUG_TYPE_NULL)
              return DEBUG_TYPE_NULL;
          }
@@ -1356,7 +1410,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
                                       parse_stab_type (dhandle, info,
                                                        (const char *) NULL,
                                                        pp,
-                                                       (debug_type **) NULL));
+                                                       (debug_type **) NULL,
+                                                       p_end));
       break;
 
     case '&':
@@ -1364,7 +1419,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
       dtype = (debug_make_reference_type
               (dhandle,
                parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                (debug_type **) NULL)));
+                                (debug_type **) NULL, p_end)));
       break;
 
     case 'f':
@@ -1373,7 +1428,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
       dtype = (debug_make_function_type
               (dhandle,
                parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                (debug_type **) NULL),
+                                (debug_type **) NULL, p_end),
                (debug_type *) NULL, FALSE));
       break;
 
@@ -1384,7 +1439,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
                                     parse_stab_type (dhandle, info,
                                                      (const char *) NULL,
                                                      pp,
-                                                     (debug_type **) NULL));
+                                                     (debug_type **) NULL,
+                                                     p_end));
       break;
 
     case 'B':
@@ -1393,7 +1449,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
       dtype = (debug_make_volatile_type
               (dhandle,
                parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                (debug_type **) NULL)));
+                                (debug_type **) NULL, p_end)));
       break;
 
     case '@':
@@ -1406,7 +1462,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
        /* Member type.  */
 
        domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                 (debug_type **) NULL);
+                                 (debug_type **) NULL, p_end);
        if (domain == DEBUG_TYPE_NULL)
          return DEBUG_TYPE_NULL;
 
@@ -1418,7 +1474,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
        ++*pp;
 
        memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                  (debug_type **) NULL);
+                                  (debug_type **) NULL, p_end);
        if (memtype == DEBUG_TYPE_NULL)
          return DEBUG_TYPE_NULL;
 
@@ -1434,7 +1490,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
 
          ++*pp;
          return_type = parse_stab_type (dhandle, info, (const char *) NULL,
-                                        pp, (debug_type **) NULL);
+                                        pp, (debug_type **) NULL, p_end);
          if (return_type == DEBUG_TYPE_NULL)
            return DEBUG_TYPE_NULL;
          if (**pp != ';')
@@ -1457,7 +1513,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
          bfd_boolean varargs;
 
          domain = parse_stab_type (dhandle, info, (const char *) NULL,
-                                   pp, (debug_type **) NULL);
+                                   pp, (debug_type **) NULL, p_end);
          if (domain == DEBUG_TYPE_NULL)
            return DEBUG_TYPE_NULL;
 
@@ -1469,7 +1525,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
          ++*pp;
 
          return_type = parse_stab_type (dhandle, info, (const char *) NULL,
-                                        pp, (debug_type **) NULL);
+                                        pp, (debug_type **) NULL, p_end);
          if (return_type == DEBUG_TYPE_NULL)
            return DEBUG_TYPE_NULL;
 
@@ -1493,7 +1549,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
                }
 
              args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
-                                        pp, (debug_type **) NULL);
+                                        pp, (debug_type **) NULL, p_end);
              if (args[n] == DEBUG_TYPE_NULL)
                return DEBUG_TYPE_NULL;
              ++n;
@@ -1521,30 +1577,30 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
 
     case 'r':
       /* Range type.  */
-      dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums);
+      dtype = parse_stab_range_type (dhandle, info, type_name, pp, typenums, p_end);
       break;
 
     case 'b':
       /* FIXME: gdb checks os9k_stabs here.  */
       /* Sun ACC builtin int type.  */
-      dtype = parse_stab_sun_builtin_type (dhandle, pp);
+      dtype = parse_stab_sun_builtin_type (dhandle, pp, p_end);
       break;
 
     case 'R':
       /* Sun ACC builtin float type.  */
-      dtype = parse_stab_sun_floating_type (dhandle, pp);
+      dtype = parse_stab_sun_floating_type (dhandle, pp, p_end);
       break;
 
     case 'e':
       /* Enumeration type.  */
-      dtype = parse_stab_enum_type (dhandle, pp);
+      dtype = parse_stab_enum_type (dhandle, pp, p_end);
       break;
 
     case 's':
     case 'u':
       /* Struct or union type.  */
-      dtype = parse_stab_struct_type (dhandle, info, typename, pp,
-                                     descriptor == 's', typenums);
+      dtype = parse_stab_struct_type (dhandle, info, type_name, pp,
+                                     descriptor == 's', typenums, p_end);
       break;
 
     case 'a':
@@ -1556,7 +1612,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
        }
       ++*pp;
 
-      dtype = parse_stab_array_type (dhandle, info, pp, stringp);
+      dtype = parse_stab_array_type (dhandle, info, pp, stringp, p_end);
       break;
 
     case 'S':
@@ -1564,7 +1620,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
                                   parse_stab_type (dhandle, info,
                                                    (const char *) NULL,
                                                    pp,
-                                                   (debug_type **) NULL),
+                                                   (debug_type **) NULL,
+                                                   p_end),
                                   stringp);
       break;
 
@@ -1597,7 +1654,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename,
    storing them in the vector TYPENUMS.  */
 
 static bfd_boolean
-parse_stab_type_number (const char **pp, int *typenums)
+parse_stab_type_number (const char **pp, int *typenums, const char *p_end)
 {
   const char *orig;
 
@@ -1606,34 +1663,39 @@ parse_stab_type_number (const char **pp, int *typenums)
   if (**pp != '(')
     {
       typenums[0] = 0;
-      typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
+      typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL, p_end);
+      return TRUE;
     }
-  else
+
+  ++*pp;
+  typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL, p_end);
+  if (**pp != ',')
     {
-      ++*pp;
-      typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL);
-      if (**pp != ',')
-       {
-         bad_stab (orig);
-         return FALSE;
-       }
-      ++*pp;
-      typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
-      if (**pp != ')')
-       {
-         bad_stab (orig);
-         return FALSE;
-       }
-      ++*pp;
+      bad_stab (orig);
+      return FALSE;
     }
 
+  ++*pp;
+  typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL, p_end);
+  if (**pp != ')')
+    {
+      bad_stab (orig);
+      return FALSE;
+    }
+
+  ++*pp;
   return TRUE;
 }
 
 /* Parse a range type.  */
 
 static debug_type
-parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, const int *typenums)
+parse_stab_range_type (void *                dhandle,
+                      struct stab_handle *  info,
+                      const char *          type_name,
+                      const char **         pp,
+                      const int *           typenums,
+                      const char *          p_end)
 {
   const char *orig;
   int rangenums[2];
@@ -1644,12 +1706,14 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
   bfd_boolean ov2, ov3;
 
   orig = *pp;
+  if (orig >= p_end)
+    return DEBUG_TYPE_NULL;
 
   index_type = DEBUG_TYPE_NULL;
 
   /* First comes a type we are a subrange of.
      In C it is usually 0, 1 or the type being defined.  */
-  if (! parse_stab_type_number (pp, rangenums))
+  if (! parse_stab_type_number (pp, rangenums, p_end))
     return DEBUG_TYPE_NULL;
 
   self_subrange = (rangenums[0] == typenums[0]
@@ -1659,7 +1723,7 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
     {
       *pp = orig;
       index_type = parse_stab_type (dhandle, info, (const char *) NULL,
-                                   pp, (debug_type **) NULL);
+                                   pp, (debug_type **) NULL, p_end);
       if (index_type == DEBUG_TYPE_NULL)
        return DEBUG_TYPE_NULL;
     }
@@ -1670,7 +1734,7 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
   /* The remaining two operands are usually lower and upper bounds of
      the range.  But in some special cases they mean something else.  */
   s2 = *pp;
-  n2 = parse_number (pp, &ov2);
+  n2 = parse_number (pp, &ov2, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1679,7 +1743,7 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
   ++*pp;
 
   s3 = *pp;
-  n3 = parse_number (pp, &ov3);
+  n3 = parse_number (pp, &ov3, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1732,11 +1796,11 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
                 long long int:t6=r1;0;-1;
                 long long unsigned int:t7=r1;0;-1;
             We hack here to handle this reasonably.  */
-         if (typename != NULL)
+         if (type_name != NULL)
            {
-             if (strcmp (typename, "long long int") == 0)
+             if (strcmp (type_name, "long long int") == 0)
                return debug_make_int_type (dhandle, 8, FALSE);
-             else if (strcmp (typename, "long long unsigned int") == 0)
+             else if (strcmp (type_name, "long long unsigned int") == 0)
                return debug_make_int_type (dhandle, 8, TRUE);
            }
          /* FIXME: The size here really depends upon the target.  */
@@ -1760,7 +1824,7 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
          else if (n3 == (bfd_signed_vma) 0xffffffff)
            return debug_make_int_type (dhandle, 4, TRUE);
 #ifdef BFD64
-         else if (n3 == ((((bfd_signed_vma) 0xffffffff) << 32) | 0xffffffff))
+         else if (n3 == (bfd_signed_vma) 0xffffffffffffffffLL)
            return debug_make_int_type (dhandle, 8, TRUE);
 #endif
        }
@@ -1817,13 +1881,15 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
    FIXME.  */
 
 static debug_type
-parse_stab_sun_builtin_type (void *dhandle, const char **pp)
+parse_stab_sun_builtin_type (void *dhandle, const char **pp, const char * p_end)
 {
   const char *orig;
   bfd_boolean unsignedp;
   bfd_vma bits;
 
   orig = *pp;
+  if (orig >= p_end)
+    return DEBUG_TYPE_NULL;
 
   switch (**pp)
     {
@@ -1839,18 +1905,20 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
     }
   ++*pp;
 
-  /* For some odd reason, all forms of char put a c here.  This is strange
-     because no other type has this honor.  We can safely ignore this because
-     we actually determine 'char'acterness by the number of bits specified in
-     the descriptor.  */
-  if (**pp == 'c')
+  /* OpenSolaris source code indicates that one of "cbv" characters
+     can come next and specify the intrinsic 'iformat' encoding.
+     'c' is character encoding, 'b' is boolean encoding, and 'v' is
+     varargs encoding.  This field can be safely ignored because
+     the type of the field is determined from the bitwidth extracted
+     below.  */
+  if (**pp == 'c' || **pp == 'b' || **pp == 'v')
     ++*pp;
 
   /* The first number appears to be the number of bytes occupied
      by this type, except that unsigned short is 4 instead of 2.
      Since this information is redundant with the third number,
      we will ignore it.  */
-  (void) parse_number (pp, (bfd_boolean *) NULL);
+  (void) parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1859,7 +1927,7 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
   ++*pp;
 
   /* The second number is always 0, so ignore it too.  */
-  (void) parse_number (pp, (bfd_boolean *) NULL);
+  (void) parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1868,7 +1936,7 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
   ++*pp;
 
   /* The third number is the number of bits for this type.  */
-  bits = parse_number (pp, (bfd_boolean *) NULL);
+  bits = parse_number (pp, (bfd_boolean *) NULL, p_end);
 
   /* The type *should* end with a semicolon.  If it are embedded
      in a larger type the semicolon may be the only way to know where
@@ -1888,17 +1956,19 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
 /* Parse a builtin floating type generated by the Sun compiler.  */
 
 static debug_type
-parse_stab_sun_floating_type (void *dhandle, const char **pp)
+parse_stab_sun_floating_type (void *dhandle, const char **pp, const char *p_end)
 {
   const char *orig;
   bfd_vma details;
   bfd_vma bytes;
 
   orig = *pp;
+  if (orig >= p_end)
+    return DEBUG_TYPE_NULL;
 
   /* The first number has more details about the type, for example
      FN_COMPLEX.  */
-  details = parse_number (pp, (bfd_boolean *) NULL);
+  details = parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1906,7 +1976,7 @@ parse_stab_sun_floating_type (void *dhandle, const char **pp)
     }
 
   /* The second number is the number of bytes occupied by this type */
-  bytes = parse_number (pp, (bfd_boolean *) NULL);
+  bytes = parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1924,7 +1994,7 @@ parse_stab_sun_floating_type (void *dhandle, const char **pp)
 /* Handle an enum type.  */
 
 static debug_type
-parse_stab_enum_type (void *dhandle, const char **pp)
+parse_stab_enum_type (void *dhandle, const char **pp, const char * p_end)
 {
   const char *orig;
   const char **names;
@@ -1933,6 +2003,8 @@ parse_stab_enum_type (void *dhandle, const char **pp)
   unsigned int alloc;
 
   orig = *pp;
+  if (orig >= p_end)
+    return DEBUG_TYPE_NULL;
 
   /* FIXME: gdb checks os9k_stabs here.  */
 
@@ -1940,8 +2012,14 @@ parse_stab_enum_type (void *dhandle, const char **pp)
      my guess is it's a type of some sort.  Just ignore it.  */
   if (**pp == '-')
     {
-      while (**pp != ':')
+      while (**pp != ':' && **pp != 0)
        ++*pp;
+
+      if (**pp == 0)
+       {
+         bad_stab (orig);
+         return DEBUG_TYPE_NULL;
+       }
       ++*pp;
     }
 
@@ -1959,16 +2037,27 @@ parse_stab_enum_type (void *dhandle, const char **pp)
       bfd_signed_vma val;
 
       p = *pp;
-      while (*p != ':')
+      while (*p != ':' && *p != 0)
        ++p;
 
+      if (*p == 0)
+       {
+         bad_stab (orig);
+         free (names);
+         free (values);
+         return DEBUG_TYPE_NULL;
+       }
+
       name = savestring (*pp, p - *pp);
 
       *pp = p + 1;
-      val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
+      val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL, p_end);
       if (**pp != ',')
        {
          bad_stab (orig);
+         free (name);
+         free (names);
+         free (values);
          return DEBUG_TYPE_NULL;
        }
       ++*pp;
@@ -2004,31 +2093,35 @@ parse_stab_enum_type (void *dhandle, const char **pp)
    *PP will point to "4a:1,0,32;;".  */
 
 static debug_type
-parse_stab_struct_type (void *dhandle, struct stab_handle *info,
-                       const char *tagname, const char **pp,
-                       bfd_boolean structp, const int *typenums)
+parse_stab_struct_type (void *                dhandle,
+                       struct stab_handle *  info,
+                       const char *          tagname,
+                       const char **         pp,
+                       bfd_boolean           structp,
+                       const int *           typenums,
+                       const char *          p_end)
 {
-  const char *orig;
   bfd_vma size;
   debug_baseclass *baseclasses;
-  debug_field *fields;
+  debug_field *fields = NULL;
   bfd_boolean statics;
   debug_method *methods;
   debug_type vptrbase;
   bfd_boolean ownvptr;
 
-  orig = *pp;
-
   /* Get the size.  */
-  size = parse_number (pp, (bfd_boolean *) NULL);
+  size = parse_number (pp, (bfd_boolean *) NULL, p_end);
 
   /* Get the other information.  */
-  if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
-      || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
-      || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
+  if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses, p_end)
+      || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics, p_end)
+      || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods, p_end)
       || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
-                                  &ownvptr))
-    return DEBUG_TYPE_NULL;
+                                  &ownvptr, p_end))
+    {
+      free (fields);
+      return DEBUG_TYPE_NULL;
+    }
 
   if (! statics
       && baseclasses == NULL
@@ -2066,8 +2159,11 @@ parse_stab_struct_type (void *dhandle, struct stab_handle *info,
   Return TRUE for success, FALSE for failure.  */
 
 static bfd_boolean
-parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
-                       const char **pp, debug_baseclass **retp)
+parse_stab_baseclasses (void *                dhandle,
+                       struct stab_handle *  info,
+                       const char **         pp,
+                       debug_baseclass **    retp,
+                       const char *          p_end)
 {
   const char *orig;
   unsigned int c, i;
@@ -2076,6 +2172,8 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
   *retp = NULL;
 
   orig = *pp;
+  if (orig >= p_end)
+    return FALSE;
 
   if (**pp != '!')
     {
@@ -2084,7 +2182,7 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
     }
   ++*pp;
 
-  c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL);
+  c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL, p_end);
 
   if (**pp != ',')
     {
@@ -2097,7 +2195,7 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
 
   for (i = 0; i < c; i++)
     {
-      bfd_boolean virtual;
+      bfd_boolean is_virtual;
       enum debug_visibility visibility;
       bfd_vma bitpos;
       debug_type type;
@@ -2105,14 +2203,17 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
       switch (**pp)
        {
        case '0':
-         virtual = FALSE;
+         is_virtual = FALSE;
          break;
        case '1':
-         virtual = TRUE;
+         is_virtual = TRUE;
          break;
+       case 0:
+         bad_stab (orig);
+         return FALSE;
        default:
          warn_stab (orig, _("unknown virtual character for baseclass"));
-         virtual = FALSE;
+         is_virtual = FALSE;
          break;
        }
       ++*pp;
@@ -2128,6 +2229,9 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
        case '2':
          visibility = DEBUG_VISIBILITY_PUBLIC;
          break;
+       case 0:
+         bad_stab (orig);
+         return FALSE;
        default:
          warn_stab (orig, _("unknown visibility character for baseclass"));
          visibility = DEBUG_VISIBILITY_PUBLIC;
@@ -2138,7 +2242,7 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
       /* The remaining value is the bit offset of the portion of the
         object corresponding to this baseclass.  Always zero in the
         absence of multiple inheritance.  */
-      bitpos = parse_number (pp, (bfd_boolean *) NULL);
+      bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end);
       if (**pp != ',')
        {
          bad_stab (orig);
@@ -2147,11 +2251,11 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
       ++*pp;
 
       type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                             (debug_type **) NULL);
+                             (debug_type **) NULL, p_end);
       if (type == DEBUG_TYPE_NULL)
        return FALSE;
 
-      classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
+      classes[i] = debug_make_baseclass (dhandle, type, bitpos, is_virtual,
                                         visibility);
       if (classes[i] == DEBUG_BASECLASS_NULL)
        return FALSE;
@@ -2189,9 +2293,12 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
    Returns 1 for success, 0 for failure.  */
 
 static bfd_boolean
-parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
-                         const char **pp, debug_field **retp,
-                         bfd_boolean *staticsp)
+parse_stab_struct_fields (void *                dhandle,
+                         struct stab_handle *  info,
+                         const char **         pp,
+                         debug_field **        retp,
+                         bfd_boolean *         staticsp,
+                         const char *          p_end)
 {
   const char *orig;
   const char *p;
@@ -2203,6 +2310,8 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
   *staticsp = FALSE;
 
   orig = *pp;
+  if (orig >= p_end)
+    return FALSE;
 
   c = 0;
   alloc = 10;
@@ -2231,8 +2340,11 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
       if ((*p == '$' || *p == '.') && p[1] != '_')
        {
          ++*pp;
-         if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
-           return FALSE;
+         if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c, p_end))
+           {
+             free (fields);
+             return FALSE;
+           }
          ++c;
          continue;
        }
@@ -2246,6 +2358,7 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
       if (p == NULL)
        {
          bad_stab (orig);
+         free (fields);
          return FALSE;
        }
 
@@ -2253,7 +2366,7 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
        break;
 
       if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
-                                        staticsp))
+                                        staticsp, p_end))
        return FALSE;
 
       ++c;
@@ -2269,20 +2382,25 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
 /* Special GNU C++ name.  */
 
 static bfd_boolean
-parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
-                      const char **pp, debug_field *retp)
+parse_stab_cpp_abbrev (void *                dhandle,
+                      struct stab_handle *  info,
+                      const char **         pp,
+                      debug_field *         retp,
+                      const char *          p_end)
 {
   const char *orig;
   int cpp_abbrev;
   debug_type context;
   const char *name;
-  const char *typename;
+  const char *type_name;
   debug_type type;
   bfd_vma bitpos;
 
   *retp = DEBUG_FIELD_NULL;
 
   orig = *pp;
+  if (orig >= p_end)
+    return FALSE;
 
   if (**pp != 'v')
     {
@@ -2292,6 +2410,11 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
   ++*pp;
 
   cpp_abbrev = **pp;
+  if (cpp_abbrev == 0)
+    {
+      bad_stab (orig);
+      return FALSE;
+    }
   ++*pp;
 
   /* At this point, *pp points to something like "22:23=*22...", where
@@ -2300,7 +2423,7 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
      name, and construct the field name.  */
 
   context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                            (debug_type **) NULL);
+                            (debug_type **) NULL, p_end);
   if (context == DEBUG_TYPE_NULL)
     return FALSE;
 
@@ -2312,13 +2435,13 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
       break;
     case 'b':
       /* $vb -- a virtual bsomethingorother */
-      typename = debug_get_type_name (dhandle, context);
-      if (typename == NULL)
+      type_name = debug_get_type_name (dhandle, context);
+      if (type_name == NULL)
        {
          warn_stab (orig, _("unnamed $vb type"));
-         typename = "FOO";
+         type_name = "FOO";
        }
-      name = concat ("_vb$", typename, (const char *) NULL);
+      name = concat ("_vb$", type_name, (const char *) NULL);
       break;
     default:
       warn_stab (orig, _("unrecognized C++ abbreviation"));
@@ -2334,7 +2457,7 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
   ++*pp;
 
   type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                         (debug_type **) NULL);
+                         (debug_type **) NULL, p_end);
   if (**pp != ',')
     {
       bad_stab (orig);
@@ -2342,7 +2465,7 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
     }
   ++*pp;
 
-  bitpos = parse_number (pp, (bfd_boolean *) NULL);
+  bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -2361,9 +2484,13 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
 /* Parse a single field in a struct or union.  */
 
 static bfd_boolean
-parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
-                            const char **pp, const char *p,
-                            debug_field *retp, bfd_boolean *staticsp)
+parse_stab_one_struct_field (void *                dhandle,
+                            struct stab_handle *  info,
+                            const char **         pp,
+                            const char *          p,
+                            debug_field *         retp,
+                            bfd_boolean *         staticsp,
+                            const char *          p_end)
 {
   const char *orig;
   char *name;
@@ -2373,6 +2500,8 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
   bfd_vma bitsize;
 
   orig = *pp;
+  if (orig >= p_end)
+    return FALSE;
 
   /* FIXME: gdb checks ARM_DEMANGLING here.  */
 
@@ -2396,6 +2525,9 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
        case '2':
          visibility = DEBUG_VISIBILITY_PUBLIC;
          break;
+       case 0:
+         bad_stab (orig);
+         return FALSE;
        default:
          warn_stab (orig, _("unknown visibility character for field"));
          visibility = DEBUG_VISIBILITY_PUBLIC;
@@ -2405,9 +2537,12 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
     }
 
   type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                         (debug_type **) NULL);
+                         (debug_type **) NULL, p_end);
   if (type == DEBUG_TYPE_NULL)
-    return FALSE;
+    {
+      free (name);
+      return FALSE;
+    }
 
   if (**pp == ':')
     {
@@ -2419,6 +2554,7 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
       if (p == NULL)
        {
          bad_stab (orig);
+         free (name);
          return FALSE;
        }
 
@@ -2436,22 +2572,25 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
   if (**pp != ',')
     {
       bad_stab (orig);
+      free (name);
       return FALSE;
     }
   ++*pp;
 
-  bitpos = parse_number (pp, (bfd_boolean *) NULL);
+  bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ',')
     {
       bad_stab (orig);
+      free (name);
       return FALSE;
     }
   ++*pp;
 
-  bitsize = parse_number (pp, (bfd_boolean *) NULL);
+  bitsize = parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
+      free (name);
       return FALSE;
     }
   ++*pp;
@@ -2495,18 +2634,27 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
    name (such as `+=') and `.' marks the end of the operator name.  */
 
 static bfd_boolean
-parse_stab_members (void *dhandle, struct stab_handle *info,
-                   const char *tagname, const char **pp,
-                   const int *typenums, debug_method **retp)
+parse_stab_members (void *                dhandle,
+                   struct stab_handle *  info,
+                   const char *          tagname,
+                   const char **         pp,
+                   const int *           typenums,
+                   debug_method **       retp,
+                   const char *          p_end)
 {
   const char *orig;
   debug_method *methods;
   unsigned int c;
   unsigned int alloc;
+  char *name = NULL;
+  debug_method_variant *variants = NULL;
+  char *argtypes = NULL;
 
   *retp = NULL;
 
   orig = *pp;
+  if (orig >= p_end)
+    return FALSE;
 
   alloc = 0;
   methods = NULL;
@@ -2515,8 +2663,6 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
   while (**pp != ';')
     {
       const char *p;
-      char *name;
-      debug_method_variant *variants;
       unsigned int cvars;
       unsigned int allocvars;
       debug_type look_ahead_type;
@@ -2545,7 +2691,7 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
          if (*p != '.')
            {
              bad_stab (orig);
-             return FALSE;
+             goto fail;
            }
          name = savestring (*pp, p - *pp);
          *pp = p + 1;
@@ -2562,7 +2708,6 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
        {
          debug_type type;
          bfd_boolean stub;
-         char *argtypes;
          enum debug_visibility visibility;
          bfd_boolean constp, volatilep, staticp;
          bfd_vma voffset;
@@ -2579,13 +2724,14 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
          else
            {
              type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                     (debug_type **) NULL);
+                                     (debug_type **) NULL, p_end);
              if (type == DEBUG_TYPE_NULL)
-               return FALSE;
+               goto fail;
+
              if (**pp != ':')
                {
                  bad_stab (orig);
-                 return FALSE;
+                 goto fail;
                }
            }
 
@@ -2594,7 +2740,7 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
          if (p == NULL)
            {
              bad_stab (orig);
-             return FALSE;
+             goto fail;
            }
 
          stub = FALSE;
@@ -2613,6 +2759,9 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
            case '1':
              visibility = DEBUG_VISIBILITY_PROTECTED;
              break;
+           case 0:
+             bad_stab (orig);
+             goto fail;
            default:
              visibility = DEBUG_VISIBILITY_PUBLIC;
              break;
@@ -2659,18 +2808,18 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
            case '*':
              /* virtual member function, followed by index.  The sign
                 bit is supposedly set to distinguish
-                pointers-to-methods from virtual function indicies.  */
+                pointers-to-methods from virtual function indices.  */
              ++*pp;
-             voffset = parse_number (pp, (bfd_boolean *) NULL);
+             voffset = parse_number (pp, (bfd_boolean *) NULL, p_end);
              if (**pp != ';')
                {
                  bad_stab (orig);
-                 return FALSE;
+                 goto fail;
                }
              ++*pp;
              voffset &= 0x7fffffff;
 
-             if (**pp == ';' || *pp == '\0')
+             if (**pp == ';' || **pp == '\0')
                {
                  /* Must be g++ version 1.  */
                  context = DEBUG_TYPE_NULL;
@@ -2683,7 +2832,8 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
                  look_ahead_type = parse_stab_type (dhandle, info,
                                                     (const char *) NULL,
                                                     pp,
-                                                    (debug_type **) NULL);
+                                                    (debug_type **) NULL,
+                                                    p_end);
                  if (**pp == ':')
                    {
                      /* g++ version 1 overloaded methods.  */
@@ -2696,7 +2846,7 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
                      if (**pp != ';')
                        {
                          bad_stab (orig);
-                         return FALSE;
+                         goto fail;
                        }
                      ++*pp;
                    }
@@ -2731,26 +2881,25 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
              argtypes string is the mangled form of the argument
              types, and the full type and the physical name must be
              extracted from them.  */
-         if (! stub)
-           physname = argtypes;
-         else
+         physname = argtypes;
+         if (stub)
            {
              debug_type class_type, return_type;
 
              class_type = stab_find_type (dhandle, info, typenums);
              if (class_type == DEBUG_TYPE_NULL)
-               return FALSE;
+               goto fail;
              return_type = debug_get_return_type (dhandle, type);
              if (return_type == DEBUG_TYPE_NULL)
                {
                  bad_stab (orig);
-                 return FALSE;
+                 goto fail;
                }
              type = parse_stab_argtypes (dhandle, info, class_type, name,
                                          tagname, return_type, argtypes,
                                          constp, volatilep, &physname);
              if (type == DEBUG_TYPE_NULL)
-               return FALSE;
+               goto fail;
            }
 
          if (cvars + 1 >= allocvars)
@@ -2774,7 +2923,7 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
                                                                constp,
                                                                volatilep);
          if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
-           return FALSE;
+           goto fail;
 
          ++cvars;
        }
@@ -2803,6 +2952,12 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
   *retp = methods;
 
   return TRUE;
+
+ fail:
+  free (name);
+  free (variants);
+  free (argtypes);
+  return FALSE;
 }
 
 /* Parse a string representing argument types for a method.  Stabs
@@ -2843,9 +2998,7 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info,
                   || CONST_STRNEQ (argtypes, "__dt"));
   is_v3 = argtypes[0] == '_' && argtypes[1] == 'Z';
 
-  if (is_destructor || is_full_physname_constructor || is_v3)
-    *pphysname = argtypes;
-  else
+  if (!(is_destructor || is_full_physname_constructor || is_v3))
     {
       unsigned int len;
       const char *const_prefix;
@@ -2880,27 +3033,15 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info,
          && fieldname[1] == 'p'
          && (fieldname[2] == '$' || fieldname[2] == '.'))
        {
-         const char *opname;
-
-         opname = cplus_mangle_opname (fieldname + 3, 0);
-         if (opname == NULL)
-           {
-             fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname);
-             return DEBUG_TYPE_NULL;
-           }
-         mangled_name_len += strlen (opname);
-         physname = (char *) xmalloc (mangled_name_len);
-         strncpy (physname, fieldname, 3);
-         strcpy (physname + 3, opname);
+         /* Opname selection is no longer supported by libiberty's demangler.  */
+         return DEBUG_TYPE_NULL;
        }
+
+      physname = (char *) xmalloc (mangled_name_len);
+      if (is_constructor)
+       physname[0] = '\0';
       else
-       {
-         physname = (char *) xmalloc (mangled_name_len);
-         if (is_constructor)
-           physname[0] = '\0';
-         else
-           strcpy (physname, fieldname);
-       }
+       strcpy (physname, fieldname);
 
       physname_len = strlen (physname);
       strcat (physname, buf);
@@ -2936,9 +3077,13 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info,
    so we can look for the vptr base class info.  */
 
 static bfd_boolean
-parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
-                       const char **pp, const int *typenums,
-                       debug_type *retvptrbase, bfd_boolean *retownvptr)
+parse_stab_tilde_field (void *                dhandle,
+                       struct stab_handle *  info,
+                       const char **         pp,
+                       const int *           typenums,
+                       debug_type *          retvptrbase,
+                       bfd_boolean *         retownvptr,
+                       const char *          p_end)
 {
   const char *orig;
   const char *hold;
@@ -2948,14 +3093,15 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
   *retownvptr = FALSE;
 
   orig = *pp;
-
+  if (orig >= p_end)
+    return FALSE;
+  
   /* If we are positioned at a ';', then skip it.  */
   if (**pp == ';')
     ++*pp;
 
   if (**pp != '~')
     return TRUE;
-
   ++*pp;
 
   if (**pp == '=' || **pp == '+' || **pp == '-')
@@ -2967,14 +3113,13 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
 
   if (**pp != '%')
     return TRUE;
-
   ++*pp;
 
   hold = *pp;
 
   /* The next number is the type number of the base class (possibly
      our own class) which supplies the vtable for this class.  */
-  if (! parse_stab_type_number (pp, vtypenums))
+  if (! parse_stab_type_number (pp, vtypenums, p_end))
     return FALSE;
 
   if (vtypenums[0] == typenums[0]
@@ -2988,7 +3133,7 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
       *pp = hold;
 
       vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                              (debug_type **) NULL);
+                              (debug_type **) NULL, p_end);
       for (p = *pp; *p != ';' && *p != '\0'; p++)
        ;
       if (*p != ';')
@@ -3008,8 +3153,11 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
 /* Read a definition of an array type.  */
 
 static debug_type
-parse_stab_array_type (void *dhandle, struct stab_handle *info,
-                      const char **pp, bfd_boolean stringp)
+parse_stab_array_type (void *                dhandle,
+                      struct stab_handle *  info,
+                      const char **         pp,
+                      bfd_boolean           stringp,
+                      const char *          p_end)
 {
   const char *orig;
   const char *p;
@@ -3027,13 +3175,16 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
      for these, produce a type like float[][].  */
 
   orig = *pp;
+  if (orig >= p_end)
+    return DEBUG_TYPE_NULL;
 
   /* FIXME: gdb checks os9k_stabs here.  */
 
   /* If the index type is type 0, we take it as int.  */
   p = *pp;
-  if (! parse_stab_type_number (&p, typenums))
+  if (! parse_stab_type_number (&p, typenums, p_end))
     return DEBUG_TYPE_NULL;
+
   if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
     {
       index_type = debug_find_named_type (dhandle, "int");
@@ -3048,7 +3199,7 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
   else
     {
       index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                   (debug_type **) NULL);
+                                   (debug_type **) NULL, p_end);
     }
 
   if (**pp != ';')
@@ -3060,13 +3211,13 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
 
   adjustable = FALSE;
 
-  if (! ISDIGIT (**pp) && **pp != '-')
+  if (! ISDIGIT (**pp) && **pp != '-' && **pp != 0)
     {
       ++*pp;
       adjustable = TRUE;
     }
 
-  lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
+  lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -3074,13 +3225,13 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
     }
   ++*pp;
 
-  if (! ISDIGIT (**pp) && **pp != '-')
+  if (! ISDIGIT (**pp) && **pp != '-' && **pp != 0)
     {
       ++*pp;
       adjustable = TRUE;
     }
 
-  upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
+  upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL, p_end);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -3089,7 +3240,7 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
   ++*pp;
 
   element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                 (debug_type **) NULL);
+                                 (debug_type **) NULL, p_end);
   if (element_type == DEBUG_TYPE_NULL)
     return DEBUG_TYPE_NULL;
 
@@ -3160,6 +3311,9 @@ pop_bincl (struct stab_handle *info)
     return info->main_filename;
   info->bincl_stack = o->next_stack;
 
+  if (o->file >= info->files)
+    return info->main_filename;
+
   o->file_types = info->file_types[o->file];
 
   if (info->bincl_stack == NULL)
@@ -3257,26 +3411,26 @@ static debug_type *
 stab_find_slot (struct stab_handle *info, const int *typenums)
 {
   int filenum;
-  int index;
+  int tindex;
   struct stab_types **ps;
 
   filenum = typenums[0];
-  index = typenums[1];
+  tindex = typenums[1];
 
   if (filenum < 0 || (unsigned int) filenum >= info->files)
     {
       fprintf (stderr, _("Type file number %d out of range\n"), filenum);
       return NULL;
     }
-  if (index < 0)
+  if (tindex < 0)
     {
-      fprintf (stderr, _("Type index number %d out of range\n"), index);
+      fprintf (stderr, _("Type index number %d out of range\n"), tindex);
       return NULL;
     }
 
   ps = info->file_types + filenum;
 
-  while (index >= STAB_TYPES_SLOTS)
+  while (tindex >= STAB_TYPES_SLOTS)
     {
       if (*ps == NULL)
        {
@@ -3284,7 +3438,7 @@ stab_find_slot (struct stab_handle *info, const int *typenums)
          memset (*ps, 0, sizeof **ps);
        }
       ps = &(*ps)->next;
-      index -= STAB_TYPES_SLOTS;
+      tindex -= STAB_TYPES_SLOTS;
     }
   if (*ps == NULL)
     {
@@ -3292,7 +3446,7 @@ stab_find_slot (struct stab_handle *info, const int *typenums)
       memset (*ps, 0, sizeof **ps);
     }
 
-  return (*ps)->types + index;
+  return (*ps)->types + tindex;
 }
 
 /* Find a type given a type number.  If the type has not been
@@ -3394,6 +3548,7 @@ stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
     case 9:
       name = "unsigned";
       rettype = debug_make_int_type (dhandle, 4, TRUE);
+      break;
     case 10:
       name = "unsigned long";
       rettype = debug_make_int_type (dhandle, 4, TRUE);
@@ -3742,8 +3897,7 @@ stab_demangle_argtypes (void *dhandle, struct stab_handle *info,
   return minfo.args;
 
  error_return:
-  if (minfo.typestrings != NULL)
-    free (minfo.typestrings);
+  free (minfo.typestrings);
   return NULL;
 }
 
@@ -4100,7 +4254,10 @@ stab_demangle_qualified (struct stab_demangle_info *minfo, const char **pp,
 
                      ft = debug_get_field_type (minfo->dhandle, *fields);
                      if (ft == NULL)
-                       return FALSE;
+                       {
+                         free (name);
+                         return FALSE;
+                       }
                      dn = debug_get_type_name (minfo->dhandle, ft);
                      if (dn != NULL && strcmp (dn, name) == 0)
                        {
@@ -4345,7 +4502,7 @@ stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
 
       free (s1);
 
-      s3 = cplus_demangle (s2, DMGL_ANSI);
+      s3 = cplus_demangle (s2, demangle_flags);
 
       free (s2);
 
@@ -4354,8 +4511,7 @@ stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
       if (s3 == NULL || s4 == NULL)
        {
          stab_bad_demangle (orig);
-         if (s3 != NULL)
-           free (s3);
+         free (s3);
          return FALSE;
        }
 
@@ -4647,7 +4803,7 @@ stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
     case 'M':
     case 'O':
       {
-       bfd_boolean memberp, constp, volatilep;
+       bfd_boolean memberp;
        debug_type class_type = DEBUG_TYPE_NULL;
        debug_type *args;
        bfd_boolean varargs;
@@ -4655,8 +4811,6 @@ stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
        const char *name;
 
        memberp = **pp == 'M';
-       constp = FALSE;
-       volatilep = FALSE;
        args = NULL;
        varargs = FALSE;
 
@@ -4700,12 +4854,10 @@ stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
          {
            if (**pp == 'C')
              {
-               constp = TRUE;
                ++*pp;
              }
            else if (**pp == 'V')
              {
-               volatilep = TRUE;
                ++*pp;
              }
            if (**pp != 'F')
@@ -4766,9 +4918,6 @@ stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
 
     case 'Q':
       {
-       const char *hold;
-
-       hold = *pp;
        if (! stab_demangle_qualified (minfo, pp, ptype))
          return FALSE;
       }
@@ -5078,7 +5227,7 @@ stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
   void *mem;
   debug_type *pargs;
 
-  dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem);
+  dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | demangle_flags, &mem);
   if (dc == NULL)
     {
       stab_bad_demangle (physname);
@@ -5137,6 +5286,11 @@ stab_demangle_v3_arglist (void *dhandle, struct stab_handle *info,
          return NULL;
        }
 
+      /* PR 13925: Cope if the demangler returns an empty
+        context for a function with no arguments.  */
+      if (dc->u.s_binary.left == NULL)
+       break;
+
       arg = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
                                  NULL, &varargs);
       if (arg == NULL)
@@ -5248,7 +5402,7 @@ stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
        /* We print this component to get a class name which we can
           use.  FIXME: This probably won't work if the template uses
           template parameters which refer to an outer template.  */
-       p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+       p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
        if (p == NULL)
          {
            fprintf (stderr, _("Failed to print demangled template\n"));
@@ -5328,7 +5482,7 @@ stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
        /* We print this component in order to find out the type name.
           FIXME: Should we instead expose the
           demangle_builtin_type_info structure?  */
-       p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+       p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
        if (p == NULL)
          {
            fprintf (stderr, _("Couldn't get demangled builtin type\n"));
This page took 0.049131 seconds and 4 git commands to generate.