X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Fstabs.c;h=9f043d1191bb317d7303ad6e3b70b865f192da52;hb=5fd104addfddb68844fb8df67be832ee98ad9888;hp=879a3e2c7a7065906d44dc65d1d8d2667fd58743;hpb=b43b5d5f768ed7a7a150d78c9fda0c194a11497d;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/stabs.c b/binutils/stabs.c index 879a3e2c7a..9f043d1191 100644 --- a/binutils/stabs.c +++ b/binutils/stabs.c @@ -1,13 +1,12 @@ /* stabs.c -- Parse stabs debugging information - Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. + Copyright (C) 1995-2020 Free Software Foundation, Inc. Written by Ian Lance Taylor . 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, @@ -25,10 +24,8 @@ code. The job it does is somewhat different, because it is not trying to identify the correct address for anything. */ -#include - +#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); @@ -1696,12 +1760,12 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type #define ULLHIGH "01777777777777777777777;" if (index_type == DEBUG_TYPE_NULL) { - if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0 - && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0) + if (CONST_STRNEQ (s2, LLLOW) + && CONST_STRNEQ (s3, LLHIGH)) return debug_make_int_type (dhandle, 8, FALSE); if (! ov2 && n2 == 0 - && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0) + && CONST_STRNEQ (s3, ULLHIGH)) return debug_make_int_type (dhandle, 8, TRUE); } @@ -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 @@ -2832,7 +2987,7 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info, && (ISDIGIT (argtypes[2]) || argtypes[2] == 'Q' || argtypes[2] == 't')) - || strncmp (argtypes, "__ct", 4) == 0); + || CONST_STRNEQ (argtypes, "__ct")); is_constructor = (is_full_physname_constructor || (tagname != NULL @@ -2840,12 +2995,10 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info, is_destructor = ((argtypes[0] == '_' && (argtypes[1] == '$' || argtypes[1] == '.') && argtypes[2] == '_') - || strncmp (argtypes, "__dt", 4) == 0); + || 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; } @@ -3841,7 +3995,7 @@ stab_demangle_function_name (struct stab_demangle_info *minfo, *pp = scan + 2; if (*pp - name >= 5 - && strncmp (name, "type", 4) == 0 + && CONST_STRNEQ (name, "type") && (name[4] == '$' || name[4] == '.')) { const char *tem; @@ -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"));