/* stabs.c -- Parse stabs debugging information
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GNU Binutils.
struct stab_handle
{
+ /* 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 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;
/* The offset of the start of the function, so that we can handle
- function relative N_RBRAC symbols. */
+ function relative N_LBRAC and N_RBRAC symbols. */
bfd_vma function_start_offset;
/* The version number of gcc which compiled the current compilation
unit, 0 if not compiled by gcc. */
static boolean parse_stab_string
PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *));
static debug_type parse_stab_type
- PARAMS ((PTR, struct stab_handle *, const char **, debug_type **));
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ debug_type **));
static boolean parse_stab_type_number
PARAMS ((const char **, int *));
static debug_type parse_stab_range_type
- PARAMS ((PTR, struct stab_handle *, const char **, const int *));
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ const int *));
static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **));
static debug_type parse_stab_sun_floating_type
PARAMS ((PTR, const char **));
/*ARGSUSED*/
PTR
-start_stab (dhandle)
+start_stab (dhandle, sections)
PTR dhandle;
+ boolean sections;
{
struct stab_handle *ret;
ret = (struct stab_handle *) xmalloc (sizeof *ret);
memset (ret, 0, sizeof *ret);
+ ret->sections = sections;
ret->files = 1;
ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
ret->file_types[0] = NULL;
}
/* Start an inner lexical block. */
- if (! debug_start_block (dhandle, value + info->function_start_offset))
+ if (! debug_start_block (dhandle,
+ (value
+ + info->file_start_offset
+ + info->function_start_offset)))
return false;
/* Emit any pending variable definitions. */
return false;
/* End an inner lexical block. */
- if (! debug_end_block (dhandle, value + info->function_start_offset))
+ if (! debug_end_block (dhandle,
+ (value
+ + info->file_start_offset
+ + info->function_start_offset)))
return false;
--info->block_depth;
{
info->within_function = false;
if (! debug_end_function (dhandle,
- value + info->function_start_offset))
+ (value
+ + info->file_start_offset
+ + info->function_start_offset)))
return false;
}
break;
}
else
{
+ if (info->within_function)
+ {
+ if (! debug_end_function (dhandle, (bfd_vma) -1))
+ 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. */
if (! debug_end_function (dhandle, (bfd_vma) -1))
return false;
}
- info->function_start_offset = value;
+ /* For stabs in sections, line numbers and block addresses
+ are offsets from the start of the function. */
+ if (info->sections)
+ info->function_start_offset = value;
info->within_function = true;
}
can be represented as integral.
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, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ &p, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (*p != ',')
case 'C':
/* The name of a caught exception. */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ &p, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_label (dhandle, name, dtype, value))
case 'f':
case 'F':
/* A function definition. */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
while (*p == ';')
{
++p;
- if (parse_stab_type (dhandle, info, &p, (debug_type **) NULL)
+ if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL)
== DEBUG_TYPE_NULL)
return false;
}
case 'G':
/* A global symbol. The value must be extracted from the symbol
table. */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ 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,
contains 'l'. */
case 'l':
case 's':
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ 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_LOCAL,
case 'p':
/* A function parameter. */
if (*p != 'F')
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
else
{
/* pF is a two-letter code that means a function parameter in
Fortran. The type-number specifies the type of the return
value. Translate it into a pointer-to-function type. */
++p;
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ 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,
while (*p == ';')
{
++p;
- if (parse_stab_type (dhandle, info, &p, (debug_type **) NULL)
+ if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL)
== DEBUG_TYPE_NULL)
return false;
}
/* Fall through. */
case 'R':
/* Parameter which is in a register. */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
case 'r':
/* Register variable (either global or local). */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ 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_REGISTER,
case 'S':
/* Static symbol at top level of file */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ 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_STATIC,
case 't':
/* A typedef. */
- dtype = parse_stab_type (dhandle, info, &p, &slot);
+ dtype = parse_stab_type (dhandle, info, name, &p, &slot);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (name == NULL)
++p;
}
- dtype = parse_stab_type (dhandle, info, &p, &slot);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, &slot);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (name == NULL)
case 'V':
/* Static symbol of local scope */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
/* FIXME: gdb checks os9k_stabs here. */
case 'v':
/* Reference parameter. */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
case 'a':
/* Reference parameter which is in a register. */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
Sun claims ("dbx and dbxtool interfaces", 2nd ed)
that Pascal uses it too, but when I tried it Pascal used
"x:3" (local symbol) instead. */
- dtype = parse_stab_type (dhandle, info, &p, (debug_type **) NULL);
+ 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_LOCAL,
return true;
}
-/* Parse a stabs type. */
+/* Parse a stabs type. The typename argument is non-NULL if this is a
+ typedef. The pp argument points to the stab string, and is
+ updated. The slotp argument points to a place to store the slot
+ used if the type is being defined. */
static debug_type
-parse_stab_type (dhandle, info, pp, slotp)
+parse_stab_type (dhandle, info, typename, pp, slotp)
PTR dhandle;
struct stab_handle *info;
+ const char *typename;
const char **pp;
debug_type **slotp;
{
/* Go back to the number and have parse_stab_type get it.
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, pp, (debug_type **) NULL);
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
}
case '*':
dtype = debug_make_pointer_type (dhandle,
- parse_stab_type (dhandle, info, pp,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
(debug_type **) NULL));
break;
/* Reference to another type. */
dtype = (debug_make_reference_type
(dhandle,
- parse_stab_type (dhandle, info, pp, (debug_type **) NULL)));
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL)));
break;
case 'f':
/* FIXME: gdb checks os9k_stabs here. */
dtype = (debug_make_function_type
(dhandle,
- parse_stab_type (dhandle, info, pp, (debug_type **) NULL)));
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL)));
break;
case 'k':
/* Const qualifier on some type (Sun). */
/* FIXME: gdb accepts 'c' here if os9k_stabs. */
dtype = debug_make_const_type (dhandle,
- parse_stab_type (dhandle, info, pp,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
(debug_type **) NULL));
break;
/* FIXME: gdb accepts 'i' here if os9k_stabs. */
dtype = (debug_make_volatile_type
(dhandle,
- parse_stab_type (dhandle, info, pp, (debug_type **) NULL)));
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL)));
break;
case '@':
/* Member type. */
- domain = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (domain == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
}
++*pp;
- memtype = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (memtype == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
debug_type return_type;
++*pp;
- return_type = parse_stab_type (dhandle, info, pp,
- (debug_type **) NULL);
+ return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
if (return_type == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
if (**pp != ';')
unsigned int n;
unsigned int alloc;
- domain = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ domain = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
if (domain == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
}
++*pp;
- return_type = parse_stab_type (dhandle, info, pp,
- (debug_type **) NULL);
+ return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
if (return_type == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
xrealloc ((PTR) args, alloc * sizeof *args));
}
- args[n] = parse_stab_type (dhandle, info, pp,
- (debug_type **) NULL);
+ args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
if (args[n] == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
++n;
case 'r':
/* Range type. */
- dtype = parse_stab_range_type (dhandle, info, pp, typenums);
+ dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums);
break;
case 'b':
case 'S':
dtype = debug_make_set_type (dhandle,
- parse_stab_type (dhandle, info, pp,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
(debug_type **) NULL),
stringp);
break;
/* Parse a range type. */
static debug_type
-parse_stab_range_type (dhandle, info, pp, typenums)
+parse_stab_range_type (dhandle, info, typename, pp, typenums)
PTR dhandle;
struct stab_handle *info;
+ const char *typename;
const char **pp;
const int *typenums;
{
if (**pp == '=')
{
*pp = orig;
- index_type = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
if (index_type == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
}
/* If the upper bound is -1, this is an unsigned int. */
if (n2 == 0 && n3 == -1)
{
+ /* When gcc is used with -gstabs, but not -gstabs+, it will emit
+ 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 (strcmp (typename, "long long int") == 0)
+ return debug_make_int_type (dhandle, 8, false);
+ else if (strcmp (typename, "long long unsigned int") == 0)
+ return debug_make_int_type (dhandle, 8, true);
+ }
/* FIXME: The size here really depends upon the target. */
return debug_make_int_type (dhandle, 4, true);
}
}
++*pp;
- type = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
return false;
after is a regular type definition. Lookup the type, find it's
name, and construct the field name. */
- context = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (context == DEBUG_TYPE_NULL)
return false;
}
++*pp;
- type = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (**pp != ',')
{
bad_stab (orig);
++*pp;
}
- type = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
return false;
}
else
{
- type = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
return false;
if (**pp != ':')
/* 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, pp,
+ look_ahead_type = parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
(debug_type **) NULL);
if (**pp == ':')
{
*pp = hold;
- vtype = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
for (p = *pp; *p != ';' && *p != '\0'; p++)
;
if (*p != ';')
/* FIXME: gdb checks os9k_stabs here. */
- index_type = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (**pp != ';')
{
bad_stab (orig);
}
++*pp;
- element_type = parse_stab_type (dhandle, info, pp, (debug_type **) NULL);
+ element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
if (element_type == DEBUG_TYPE_NULL)
return false;