* debug.h (struct debug_write_fns): Add tag parameter to

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.
This commit is contained in:
Ian Lance Taylor
1996-01-08 23:18:51 +00:00
parent f5818d79dd
commit 63840d265c
3 changed files with 155 additions and 146 deletions

View File

@ -1,5 +1,5 @@
/* 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.
@ -48,7 +48,7 @@ struct debug_handle
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;
@ -66,6 +66,10 @@ struct debug_unit
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. */
@ -394,12 +398,11 @@ struct debug_block
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
{
@ -511,7 +514,7 @@ static boolean debug_write_type
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 *));
@ -769,7 +772,6 @@ debug_record_function (handle, name, return_type, global, addr)
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. */
@ -855,7 +857,6 @@ debug_end_function (handle, addr)
info->current_function = NULL;
info->current_block = NULL;
info->current_lineno = NULL;
return true;
}
@ -897,7 +898,6 @@ debug_start_block (handle, addr)
*pb = b;
info->current_block = b;
info->current_lineno = NULL;
return true;
}
@ -931,7 +931,6 @@ debug_end_block (handle, addr)
info->current_block->end = addr;
info->current_block = parent;
info->current_lineno = NULL;
return true;
}
@ -949,10 +948,9 @@ debug_record_line (handle, lineno, addr)
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;
}
@ -971,11 +969,12 @@ debug_record_line (handle, lineno, addr)
}
/* 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);
@ -989,18 +988,7 @@ debug_record_line (handle, lineno, addr)
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;
@ -2098,6 +2086,7 @@ debug_write (handle, fns, fhandle)
{
struct debug_file *f;
boolean first_file;
struct debug_lineno *l;
if (! (*fns->start_compilation_unit) (fhandle, u->files->filename))
return false;
@ -2124,6 +2113,20 @@ debug_write (handle, fns, fhandle)
}
}
}
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;
@ -2179,7 +2182,11 @@ debug_write_name (info, fns, fhandle, n)
/*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)
@ -2190,6 +2197,7 @@ 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
@ -2214,6 +2222,15 @@ debug_write_type (info, fns, fhandle, type, name)
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:
@ -2241,7 +2258,7 @@ debug_write_type (info, fns, fhandle, type, name)
}
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;
@ -2262,9 +2279,9 @@ debug_write_type (info, fns, fhandle, type, name)
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,
@ -2349,9 +2366,11 @@ debug_write_type (info, fns, fhandle, type, name)
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;
@ -2361,11 +2380,12 @@ debug_write_type (info, fns, fhandle, type, name)
/* 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;
@ -2385,7 +2405,7 @@ debug_write_class_type (info, fns, fhandle, type)
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,
@ -2533,7 +2553,6 @@ debug_write_block (info, fns, fhandle, block)
struct debug_block *block;
{
struct debug_name *n;
struct debug_lineno *l;
struct debug_block *b;
if (! (*fns->start_block) (fhandle, block->start))
@ -2548,20 +2567,6 @@ debug_write_block (info, fns, fhandle, block)
}
}
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))

View File

@ -1,5 +1,5 @@
/* 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.
@ -192,9 +192,11 @@ struct debug_write_fns
/* 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. */
@ -240,8 +242,8 @@ struct debug_write_fns
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
@ -254,10 +256,12 @@ struct debug_write_fns
/* 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
@ -273,19 +277,20 @@ struct debug_write_fns
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));
@ -319,7 +324,8 @@ struct debug_write_fns
/* 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));
@ -342,7 +348,9 @@ struct debug_write_fns
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. */
@ -376,15 +384,15 @@ struct debug_write_fns
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. */
@ -446,8 +454,8 @@ extern boolean debug_start_block PARAMS ((PTR, bfd_vma));
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));

View File

@ -1,5 +1,5 @@
/* 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.
@ -78,7 +78,8 @@ static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean));
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));
@ -90,12 +91,13 @@ static boolean pr_offset_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
@ -121,9 +123,9 @@ static boolean pr_start_function PARAMS ((PTR, const char *, boolean));
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 =
{
@ -168,9 +170,9 @@ 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
};
/* Print out the generic debugging information recorded in dhandle. */
@ -337,7 +339,7 @@ pop_type (info)
struct pr_handle *info;
{
struct pr_stack *o;
char *ret, *s;
char *ret;
assert (info->stack != NULL);
@ -346,10 +348,6 @@ pop_type (info)
ret = o->type;
free (o);
s = strchr (ret, '+');
if (s != NULL)
memmove (s, s + 2, strlen (s + 2) + 1);
return ret;
}
@ -500,8 +498,9 @@ pr_bool_type (p, size)
/* 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;
{
@ -509,8 +508,15 @@ pr_enum_type (p, names, 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;
@ -824,26 +830,30 @@ pr_volatile_type (p)
/* 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);
@ -977,8 +987,9 @@ pr_end_struct_type (p)
/* 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;
@ -996,8 +1007,15 @@ pr_start_class_type (p, structp, size, vptr, ownvptr)
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)
{
@ -1079,7 +1097,7 @@ pr_class_baseclass (p, bitpos, virtual, visibility)
char *t;
const char *prefix;
char ab[20];
char *s, *n;
char *s, *l, *n;
assert (info->stack != NULL && info->stack->next != NULL);
@ -1134,27 +1152,19 @@ pr_class_baseclass (p, bitpos, virtual, visibility)
/* 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)
@ -1426,31 +1436,17 @@ pr_typdef (p, name)
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)
@ -1459,7 +1455,7 @@ pr_tag (p, name)
indent (info);
fprintf (info->f, "%s;\n", t);
free (n);
free (t);
return true;
}