/* stabs.c -- Parse stabs debugging information
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GNU Binutils.
trying to identify the correct address for anything. */
#include <stdio.h>
-#include <ctype.h>
#include "bfd.h"
#include "bucomm.h"
#include "libiberty.h"
+#include "safe-ctype.h"
#include "demangle.h"
#include "debug.h"
#include "budbg.h"
+#include "filenames.h"
/* Meaningless definition needs by aout64.h. FIXME. */
#define BYTES_IN_WORD 4
#include "aout/aout64.h"
#include "aout/stab_gnu.h"
-#ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
-#endif
-
/* The number of predefined XCOFF types. */
#define XCOFF_TYPE_COUNT 34
int d;
d = *p++;
- if (isdigit ((unsigned char) d))
+ if (ISDIGIT (d))
d -= '0';
- else if (isupper ((unsigned char) d))
+ else if (ISUPPER (d))
d -= 'A';
- else if (islower ((unsigned char) d))
+ else if (ISLOWER (d))
d -= 'a';
else
break;
/* Create a handle to parse stabs symbols with. */
-/*ARGSUSED*/
PTR
start_stab (dhandle, abfd, sections, syms, symcount)
- PTR dhandle;
+ PTR dhandle ATTRIBUTE_UNUSED;
bfd *abfd;
boolean sections;
asymbol **syms;
f = info->so_string;
- if ( (string[0] == '/')
- || (string[0] == DIR_SEPARATOR)
- || ( (DIR_SEPARATOR == '\\')
- && (string[1] == ':')
- && ( (string[2] == DIR_SEPARATOR)
- || (string[2] == '/'))))
+ if (IS_ABSOLUTE_PATH (string))
info->so_string = xstrdup (string);
else
info->so_string = concat (info->so_string, string,
case N_OBJ:
case N_ENDM:
case N_MAIN:
+ case N_WARNING:
break;
}
}
++p;
- if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+ if (ISDIGIT (*p) || *p == '(' || *p == '-')
type = 'l';
else
type = *p++;
/* Read type number if present. The type number may be omitted.
for instance in a two-dimensional array declared with type
"ar1;1;10;ar1;1;10;4". */
- if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '(' && **pp != '-')
{
/* 'typenums=' not present, type is anonymous. Read and return
the definition, but don't put it in the type vector. */
const char *p = *pp + 1;
const char *attr;
- if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+ if (ISDIGIT (*p) || *p == '(' || *p == '-')
{
/* Member type. */
break;
{
case 's':
size = atoi (attr + 1);
+ size /= 8; /* Size is in bits. We store it in bytes. */
if (size <= 0)
size = -1;
break;
bad_stab (orig);
return DEBUG_TYPE_NULL;
}
- while (q1 != NULL && p > q1 && p[1] == ':')
+ if (q1 != NULL && p > q1 && p[1] == ':')
{
- q2 = strchr (q1, '>');
- if (q2 == NULL || q2 < p)
- break;
- p += 2;
- p = strchr (p, ':');
- if (p == NULL)
+ int nest = 0;
+
+ for (q2 = q1; *q2 != '\0'; ++q2)
+ {
+ if (*q2 == '<')
+ ++nest;
+ else if (*q2 == '>')
+ --nest;
+ else if (*q2 == ':' && nest == 0)
+ break;
+ }
+ p = q2;
+ if (*p != ':')
{
bad_stab (orig);
return DEBUG_TYPE_NULL;
if (size != -1)
{
if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
- return false;
+ return DEBUG_TYPE_NULL;
}
return dtype;
return debug_make_int_type (dhandle, 1, true);
else if (n3 == 0xffff)
return debug_make_int_type (dhandle, 2, true);
- /* -1 is used for the upper bound of (4 byte) "unsigned int"
- and "unsigned long", and we already checked for that, so
- don't need to test for it here. */
+ 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))
+ return debug_make_int_type (dhandle, 8, true);
+#endif
}
else if (n3 == 0
&& n2 < 0
&& (self_subrange || n2 == -8))
return debug_make_int_type (dhandle, - n2, true);
- else if (n2 == - n3 - 1)
+ else if (n2 == - n3 - 1 || n2 == n3 + 1)
{
if (n3 == 0x7f)
return debug_make_int_type (dhandle, 1, false);
return debug_make_int_type (dhandle, 2, false);
else if (n3 == 0x7fffffff)
return debug_make_int_type (dhandle, 4, false);
+#ifdef BFD64
+ else if (n3 == ((((bfd_vma) 0x7fffffff) << 32) | 0xffffffff))
+ return debug_make_int_type (dhandle, 8, false);
+#endif
}
}
}
++*pp;
- /* The second number is always 0, so ignore it too. */
+ /* The second number is always 0, so ignore it too. */
(void) parse_number (pp, (boolean *) NULL);
if (**pp != ';')
{
}
++*pp;
- /* The third number is the number of bits for this type. */
+ /* The third number is the number of bits for this type. */
bits = parse_number (pp, (boolean *) NULL);
/* The type *should* end with a semicolon. If it are embedded
|| details == NF_COMPLEX32)
return debug_make_complex_type (dhandle, bytes);
- return debug_make_float_type (dhandle, bytes);
+ return debug_make_float_type (dhandle, bytes);
}
/* Handle an enum type. */
/* Look for the ':' that separates the field name from the field
values. Data members are delimited by a single ':', while member
functions are delimited by a pair of ':'s. When we hit the member
- functions (if any), terminate scan loop and return. */
+ functions (if any), terminate scan loop and return. */
p = strchr (p, ':');
if (p == NULL)
/* Figure out from whence this virtual function
came. It may belong to virtual function table of
one of its baseclasses. */
- look_ahead_type = parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL);
- if (**pp == ':')
- {
- /* g++ version 1 overloaded methods. */
- context = DEBUG_TYPE_NULL;
- }
- else
- {
- context = look_ahead_type;
- look_ahead_type = DEBUG_TYPE_NULL;
- if (**pp != ';')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
- }
- }
+ look_ahead_type = parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL);
+ if (**pp == ':')
+ {
+ /* g++ version 1 overloaded methods. */
+ context = DEBUG_TYPE_NULL;
+ }
+ else
+ {
+ context = look_ahead_type;
+ look_ahead_type = DEBUG_TYPE_NULL;
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ }
+ }
break;
case '?':
/* Constructors are sometimes handled specially. */
is_full_physname_constructor = ((argtypes[0] == '_'
&& argtypes[1] == '_'
- && (isdigit ((unsigned char) argtypes[2])
+ && (ISDIGIT (argtypes[2])
|| argtypes[2] == 'Q'
|| argtypes[2] == 't'))
|| strncmp (argtypes, "__ct", 4) == 0);
orig = *pp;
- /* If we are positioned at a ';', then skip it. */
+ /* If we are positioned at a ';', then skip it. */
if (**pp == ';')
++*pp;
if (**pp == '=' || **pp == '+' || **pp == '-')
{
/* Obsolete flags that used to indicate the presence of
- constructors and/or destructors. */
+ constructors and/or destructors. */
++*pp;
}
*pp = p + 1;
}
- return true;
+ return true;
}
/* Read a definition of an array type. */
/* If the index type is type 0, we take it as int. */
p = *pp;
if (! parse_stab_type_number (&p, typenums))
- return false;
+ return DEBUG_TYPE_NULL;
if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
{
index_type = debug_find_named_type (dhandle, "int");
{
index_type = debug_make_int_type (dhandle, 4, false);
if (index_type == DEBUG_TYPE_NULL)
- return false;
+ return DEBUG_TYPE_NULL;
}
*pp = p;
}
adjustable = false;
- if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '-')
{
++*pp;
adjustable = true;
if (**pp != ';')
{
bad_stab (orig);
- return false;
+ return DEBUG_TYPE_NULL;
}
++*pp;
- if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '-')
{
++*pp;
adjustable = true;
if (**pp != ';')
{
bad_stab (orig);
- return false;
+ return DEBUG_TYPE_NULL;
}
++*pp;
element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (element_type == DEBUG_TYPE_NULL)
- return false;
+ return DEBUG_TYPE_NULL;
if (adjustable)
{
static boolean
stab_record_type (dhandle, info, typenums, type)
- PTR dhandle;
+ PTR dhandle ATTRIBUTE_UNUSED;
struct stab_handle *info;
const int *typenums;
debug_type type;
static boolean stab_demangle_qualified
PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
static boolean stab_demangle_template
- PARAMS ((struct stab_demangle_info *, const char **));
+ PARAMS ((struct stab_demangle_info *, const char **, char **));
static boolean stab_demangle_class
PARAMS ((struct stab_demangle_info *, const char **, const char **));
static boolean stab_demangle_args
unsigned int count;
count = 0;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
{
count *= 10;
count += **pp - '0';
const char **pp;
unsigned int *pi;
{
- if (! isdigit ((unsigned char) **pp))
+ if (! ISDIGIT (**pp))
return false;
*pi = **pp - '0';
++*pp;
- if (isdigit ((unsigned char) **pp))
+ if (ISDIGIT (**pp))
{
unsigned int count;
const char *p;
count += *p - '0';
++p;
}
- while (isdigit ((unsigned char) *p));
+ while (ISDIGIT (*p));
if (*p == '_')
{
*pp = p + 1;
scan += i - 2;
if (scan == *pp
- && (isdigit ((unsigned char) scan[2])
+ && (ISDIGIT (scan[2])
|| scan[2] == 'Q'
|| scan[2] == 't'))
{
return true;
}
else if (scan == *pp
- && ! isdigit ((unsigned char) scan[2])
+ && ! ISDIGIT (scan[2])
&& scan[2] != 't')
{
/* Look for the `__' that separates the prefix from the
/* Template. */
if (hold == NULL)
hold = *pp;
- if (! stab_demangle_template (minfo, pp)
+ if (! stab_demangle_template (minfo, pp, (char **) NULL)
|| ! stab_demangle_remember_type (minfo, hold, *pp - hold))
return false;
hold = NULL;
preceded by an underscore (to distinguish it from the <= 9
case) and followed by an underscore. */
p = *pp + 2;
- if (! isdigit ((unsigned char) *p) || *p == '0')
+ if (! ISDIGIT (*p) || *p == '0')
{
stab_bad_demangle (orig);
return false;
}
qualifiers = atoi (p);
- while (isdigit ((unsigned char) *p))
+ while (ISDIGIT (*p))
++p;
if (*p != '_')
{
++*pp;
if (**pp == 't')
{
- /* FIXME: I don't know how to handle the ptype != NULL case
- here. */
- if (! stab_demangle_template (minfo, pp))
+ char *name;
+
+ if (! stab_demangle_template (minfo, pp,
+ ptype != NULL ? &name : NULL))
return false;
+
+ if (ptype != NULL)
+ {
+ context = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ name, strlen (name),
+ DEBUG_KIND_CLASS);
+ free (name);
+ if (context == DEBUG_TYPE_NULL)
+ return false;
+ }
}
else
{
if (context == DEBUG_TYPE_NULL)
{
- /* We have to fall back on finding the type by name.
+ /* We have to fall back on finding the type by name.
If there are more types to come, then this must
be a class. Otherwise, it could be anything. */
return true;
}
-/* Demangle a template. */
+/* Demangle a template. If PNAME is not NULL, this sets *PNAME to a
+ string representation of the template. */
static boolean
-stab_demangle_template (minfo, pp)
+stab_demangle_template (minfo, pp, pname)
struct stab_demangle_info *minfo;
const char **pp;
+ char **pname;
{
const char *orig;
unsigned int r, i;
{
if (**pp == 'm')
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
}
else if (charp)
{
if (**pp == 'm')
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
if (**pp == '.')
{
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
}
if (**pp == 'e')
{
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
}
}
}
}
+ /* We can translate this to a string fairly easily by invoking the
+ regular demangling routine. */
+ if (pname != NULL)
+ {
+ char *s1, *s2, *s3, *s4 = NULL;
+ char *from, *to;
+
+ s1 = savestring (orig, *pp - orig);
+
+ s2 = concat ("NoSuchStrinG__", s1, (const char *) NULL);
+
+ free (s1);
+
+ s3 = cplus_demangle (s2, DMGL_ANSI);
+
+ free (s2);
+
+ if (s3 != NULL)
+ s4 = strstr (s3, "::NoSuchStrinG");
+ if (s3 == NULL || s4 == NULL)
+ {
+ stab_bad_demangle (orig);
+ if (s3 != NULL)
+ free (s3);
+ return false;
+ }
+
+ /* Eliminating all spaces, except those between > characters,
+ makes it more likely that the demangled name will match the
+ name which g++ used as the structure name. */
+ for (from = to = s3; from != s4; ++from)
+ if (*from != ' '
+ || (from[1] == '>' && from > s3 && from[-1] == '>'))
+ *to++ = *from;
+
+ *pname = savestring (s3, to - s3);
+
+ free (s3);
+ }
+
return true;
}
static boolean
stab_demangle_class (minfo, pp, pstart)
- struct stab_demangle_info *minfo;
+ struct stab_demangle_info *minfo ATTRIBUTE_UNUSED;
const char **pp;
const char **pstart;
{
high = 0;
while (**pp != '\0' && **pp != '_')
{
- if (! isdigit ((unsigned char) **pp))
+ if (! ISDIGIT (**pp))
{
stab_bad_demangle (orig);
return false;
case 'O':
{
boolean memberp, constp, volatilep;
+ debug_type class_type = DEBUG_TYPE_NULL;
debug_type *args;
boolean varargs;
unsigned int n;
varargs = false;
++*pp;
- if (! isdigit ((unsigned char) **pp))
+ if (ISDIGIT (**pp))
{
- stab_bad_demangle (orig);
- return false;
+ n = stab_demangle_count (pp);
+ if (strlen (*pp) < n)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ name = *pp;
+ *pp += n;
+
+ if (ptype != NULL)
+ {
+ class_type = stab_find_tagged_type (minfo->dhandle,
+ minfo->info,
+ name, (int) n,
+ DEBUG_KIND_CLASS);
+ if (class_type == DEBUG_TYPE_NULL)
+ return false;
+ }
+ }
+ else if (**pp == 'Q')
+ {
+ if (! stab_demangle_qualified (minfo, pp,
+ (ptype == NULL
+ ? (debug_type *) NULL
+ : &class_type)))
+ return false;
}
- n = stab_demangle_count (pp);
- if (strlen (*pp) < n)
+ else
{
stab_bad_demangle (orig);
return false;
}
- name = *pp;
- *pp += n;
if (memberp)
{
if (ptype != NULL)
{
- debug_type class_type;
-
- class_type = stab_find_tagged_type (minfo->dhandle, minfo->info,
- name, (int) n,
- DEBUG_KIND_CLASS);
- if (class_type == DEBUG_TYPE_NULL)
- return false;
-
if (! memberp)
*ptype = debug_make_offset_type (minfo->dhandle, class_type,
*ptype);
case 'G':
++*pp;
- if (! isdigit ((unsigned char) **pp))
+ if (! ISDIGIT (**pp))
{
stab_bad_demangle (orig);
return false;
name = savestring (hold, *pp - hold);
*ptype = debug_find_named_type (minfo->dhandle, name);
+ free (name);
if (*ptype == DEBUG_TYPE_NULL)
{
/* FIXME: It is probably incorrect to assume that
*ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
hold, *pp - hold,
DEBUG_KIND_ILLEGAL);
+ if (*ptype == DEBUG_TYPE_NULL)
+ return false;
}
- free (name);
}
}
break;
case 't':
- if (! stab_demangle_template (minfo, pp))
- return false;
- if (ptype != NULL)
- {
- debug_type t;
-
- /* FIXME: I really don't know how a template should be
- represented in the current type system. Perhaps the
- template should be demangled into a string, and the type
- should be represented as a named type. However, I don't
- know what the base type of the named type should be. */
- t = debug_make_void_type (minfo->dhandle);
- t = debug_make_pointer_type (minfo->dhandle, t);
- t = debug_name_type (minfo->dhandle, "TEMPLATE", t);
- *ptype = t;
- }
+ {
+ char *name;
+
+ if (! stab_demangle_template (minfo, pp,
+ ptype != NULL ? &name : NULL))
+ return false;
+ if (ptype != NULL)
+ {
+ *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ name, strlen (name),
+ DEBUG_KIND_CLASS);
+ free (name);
+ if (*ptype == DEBUG_TYPE_NULL)
+ return false;
+ }
+ }
break;
default: