enum_type, start_struct_type, and start_class_type.
* debug.c (debug_write_type): Pass any tag name to
start_struct_type, debug_write_class_type, and enum_type. If
DEBUG_KIND_TAGGED, pass the name in the recursive call.
(debug_write_class_type): Accept a new tag parameter, and pass it
to start_class_type.
* prdbg.c (pop_type): Don't remove '+' character.
(pr_enum_type): Accept and use tag parameter.
(pr_start_struct_type): Likewise.
(pr_start_class_type): Likewise.
(pr_class_baseclass): Adjust algorithm used to find where to put
the baseclass name.
(pr_tag): Don't bother to insert the tag name.
/* debug.c -- Handle generic 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 debug_function *current_function;
/* The current block. */
struct debug_block *current_block;
- /* The current line number information for the current block. */
+ /* The current line number information for the current unit. */
struct debug_lineno *current_lineno;
/* Mark. This is used by debug_write. */
unsigned int mark;
file is always the main one, and that is where the main file name
is stored. */
struct debug_file *files;
+ /* Line number information for this compilation unit. This is not
+ stored by function, because assembler code may have line number
+ information without function information. */
+ struct debug_lineno *linenos;
};
/* Information kept for a single source file. */
bfd_vma end;
/* Local variables. */
struct debug_namespace *locals;
- /* Line number information. */
- struct debug_lineno *linenos;
};
-/* Line number information we keep for a function. FIXME: This
- structure is easy to create, but can be very space inefficient. */
+/* Line number information we keep for a compilation unit. FIXME:
+ This structure is easy to create, but can be very space
+ inefficient. */
struct debug_lineno
{
struct debug_type *, struct debug_name *));
static boolean debug_write_class_type
PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
- struct debug_type *));
+ struct debug_type *, const char *));
static boolean debug_write_function
PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
const char *, enum debug_object_linkage, struct debug_function *));
info->current_function = f;
info->current_block = b;
- info->current_lineno = NULL;
/* FIXME: If we could handle nested functions, this would be the
place: we would want to use a different namespace. */
info->current_function = NULL;
info->current_block = NULL;
- info->current_lineno = NULL;
return true;
}
*pb = b;
info->current_block = b;
- info->current_lineno = NULL;
return true;
}
info->current_block->end = addr;
info->current_block = parent;
- info->current_lineno = NULL;
return true;
}
struct debug_lineno *l;
unsigned int i;
- if (info->current_unit == NULL
- || info->current_block == NULL)
+ if (info->current_unit == NULL)
{
- debug_error ("debug_record_line: no current block");
+ debug_error ("debug_record_line: no current unit");
return false;
}
}
/* If we get here, then either 1) there is no current_lineno
- structure, which means this is the first line number since we got
- to this block, 2) the current_lineno structure is for a different
- file, or 3) the current_lineno structure is full. Regardless, we
- want to allocate a new debug_lineno structure, put it in the
- right place, and make it the new current_lineno structure. */
+ structure, which means this is the first line number in this
+ compilation unit, 2) the current_lineno structure is for a
+ different file, or 3) the current_lineno structure is full.
+ Regardless, we want to allocate a new debug_lineno structure, put
+ it in the right place, and make it the new current_lineno
+ structure. */
l = (struct debug_lineno *) xmalloc (sizeof *l);
memset (l, 0, sizeof *l);
if (info->current_lineno != NULL)
info->current_lineno->next = l;
else
- {
- struct debug_lineno **pl;
-
- /* We may be back in this block after dealing with child blocks,
- which means we may have some line number information for this
- block even though current_lineno was NULL. */
- for (pl = &info->current_block->linenos;
- *pl != NULL;
- pl = &(*pl)->next)
- ;
- *pl = l;
- }
+ info->current_unit->linenos = l;
info->current_lineno = l;
{
struct debug_file *f;
boolean first_file;
+ struct debug_lineno *l;
if (! (*fns->start_compilation_unit) (fhandle, u->files->filename))
return false;
}
}
}
+
+ for (l = u->linenos; l != NULL; l = l->next)
+ {
+ unsigned int i;
+
+ for (i = 0; i < DEBUG_LINENO_COUNT; i++)
+ {
+ if (l->linenos[i] == (unsigned long) -1)
+ break;
+ if (! (*fns->lineno) (fhandle, l->file->filename, l->linenos[i],
+ l->addrs[i]))
+ return false;
+ }
+ }
}
return true;
/*NOTREACHED*/
}
-/* Write out a type. */
+/* Write out a type. If the type is DEBUG_KIND_NAMED or
+ DEBUG_KIND_TAGGED, then the name argument is the name for which we
+ are about to call typedef or tag. If the type is anything else,
+ then the name argument is a tag from a DEBUG_KIND_TAGGED type which
+ points to this one. */
static boolean
debug_write_type (info, fns, fhandle, type, name)
struct debug_name *name;
{
unsigned int i;
+ const char *tag;
/* If we have a name for this type, just output it. We only output
typedef names after they have been defined. We output type tags
if (name != NULL)
name->mark = info->mark;
+ tag = NULL;
+ if (name != NULL
+ && type->kind != DEBUG_KIND_NAMED
+ && type->kind != DEBUG_KIND_TAGGED)
+ {
+ assert (name->kind == DEBUG_OBJECT_TAG);
+ tag = name->name;
+ }
+
switch (type->kind)
{
case DEBUG_KIND_INDIRECT:
}
type->u.kclass->mark = info->class_mark;
- if (! (*fns->start_struct_type) (fhandle,
+ if (! (*fns->start_struct_type) (fhandle, tag,
type->kind == DEBUG_KIND_STRUCT,
type->size))
return false;
return (*fns->end_struct_type) (fhandle);
case DEBUG_KIND_CLASS:
case DEBUG_KIND_UNION_CLASS:
- return debug_write_class_type (info, fns, fhandle, type);
+ return debug_write_class_type (info, fns, fhandle, type, tag);
case DEBUG_KIND_ENUM:
- return (*fns->enum_type) (fhandle, type->u.kenum->names,
+ return (*fns->enum_type) (fhandle, tag, type->u.kenum->names,
type->u.kenum->values);
case DEBUG_KIND_POINTER:
if (! debug_write_type (info, fns, fhandle, type->u.kpointer,
return false;
return (*fns->volatile_type) (fhandle);
case DEBUG_KIND_NAMED:
- case DEBUG_KIND_TAGGED:
return debug_write_type (info, fns, fhandle, type->u.knamed->type,
(struct debug_name *) NULL);
+ case DEBUG_KIND_TAGGED:
+ return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+ type->u.knamed->name);
default:
abort ();
return false;
/* Write out a class type. */
static boolean
-debug_write_class_type (info, fns, fhandle, type)
+debug_write_class_type (info, fns, fhandle, type, tag)
struct debug_handle *info;
const struct debug_write_fns *fns;
PTR fhandle;
struct debug_type *type;
+ const char *tag;
{
unsigned int i;
return false;
}
- if (! (*fns->start_class_type) (fhandle,
+ if (! (*fns->start_class_type) (fhandle, tag,
type->kind == DEBUG_KIND_CLASS,
type->size,
type->u.kclass->vptrbase != NULL,
struct debug_block *block;
{
struct debug_name *n;
- struct debug_lineno *l;
struct debug_block *b;
if (! (*fns->start_block) (fhandle, block->start))
}
}
- for (l = block->linenos; l != NULL; l = l->next)
- {
- unsigned int i;
-
- for (i = 0; i < DEBUG_LINENO_COUNT; i++)
- {
- if (l->linenos[i] == (unsigned long) -1)
- break;
- if (! (*fns->lineno) (fhandle, l->file->filename, l->linenos[i],
- l->addrs[i]))
- return false;
- }
- }
-
for (b = block->children; b != NULL; b = b->next)
{
if (! debug_write_block (info, fns, fhandle, b))
/* debug.h -- Describe generic 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.
/* Push a boolean type onto the type stack, given the size. */
boolean (*bool_type) PARAMS ((PTR, unsigned int));
- /* Push an enum type onto the type stack, given a NULL terminated
- array of names and the associated values. */
- boolean (*enum_type) PARAMS ((PTR, const char **, bfd_signed_vma *));
+ /* Push an enum type onto the type stack, given the tag, a NULL
+ terminated array of names and the associated values. If there is
+ no tag, the tag argument will be NULL. */
+ boolean (*enum_type) PARAMS ((PTR, const char *, const char **,
+ bfd_signed_vma *));
/* Pop the top type on the type stack, and push a pointer to that
type onto the type stack. */
method). An argument type of -1 means that no argument in
formation is available. The next type on the type stack below
the domain and the argument types is the return type of the
- method. All these types must be poppsed, and then the method
- type must be pushed. */
+ method. All these types must be popped, and then the method type
+ must be pushed. */
boolean (*method_type) PARAMS ((PTR, boolean, int));
/* Pop the top type off the type stack, and push a const qualified
/* Start building a struct. This is followed by calls to the
struct_field function, and finished by a call to the
- end_struct_type function. The boolean argument is true for a
- struct, false for a union. The unsigned int argument is the
- size. */
- boolean (*start_struct_type) PARAMS ((PTR, boolean, unsigned int));
+ end_struct_type function. The second argument is the tag; this
+ will be NULL if there isn't one. The boolean argument is true
+ for a struct, false for a union. The unsigned int argument is
+ the size. */
+ boolean (*start_struct_type) PARAMS ((PTR, const char *, boolean,
+ unsigned int));
/* Add a field to the struct type currently being built. The type
of the field should be popped off the type stack. The arguments
functions: struct_field, class_static_member, class_baseclass,
class_start_method, class_method_variant,
class_static_method_variant, and class_end_method. The class is
- finished by a call to end_class_type. The boolean argument is
- true for a struct, false for a union. The next argument is the
- size. The next argument is true if there is a virtual function
- table; if there is, the next argument is true if the virtual
- function table can be found in the type itself, and is false if
- the type of the object holding the virtual function table should
- be popped from the type stack. */
- boolean (*start_class_type) PARAMS ((PTR, boolean, unsigned int,
- boolean, boolean));
+ finished by a call to end_class_type. The second argument is the
+ tag; this will be NULL if there isn't one. The boolean argument
+ is true for a struct, false for a union. The next argument is
+ the size. The next argument is true if there is a virtual
+ function table; if there is, the next argument is true if the
+ virtual function table can be found in the type itself, and is
+ false if the type of the object holding the virtual function
+ table should be popped from the type stack. */
+ boolean (*start_class_type) PARAMS ((PTR, const char *, boolean,
+ unsigned int, boolean, boolean));
/* Add a static member to the class currently being built. The
arguments are the field name, the physical name, and the
- visibility. */
+ visibility. The type must be popped off the type stack. */
boolean (*class_static_member) PARAMS ((PTR, const char *, const char *,
enum debug_visibility));
/* Describe a static variant to the class method currently being
built. The arguments are the same as for class_method_variant,
- except that the last two arguments are omitted. */
+ except that the last two arguments are omitted. The type of the
+ variant must be popped off the type stack. */
boolean (*class_static_method_variant) PARAMS ((PTR, const char *,
enum debug_visibility,
boolean, boolean));
boolean (*typdef) PARAMS ((PTR, const char *));
/* Pop the type stack, and declare it as a tagged struct or union or
- enum or whatever. */
+ enum or whatever. The tag passed down here is redundant, since
+ was also passed when enum_type, start_struct_type, or
+ start_class_type was called. */
boolean (*tag) PARAMS ((PTR, const char *));
/* This is called to record a named integer constant. */
starting address of the block. */
boolean (*start_block) PARAMS ((PTR, bfd_vma));
- /* Record line number information for the current block. */
- boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
-
/* Finish writing out a block. The argument is the ending address
of the block. */
boolean (*end_block) PARAMS ((PTR, bfd_vma));
/* Finish writing out a function. */
boolean (*end_function) PARAMS ((PTR));
+
+ /* Record line number information for the current compilation unit. */
+ boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
};
/* Exported functions. */
extern boolean debug_end_block PARAMS ((PTR, bfd_vma));
-/* Associate a line number in the current source file and function
- with a given address. */
+/* Associate a line number in the current source file with a given
+ address. */
extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma));
/* prdbg.c -- Print out generic 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.
static boolean pr_float_type PARAMS ((PTR, unsigned int));
static boolean pr_complex_type PARAMS ((PTR, unsigned int));
static boolean pr_bool_type PARAMS ((PTR, unsigned int));
-static boolean pr_enum_type PARAMS ((PTR, const char **, bfd_signed_vma *));
+static boolean pr_enum_type
+ PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
static boolean pr_pointer_type PARAMS ((PTR));
static boolean pr_function_type PARAMS ((PTR));
static boolean pr_reference_type PARAMS ((PTR));
static boolean pr_method_type PARAMS ((PTR, boolean, int));
static boolean pr_const_type PARAMS ((PTR));
static boolean pr_volatile_type PARAMS ((PTR));
-static boolean pr_start_struct_type PARAMS ((PTR, boolean, unsigned int));
+static boolean pr_start_struct_type
+ PARAMS ((PTR, const char *, boolean, unsigned int));
static boolean pr_struct_field
PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
static boolean pr_end_struct_type PARAMS ((PTR));
static boolean pr_start_class_type
- PARAMS ((PTR, boolean, unsigned int, boolean, boolean));
+ PARAMS ((PTR, const char *, boolean, unsigned int, boolean, boolean));
static boolean pr_class_static_member
PARAMS ((PTR, const char *, const char *, enum debug_visibility));
static boolean pr_class_baseclass
static boolean pr_function_parameter
PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
static boolean pr_start_block PARAMS ((PTR, bfd_vma));
-static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
static boolean pr_end_block PARAMS ((PTR, bfd_vma));
static boolean pr_end_function PARAMS ((PTR));
+static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
static const struct debug_write_fns pr_fns =
{
pr_start_function,
pr_function_parameter,
pr_start_block,
- pr_lineno,
pr_end_block,
- pr_end_function
+ pr_end_function,
+ pr_lineno
};
\f
/* Print out the generic debugging information recorded in dhandle. */
struct pr_handle *info;
{
struct pr_stack *o;
- char *ret, *s;
+ char *ret;
assert (info->stack != NULL);
ret = o->type;
free (o);
- s = strchr (ret, '+');
- if (s != NULL)
- memmove (s, s + 2, strlen (s + 2) + 1);
-
return ret;
}
/* Push an enum type onto the type stack. */
static boolean
-pr_enum_type (p, names, values)
+pr_enum_type (p, tag, names, values)
PTR p;
+ const char *tag;
const char **names;
bfd_signed_vma *values;
{
unsigned int i;
bfd_signed_vma val;
- /* The + indicates where the tag goes, if there is one. */
- if (! push_type (info, "enum + { "))
+ if (! push_type (info, "enum "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag)
+ || ! append_type (info, " "))
+ return false;
+ }
+ if (! append_type (info, "{ "))
return false;
val = 0;
/* Start accumulating a struct type. */
static boolean
-pr_start_struct_type (p, structp, size)
+pr_start_struct_type (p, tag, structp, size)
PTR p;
+ const char *tag;
boolean structp;
unsigned int size;
{
struct pr_handle *info = (struct pr_handle *) p;
- const char *t;
char ab[30];
info->indent += 2;
- if (structp)
- t = "struct";
- else
- t = "union";
+ if (! push_type (info, structp ? "struct " : "union "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag)
+ || ! append_type (info, " "))
+ return false;
+ }
if (size != 0)
- sprintf (ab, "%s + { /* size %u */\n", t, size);
+ sprintf (ab, "{ /* size %u */\n", size);
else
- sprintf (ab, "%s + {\n", t);
- if (! push_type (info, ab))
+ strcpy (ab, "{\n");
+ if (! append_type (info, ab))
return false;
info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
return indent_type (info);
/* Start a class type. */
static boolean
-pr_start_class_type (p, structp, size, vptr, ownvptr)
+pr_start_class_type (p, tag, structp, size, vptr, ownvptr)
PTR p;
+ const char *tag;
boolean structp;
unsigned int size;
boolean vptr;
return false;
}
- if (! push_type (info, structp ? "class" : "union class")
- || ! append_type (info, " + {"))
+ if (! push_type (info, structp ? "class " : "union class "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag)
+ || ! append_type (info, " "))
+ return false;
+ }
+ if (! append_type (info, "{"))
return false;
if (size != 0 || vptr || ownvptr)
{
char *t;
const char *prefix;
char ab[20];
- char *s, *n;
+ char *s, *l, *n;
assert (info->stack != NULL && info->stack->next != NULL);
/* Now the top of the stack is something like "public A / * bitpos
10 * /". The next element on the stack is something like "class
- + { / * size 8 * /\n...". We want to substitute the top of the
- stack in after the +. */
- s = strchr (info->stack->next->type, '+');
+ xx { / * size 8 * /\n...". We want to substitute the top of the
+ stack in before the {. */
+ s = strchr (info->stack->next->type, '{');
assert (s != NULL);
+ --s;
- if (s[2] != ':')
- {
- ++s;
- assert (s[1] == '{');
- if (! prepend_type (info, " : "))
- return false;
- }
- else
- {
- /* We already have a baseclass. Append this one after a comma. */
- s = strchr (s, '{');
- assert (s != NULL);
- --s;
- if (! prepend_type (info, ", "))
- return false;
- }
+ /* If there is already a ':', then we already have a baseclass, and
+ we must append this one after a comma. */
+ for (l = info->stack->next->type; l != s; l++)
+ if (*l == ':')
+ break;
+ if (! prepend_type (info, l == s ? " : " : ", "))
+ return false;
t = pop_type (info);
if (t == NULL)
return true;
}
-/* Output a tag. */
+/* Output a tag. The tag should already be in the string on the
+ stack, so all we have to do here is print it out. */
+/*ARGSUSED*/
static boolean
pr_tag (p, name)
PTR p;
const char *name;
{
struct pr_handle *info = (struct pr_handle *) p;
- char *t, *s, *n;
-
- assert (info->stack != NULL);
-
- t = info->stack->type;
-
- s = strchr (t, '+');
- assert (s != NULL);
-
- n = (char *) xmalloc (strlen (t) + strlen (name));
-
- memcpy (n, t, s - t);
- strcpy (n + (s - t), name);
- strcat (n, s + 1);
-
- free (t);
- info->stack->type = n;
+ char *t;
t = pop_type (info);
if (t == NULL)
indent (info);
fprintf (info->f, "%s;\n", t);
- free (n);
+ free (t);
return true;
}