struct stab_handle
{
+ /* The BFD. */
+ bfd *abfd;
/* True if this is stabs in sections. */
boolean sections;
- /* The type of the last stab symbol, so that we can detect N_SO
- pairs. */
- int last_type;
+ /* The symbol table. */
+ asymbol **syms;
+ /* The number of symbols. */
+ long symcount;
+ /* The accumulated file name string. */
+ char *so_string;
+ /* The value of the last N_SO symbol. */
+ bfd_vma so_value;
/* The value of the start of the file, so that we can handle file
relative N_LBRAC and N_RBRAC symbols. */
bfd_vma file_start_offset;
struct bincl_file *bincl_stack;
/* Whether we are inside a function or not. */
boolean within_function;
+ /* The address of the end of the function, used if we have seen an
+ N_FUN symbol while in a function. This is -1 if we have not seen
+ an N_FUN (the normal case). */
+ bfd_vma function_end;
/* The depth of block nesting. */
int block_depth;
/* List of pending variable definitions. */
PARAMS ((PTR, struct stab_handle *, const char *, int,
enum debug_type_kind));
static debug_type *stab_demangle_argtypes
- PARAMS ((PTR, struct stab_handle *, const char *));
+ PARAMS ((PTR, struct stab_handle *, const char *, boolean *));
/* Save a string in memory. */
/*ARGSUSED*/
PTR
-start_stab (dhandle, sections)
+start_stab (dhandle, abfd, sections, syms, symcount)
PTR dhandle;
+ bfd *abfd;
boolean sections;
+ asymbol **syms;
+ long symcount;
{
struct stab_handle *ret;
ret = (struct stab_handle *) xmalloc (sizeof *ret);
memset (ret, 0, sizeof *ret);
+ ret->abfd = abfd;
ret->sections = sections;
+ ret->syms = syms;
+ ret->symcount = symcount;
ret->files = 1;
ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
ret->file_types[0] = NULL;
+ ret->function_end = (bfd_vma) -1;
return (PTR) ret;
}
if (info->within_function)
{
- if (! debug_end_function (dhandle, (bfd_vma) -1))
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, info->function_end))
return false;
info->within_function = false;
+ info->function_end = (bfd_vma) -1;
}
for (st = info->tags; st != NULL; st = st->next)
return false;
}
- if (info->pending)
- fprintf (stderr, "Left over pending variables in stabs debugging\n");
-
return true;
}
{
struct stab_handle *info = (struct stab_handle *) handle;
+ /* gcc will emit two N_SO strings per compilation unit, one for the
+ directory name and one for the file name. We just collect N_SO
+ strings as we see them, and start the new compilation unit when
+ we see a non N_SO symbol. */
+ if (info->so_string != NULL
+ && (type != N_SO || *string == '\0' || value != info->so_value))
+ {
+ if (! debug_set_filename (dhandle, info->so_string))
+ return false;
+ info->main_filename = info->so_string;
+
+ info->gcc_compiled = 0;
+ info->n_opt_found = false;
+
+ /* Generally, for stabs in the symbol table, the N_LBRAC and
+ N_RBRAC symbols are relative to the N_SO symbol value. */
+ if (! info->sections)
+ info->file_start_offset = info->so_value;
+
+ /* We need to reset the mapping from type numbers to types. We
+ can't free the old mapping, because of the use of
+ debug_make_indirect_type. */
+ info->files = 1;
+ 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. */
+ }
+
switch (type)
{
case N_FN:
break;
case N_SO:
- /* Start a file. If we get two in a row, the first is the
- directory name. An empty string is emitted by gcc at the end
- of a compilation unit. */
- if (*string == '\0')
- {
- if (info->within_function)
- {
- if (! debug_end_function (dhandle, value))
- return false;
- info->within_function = false;
- }
- return true;
- }
- info->gcc_compiled = 0;
- info->n_opt_found = false;
- if (info->last_type == N_SO)
+ /* This always ends a function. */
+ if (info->within_function)
{
- char *o;
-
- if (! debug_append_filename (dhandle, string))
+ bfd_vma endval;
+
+ endval = value;
+ if (*string != '\0'
+ && info->function_end != (bfd_vma) -1
+ && info->function_end < endval)
+ endval = info->function_end;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, endval))
return false;
- o = info->main_filename;
- info->main_filename = concat (o, string, (const char *) NULL);
- free (o);
+ info->within_function = false;
+ info->function_end = (bfd_vma) -1;
}
+
+ /* An empty string is emitted by gcc at the end of a compilation
+ unit. */
+ if (*string == '\0')
+ return true;
+
+ /* Just accumulate strings until we see a non N_SO symbol. If
+ the string starts with '/', we discard the previously
+ accumulated strings. */
+ if (info->so_string == NULL)
+ info->so_string = xstrdup (string);
else
{
- if (info->within_function)
- {
- if (! debug_end_function (dhandle, value))
- return false;
- info->within_function = false;
- }
- if (! debug_set_filename (dhandle, string))
- return false;
- if (info->main_filename != NULL)
- free (info->main_filename);
- info->main_filename = xstrdup (string);
-
- /* Generally, for stabs in the symbol table, the N_LBRAC and
- N_RBRAC symbols are relative to the N_SO symbol value. */
- if (! info->sections)
- info->file_start_offset = value;
-
- /* We need to reset the mapping from type numbers to types.
- We can't free the old mapping, because of the use of
- debug_make_indirect_type. */
- info->files = 1;
- info->file_types = ((struct stab_types **)
- xmalloc (sizeof *info->file_types));
- info->file_types[0] = NULL;
+ char *f;
+
+ f = info->so_string;
+ if (*string == '/')
+ info->so_string = xstrdup (string);
+ else
+ info->so_string = concat (info->so_string, string,
+ (const char *) NULL);
+ free (f);
}
+
+ info->so_value = value;
+
break;
case N_SOL:
return false;
break;
+ case N_FUN:
+ if (*string == '\0')
+ {
+ if (info->within_function)
+ {
+ /* This always marks the end of a function; we don't
+ need to worry about info->function_end. */
+ if (info->sections)
+ value += info->function_start_offset;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, value))
+ return false;
+ info->within_function = false;
+ info->function_end = (bfd_vma) -1;
+ }
+ break;
+ }
+
+ /* A const static symbol in the .text section will have an N_FUN
+ entry. We need to use these to mark the end of the function,
+ in case we are looking at gcc output before it was changed to
+ always emit an empty N_FUN. We can't call debug_end_function
+ here, because it might be a local static symbol. */
+ if (info->within_function
+ && (info->function_end == (bfd_vma) -1
+ || value < info->function_end))
+ info->function_end = value;
+
+ /* Fall through. */
/* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
symbols, and if it does not start with :S, gdb relocates the
value to the start of the section. gcc always seems to use
:S, so we don't worry about this. */
+ /* Fall through. */
default:
{
const char *colon;
{
if (info->within_function)
{
- if (! debug_end_function (dhandle, value))
+ bfd_vma endval;
+
+ endval = value;
+ if (info->function_end != (bfd_vma) -1
+ && info->function_end < endval)
+ endval = info->function_end;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, endval))
return false;
+ info->function_end = (bfd_vma) -1;
}
/* For stabs in sections, line numbers and block addresses
are offsets from the start of the function. */
break;
}
- info->last_type = type;
-
return true;
}
break;
case 'G':
- /* 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);
- if (dtype == DEBUG_TYPE_NULL)
- return false;
- if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
- (bfd_vma) -1))
- return false;
+ {
+ 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);
+ 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)
+ {
+ 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 (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
+ value))
+ return false;
+ }
break;
/* This case is faked by a conditional above, when there is no
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype != DEBUG_TYPE_NULL)
- dtype = debug_make_pointer_type (dhandle,
- debug_make_function_type (dhandle,
- dtype));
+ {
+ debug_type ftype;
+
+ ftype = debug_make_function_type (dhandle, dtype,
+ (debug_type *) NULL, false);
+ dtype = debug_make_pointer_type (dhandle, ftype);
+ }
}
if (dtype == DEBUG_TYPE_NULL)
return false;
dtype = (debug_make_function_type
(dhandle,
parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL)));
+ (debug_type **) NULL),
+ (debug_type *) NULL, false));
break;
case 'k':
}
++*pp;
dtype = debug_make_method_type (dhandle, return_type,
- DEBUG_TYPE_NULL, NULL);
+ DEBUG_TYPE_NULL,
+ (debug_type *) NULL, false);
}
else
{
debug_type *args;
unsigned int n;
unsigned int alloc;
+ boolean varargs;
domain = parse_stab_type (dhandle, info, (const char *) NULL,
pp, (debug_type **) NULL);
}
++*pp;
- /* If the last type is void, then this function does not
- take a variable number of arguments. If the last is not
- void, then it does. */
- if (n > 0
- && debug_get_type_kind (dhandle, args[n - 1]) == DEBUG_KIND_VOID)
- --n;
+ /* If the last type is not void, then this function takes a
+ variable number of arguments. Otherwise, we must strip
+ the void type. */
+ if (n == 0
+ || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
+ varargs = true;
else
{
- if (n + 1 >= alloc)
- {
- alloc += 10;
- args = ((debug_type *)
- xrealloc ((PTR) args, alloc * sizeof *args));
- }
-
- args[n] = debug_make_ellipsis_type (dhandle);
- if (args[n] == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- ++n;
+ --n;
+ varargs = false;
}
args[n] = DEBUG_TYPE_NULL;
- dtype = debug_make_method_type (dhandle, return_type, domain, args);
+ dtype = debug_make_method_type (dhandle, return_type, domain, args,
+ varargs);
}
break;
if (self_subrange && n2 == 0 && n3 == 0)
return debug_make_void_type (dhandle);
+ /* A type defined as a subrange of itself, with n2 positive and
+ n3 zero, is a complex type, and n2 is the number of bytes. */
+ if (self_subrange && n3 == 0 && n2 > 0)
+ return debug_make_complex_type (dhandle, n2);
+
/* If n3 is zero and n2 is positive, this is a floating point
type, and n2 is the number of bytes. */
if (n3 == 0 && n2 > 0)
do
{
debug_type type;
+ boolean stub;
char *argtypes;
enum debug_visibility visibility;
boolean constp, volatilep, staticp;
bfd_vma voffset;
debug_type context;
const char *physname;
+ boolean varargs;
if (look_ahead_type != DEBUG_TYPE_NULL)
{
return false;
}
+ stub = false;
+ if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
+ && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
+ stub = true;
+
argtypes = savestring (*pp, p - *pp);
*pp = p + 1;
{
case '*':
/* virtual member function, followed by index. The sign
- bit is set to distinguish pointers-to-methods from
- virtual function indicies. Since the array is in
- words, the quantity must be shifted left by 1 on 16
- bit machine, and by 2 on 32 bit machine, forcing the
- sign bit out, and usable as a valid index into the
- array. Remove the sign bit here. */
+ bit is supposedly set to distinguish
+ pointers-to-methods from virtual function indicies. */
++*pp;
voffset = parse_number (pp, (boolean *) NULL);
if (**pp != ';')
}
++*pp;
voffset &= 0x7fffffff;
- voffset += 2;
if (**pp == ';' || *pp == '\0')
{
if (**pp == ':')
{
/* g++ version 1 overloaded methods. */
+ context = DEBUG_TYPE_NULL;
}
else
{
staticp = true;
voffset = 0;
context = DEBUG_TYPE_NULL;
+ if (strncmp (argtypes, name, strlen (name)) != 0)
+ stub = true;
break;
default:
break;
}
- /* If this is a method type which is not a stub--that is,
- the argument types are fully specified--then the argtypes
- string is actually the physical name of the function.
- Otherwise, the argtypes string is the mangled from of the
- argument types, and the physical name of the function,
- and the argument types, must be deduced from it. */
-
- if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
- && debug_get_parameter_types (dhandle, type) != NULL)
+ /* If the type is not a stub, then the argtypes string is
+ the physical name of the function. Otherwise the
+ 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
{
boolean is_constructor;
boolean is_destructor;
debug_type *args;
+ boolean varargs;
/* Constructors are sometimes handled specially. */
is_full_physname_constructor = ((argtypes[0] == '_'
{
args = (debug_type *) xmalloc (sizeof *args);
*args = NULL;
- return debug_make_method_type (dhandle, return_type, class_type, args);
+ return debug_make_method_type (dhandle, return_type, class_type, args,
+ false);
}
- args = stab_demangle_argtypes (dhandle, info, *pphysname);
+ args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs);
if (args == NULL)
return DEBUG_TYPE_NULL;
- return debug_make_method_type (dhandle, return_type, class_type, args);
+ return debug_make_method_type (dhandle, return_type, class_type, args,
+ varargs);
}
/* The tail end of stabs for C++ classes that contain a virtual function
boolean stringp;
{
const char *orig;
+ const char *p;
+ int typenums[2];
debug_type index_type;
boolean adjustable;
bfd_signed_vma lower, upper;
/* FIXME: gdb checks os9k_stabs here. */
- index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ /* If the index type is type 0, we take it as int. */
+ p = *pp;
+ if (! parse_stab_type_number (&p, typenums))
+ return false;
+ if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
+ {
+ index_type = debug_find_named_type (dhandle, "int");
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ index_type = debug_make_int_type (dhandle, 4, false);
+ if (index_type == DEBUG_TYPE_NULL)
+ return false;
+ }
+ *pp = p;
+ }
+ else
+ {
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ }
+
if (**pp != ';')
{
bad_stab (orig);
struct stab_handle *info;
/* The array of arguments we are building. */
debug_type *args;
+ /* Whether the method takes a variable number of arguments. */
+ boolean varargs;
/* The array of types we have remembered. */
struct stab_demangle_typestring *typestrings;
/* The number of typestrings. */
static boolean stab_demangle_class
PARAMS ((struct stab_demangle_info *, const char **, const char **));
static boolean stab_demangle_args
- PARAMS ((struct stab_demangle_info *, const char **, debug_type **));
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+ boolean *));
static boolean stab_demangle_arg
PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
unsigned int *, unsigned int *));
terminated array of argument types. */
static debug_type *
-stab_demangle_argtypes (dhandle, info, physname)
+stab_demangle_argtypes (dhandle, info, physname, pvarargs)
PTR dhandle;
struct stab_handle *info;
const char *physname;
+ boolean *pvarargs;
{
struct stab_demangle_info minfo;
minfo.dhandle = dhandle;
minfo.info = info;
minfo.args = NULL;
+ minfo.varargs = false;
minfo.typestring_alloc = 10;
minfo.typestrings = ((struct stab_demangle_typestring *)
xmalloc (minfo.typestring_alloc
if (minfo.args == NULL)
fprintf (stderr, "no argument types in mangled string\n");
+ *pvarargs = minfo.varargs;
return minfo.args;
error_return:
hold = NULL;
func_done = true;
++*pp;
- if (! stab_demangle_args (minfo, pp, &minfo->args))
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
return false;
break;
/* Assume we have stumbled onto the first outermost function
argument token, and start processing args. */
func_done = true;
- if (! stab_demangle_args (minfo, pp, &minfo->args))
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
return false;
break;
}
if (expect_func)
{
func_done = true;
- if (! stab_demangle_args (minfo, pp, &minfo->args))
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
return false;
}
}
bar__3fooi is 'foo::bar(int)'. We get here when we find the
first case, and need to ensure that the '(void)' gets added
to the current declp. */
- if (! stab_demangle_args (minfo, pp, &minfo->args))
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
return false;
}
done = true;
break;
default:
- /* Assume it's a uder defined integral type. */
+ /* Assume it's a user defined integral type. */
integralp = true;
done = true;
break;
is set to a NULL terminated array holding the arguments. */
static boolean
-stab_demangle_args (minfo, pp, pargs)
+stab_demangle_args (minfo, pp, pargs, pvarargs)
struct stab_demangle_info *minfo;
const char **pp;
debug_type **pargs;
+ boolean *pvarargs;
{
const char *orig;
unsigned int alloc, count;
alloc = 10;
if (pargs != NULL)
- *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+ {
+ *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+ *pvarargs = false;
+ }
count = 0;
while (**pp != '_' && **pp != '\0' && **pp != 'e')
}
}
+ if (pargs != NULL)
+ (*pargs)[count] = DEBUG_TYPE_NULL;
+
if (**pp == 'e')
{
if (pargs != NULL)
- {
- debug_type type;
-
- type = debug_make_ellipsis_type (minfo->dhandle);
- if (type == DEBUG_TYPE_NULL)
- return false;
-
- if (count + 1 >= alloc)
- {
- alloc += 10;
- *pargs = ((debug_type *)
- xrealloc (*pargs, alloc * sizeof **pargs));
- }
- (*pargs)[count] = type;
- ++count;
- }
-
+ *pvarargs = true;
++*pp;
}
- if (pargs != NULL)
- (*pargs)[count] = DEBUG_TYPE_NULL;
-
return true;
}
case 'F':
/* A function. */
- ++*pp;
- /* FIXME: We should pick up the argument types. */
- if (! stab_demangle_args (minfo, pp, (debug_type **) NULL))
- return false;
- if (**pp != '_')
- {
- /* cplus_demangle will accept a function without a return
- type, but I don't know when that will happen, or what to
- do if it does. */
- stab_bad_demangle (orig);
+ {
+ debug_type *args;
+ boolean varargs;
+
+ ++*pp;
+ if (! stab_demangle_args (minfo, pp,
+ (ptype == NULL
+ ? (debug_type **) NULL
+ : &args),
+ (ptype == NULL
+ ? (boolean *) NULL
+ : &varargs)))
return false;
- }
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return false;
- if (ptype != NULL)
- *ptype = debug_make_function_type (minfo->dhandle, *ptype);
+ if (**pp != '_')
+ {
+ /* cplus_demangle will accept a function without a return
+ type, but I don't know when that will happen, or what
+ to do if it does. */
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
+ varargs);
+
+ }
break;
case 'M':
{
boolean memberp, constp, volatilep;
debug_type *args;
+ boolean varargs;
unsigned int n;
const char *name;
constp = false;
volatilep = false;
args = NULL;
+ varargs = false;
++*pp;
if (! isdigit ((unsigned char) **pp))
if (! stab_demangle_args (minfo, pp,
(ptype == NULL
? (debug_type **) NULL
- : &args)))
+ : &args),
+ (ptype == NULL
+ ? (boolean *) NULL
+ : &varargs)))
return false;
}
/* FIXME: We have no way to record constp or
volatilep. */
*ptype = debug_make_method_type (minfo->dhandle, *ptype,
- class_type, args);
+ class_type, args, varargs);
}
}
}
case 't':
if (! stab_demangle_template (minfo, pp))
return false;
- abort ();
+ 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;
+ }
break;
default: