From 07aa1e1b7a4a32b727bb943186680cbd3fc77b94 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 19 Jan 1996 18:03:04 +0000 Subject: [PATCH] * debug.h (enum debug_type_kind): Add DEBUG_KIND_ILLEGAL. (struct debug_write_fns): Add field ellipsis_type. Add id parameter to start_struct_type, start_class_type, and tag_type. (debug_make_ellipsis_type): Declare. (debug_find_named_type): Declare. (debug_get_type_kind): Declare. (debug_get_return_type): Declare. (debug_get_parameter_types): Declare. (debug_get_fields): Declare. (debug_get_field_type): Declare. * debug.c (struct debug_handle): Add fields class_id and base_id. (struct debug_class_type): Add field id. (struct debug_method_variant): Rename argtypes to physname. Change all uses. (debug_ellipsis_type): New static variable. (ELLIPSIS_P): New macro. (debug_make_ellipsis_type): New function. (debug_make_method_variant): Rename argtypes to physname. (debug_make_static_method_variant): Likewise. (debug_name_type): Always put types in the global namespace. (debug_find_named_type): New function. (debug_find_tagged_type): Treat DEBUG_KIND_ILLEGAL specially, rather than DEBUG_KIND_VOID. (debug_get_real_type): New static function. (debug_get_type_kind): New function. (debug_get_return_type): New function. (debug_get_parameter_types): New function. (debug_get_fields): New function. (debug_get_field_type): New function. (debug_write): Initialize base_id. (debug_write_type): Pass new id argument to tag_type. Handle DEBUG_KIND_ILLEGAL. Use id for DEBUG_KIND_STRUCT and DEBUG_KIND_UNION. Handle ellipsis for method arguments. (debug_write_class_type): Don't dereference kclass if it is NULL. Use id. * prdbg.c (pr_fns): Add pr_ellipsis_type. (pr_ellipsis_type): New static function. (pr_pointer_type): If this is a pointer to an array, parenthesize it correctly. (pr_start_struct_type): Add id parameter. (pr_start_class_type): Likewise. (pr_tag_type): Likewise. (pr_fix_visibility): Add the visibility to the top of the stack, not the second element on the stack. (pr_struct_field): Pop the stack before calling pr_fix_visibility. (pr_class_static_member): Likewise. (pr_class_start_method): Don't push a type, just set the method name in the type on the top of the stack. (pr_class_end_method): Don't pop the stack. (pr_class_method_variant): Rename argtypes parameter to physname. Append const and volatile rather than prepending them. Add a space after the physname. (pr_class_static_method_variant): Likewise. * ieee.c (ieee_fns): Add ieee_ellipsis_type. (ieee_define_named_type): Use DEBUG_KIND_ILLEGAL rather than DEBUG_KIND_VOID. (write_ieee_debugging_info): Likewise. (ieee_typdef): Likewise. (ieee_ellipsis_type): New static function. (ieee_start_struct_type): Add id parameter. (ieee_start_class_type): Likewise. (ieee_tag_type): Likewise. (ieee_class_method_variant): Rename name to physname. (ieee_class_static_method_variant): Likewise. --- binutils/debug.c | 317 +++++++++++++++++++++++++++++++++++++++++------ binutils/debug.h | 109 +++++++++++----- binutils/ieee.c | 48 ++++--- binutils/prdbg.c | 169 ++++++++++++++++--------- 4 files changed, 500 insertions(+), 143 deletions(-) diff --git a/binutils/debug.c b/binutils/debug.c index 02a80aea391..edb5835c70d 100644 --- a/binutils/debug.c +++ b/binutils/debug.c @@ -54,6 +54,10 @@ struct debug_handle unsigned int mark; /* Another mark used by debug_write. */ unsigned int class_mark; + /* A struct/class ID used by debug_write. */ + unsigned int class_id; + /* The base for class_id for this call to debug_write. */ + unsigned int base_id; }; /* Information we keep for a single compilation unit. */ @@ -150,6 +154,8 @@ struct debug_class_type debug_field *fields; /* A mark field used to avoid recursively printing out structs. */ unsigned int mark; + /* This is used to uniquely identify unnamed structs when printing. */ + unsigned int id; /* The remaining fields are only used for DEBUG_KIND_CLASS and DEBUG_KIND_UNION_CLASS. */ /* NULL terminated array of base classes. */ @@ -309,8 +315,8 @@ struct debug_method struct debug_method_variant { - /* The argument types of the function. */ - const char *argtypes; + /* The physical name of the function. */ + const char *physname; /* The type of the function. */ struct debug_type *type; /* The visibility of the function. */ @@ -497,6 +503,17 @@ struct debug_name } u; }; +/* This variable is an ellipsis type. The contents are not used; its + address is returned by debug_make_ellipsis_type, and anything which + needs to know whether it is dealing with an ellipsis compares + addresses. */ + +static const struct debug_type debug_ellipsis_type; + +#define ELLIPSIS_P(t) ((t) == &debug_ellipsis_type) + +/* Local functions. */ + static void debug_error PARAMS ((const char *)); static struct debug_name *debug_add_to_namespace PARAMS ((struct debug_handle *, struct debug_namespace **, const char *, @@ -506,6 +523,7 @@ static struct debug_name *debug_add_to_current_namespace enum debug_object_linkage)); static struct debug_type *debug_make_type PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int)); +static struct debug_type *debug_get_real_type PARAMS ((PTR, debug_type)); static boolean debug_write_name PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, struct debug_name *)); @@ -1223,6 +1241,18 @@ debug_make_indirect_type (handle, slot, tag) return t; } +/* Make an ellipsis type. This is not a type at all, but is a marker + suitable for appearing in the list of argument types passed to + debug_make_method_type. It should be used to indicate a method + which takes a variable number of arguments. */ + +debug_type +debug_make_ellipsis_type (handle) + PTR handle; +{ + return (debug_type) &debug_ellipsis_type; +} + /* Make a void type. There is only one of these. */ debug_type @@ -1847,10 +1877,10 @@ debug_make_method (handle, name, variants) /*ARGSUSED*/ debug_method_variant -debug_make_method_variant (handle, argtypes, type, visibility, constp, +debug_make_method_variant (handle, physname, type, visibility, constp, volatilep, voffset, context) PTR handle; - const char *argtypes; + const char *physname; debug_type type; enum debug_visibility visibility; boolean constp; @@ -1863,7 +1893,7 @@ debug_make_method_variant (handle, argtypes, type, visibility, constp, m = (struct debug_method_variant *) xmalloc (sizeof *m); memset (m, 0, sizeof *m); - m->argtypes = argtypes; + m->physname = physname; m->type = type; m->visibility = visibility; m->constp = constp; @@ -1879,10 +1909,10 @@ debug_make_method_variant (handle, argtypes, type, visibility, constp, since a static method can not also be virtual. */ debug_method_variant -debug_make_static_method_variant (handle, argtypes, type, visibility, +debug_make_static_method_variant (handle, physname, type, visibility, constp, volatilep) PTR handle; - const char *argtypes; + const char *physname; debug_type type; enum debug_visibility visibility; boolean constp; @@ -1893,7 +1923,7 @@ debug_make_static_method_variant (handle, argtypes, type, visibility, m = (struct debug_method_variant *) xmalloc (sizeof *m); memset (m, 0, sizeof *m); - m->argtypes = argtypes; + m->physname = physname; m->type = type; m->visibility = visibility; m->constp = constp; @@ -1919,6 +1949,13 @@ debug_name_type (handle, name, type) if (name == NULL || type == NULL) return DEBUG_TYPE_NULL; + if (info->current_unit == NULL + || info->current_file == NULL) + { + debug_error ("debug_record_variable: no current file"); + return false; + } + t = debug_make_type (info, DEBUG_KIND_NAMED, 0); if (t == NULL) return DEBUG_TYPE_NULL; @@ -1930,10 +1967,11 @@ debug_name_type (handle, name, type) t->u.knamed = n; - /* We also need to add the name to the current namespace. */ + /* We always add the name to the global namespace. This is probably + wrong in some cases, but it seems to be right for stabs. FIXME. */ - nm = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPE, - DEBUG_LINKAGE_NONE); + nm = debug_add_to_namespace (info, &info->current_file->globals, name, + DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE); if (nm == NULL) return false; @@ -2018,6 +2056,61 @@ debug_record_type_size (handle, type, size) return true; } +/* Find a named type. */ + +debug_type +debug_find_named_type (handle, name) + PTR handle; + const char *name; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_block *b; + struct debug_file *f; + + /* We only search the current compilation unit. I don't know if + this is right or not. */ + + if (info->current_unit == NULL) + { + debug_error ("debug_find_named_type: no current compilation unit"); + return DEBUG_TYPE_NULL; + } + + for (b = info->current_block; b != NULL; b = b->parent) + { + if (b->locals != NULL) + { + struct debug_name *n; + + for (n = b->locals->list; n != NULL; n = n->next) + { + if (n->kind == DEBUG_OBJECT_TYPE + && n->name[0] == name[0] + && strcmp (n->name, name) == 0) + return n->u.type; + } + } + } + + for (f = info->current_unit->files; f != NULL; f = f->next) + { + if (f->globals != NULL) + { + struct debug_name *n; + + for (n = f->globals->list; n != NULL; n = n->next) + { + if (n->kind == DEBUG_OBJECT_TYPE + && n->name[0] == name[0] + && strcmp (n->name, name) == 0) + return n->u.type; + } + } + } + + return DEBUG_TYPE_NULL; +} + /* Find a tagged type. */ debug_type @@ -2045,7 +2138,7 @@ debug_find_tagged_type (handle, name, kind) for (n = f->globals->list; n != NULL; n = n->next) { if (n->kind == DEBUG_OBJECT_TAG - && (kind == DEBUG_KIND_VOID + && (kind == DEBUG_KIND_ILLEGAL || n->u.tag->kind == kind) && n->name[0] == name[0] && strcmp (n->name, name) == 0) @@ -2058,9 +2151,42 @@ debug_find_tagged_type (handle, name, kind) return DEBUG_TYPE_NULL; } +/* Get a base type. */ + +static struct debug_type * +debug_get_real_type (handle, type) + PTR handle; + debug_type type; +{ + switch (type->kind) + { + default: + return type; + case DEBUG_KIND_INDIRECT: + if (*type->u.kindirect->slot != NULL) + return debug_get_real_type (handle, *type->u.kindirect->slot); + return type; + case DEBUG_KIND_NAMED: + return debug_get_real_type (handle, type->u.knamed->type); + } + /*NOTREACHED*/ +} + +/* Get the kind of a type. */ + +enum debug_type_kind +debug_get_type_kind (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return DEBUG_KIND_ILLEGAL; + type = debug_get_real_type (handle, type); + return type->kind; +} + /* Get the name of a type. */ -/*ARGSUSED*/ const char * debug_get_type_name (handle, type) PTR handle; @@ -2077,6 +2203,86 @@ debug_get_type_name (handle, type) return type->u.knamed->name->name; return NULL; } + +/* Get the return type of a function or method type. */ + +debug_type +debug_get_return_type (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return DEBUG_TYPE_NULL; + type = debug_get_real_type (handle, type); + switch (type->kind) + { + default: + return DEBUG_TYPE_NULL; + case DEBUG_KIND_FUNCTION: + return type->u.kfunction->return_type; + case DEBUG_KIND_METHOD: + return type->u.kmethod->return_type; + } + /*NOTREACHED*/ +} + +/* Get the parameter types of a function or method type (except that + we don't currently store the parameter types of a function). */ + +const debug_type * +debug_get_parameter_types (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return NULL; + type = debug_get_real_type (handle, type); + switch (type->kind) + { + default: + return NULL; + case DEBUG_KIND_METHOD: + return type->u.kmethod->arg_types; + } + /*NOTREACHED*/ +} + +/* Get the NULL terminated array of fields for a struct, union, or + class. */ + +const debug_field * +debug_get_fields (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return NULL; + type = debug_get_real_type (handle, type); + switch (type->kind) + { + default: + return NULL; + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_UNION: + case DEBUG_KIND_CLASS: + case DEBUG_KIND_UNION_CLASS: + return type->u.kclass->fields; + } + /*NOTREACHED*/ +} + +/* Get the type of a field. */ + +/*ARGSUSED*/ +debug_type +debug_get_field_type (handle, field) + PTR handle; + debug_field field; +{ + if (field == NULL) + return NULL; + return field->type; +} /* Write out the debugging information. This is given a handle to debugging information, and a set of function pointers to call. */ @@ -2096,6 +2302,11 @@ debug_write (handle, fns, fhandle) information more than once. */ ++info->mark; + /* The base_id field holds an ID value which will never be used, so + that we can tell whether we have assigned an ID during this call + to debug_write. */ + info->base_id = info->class_id; + for (u = info->units; u != NULL; u = u->next) { struct debug_file *f; @@ -2225,7 +2436,7 @@ debug_write_type (info, fns, fhandle, type, name) if (type->kind == DEBUG_KIND_NAMED) return (*fns->typedef_type) (fhandle, type->u.knamed->name->name); else - return (*fns->tag_type) (fhandle, type->u.knamed->name->name, + return (*fns->tag_type) (fhandle, type->u.knamed->name->name, 0, type->u.knamed->type->kind); } @@ -2247,6 +2458,9 @@ debug_write_type (info, fns, fhandle, type, name) switch (type->kind) { + case DEBUG_KIND_ILLEGAL: + debug_error ("debug_write_type: illegal type encountered"); + return false; case DEBUG_KIND_INDIRECT: if (*type->u.kindirect->slot == DEBUG_TYPE_NULL) return (*fns->empty_type) (fhandle); @@ -2266,17 +2480,25 @@ debug_write_type (info, fns, fhandle, type, name) case DEBUG_KIND_UNION: if (type->u.kclass != NULL) { - if (info->class_mark == type->u.kclass->mark) + if (info->class_mark == type->u.kclass->mark + || type->u.kclass->id > info->base_id) { - /* We are currently outputting this struct. I don't - know if this can happen, but it can happen for a - class. */ - return (*fns->tag_type) (fhandle, "?defining?", type->kind); + /* We are currently outputting this struct, or we have + already output it. I don't know if this can happen, + but it can happen for a class. */ + assert (type->u.kclass->id > info->base_id); + return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, + type->kind); } type->u.kclass->mark = info->class_mark; + ++info->class_id; + type->u.kclass->id = info->class_id; } if (! (*fns->start_struct_type) (fhandle, tag, + (type->u.kclass != NULL + ? type->u.kclass->id + : 0), type->kind == DEBUG_KIND_STRUCT, type->size)) return false; @@ -2361,10 +2583,18 @@ debug_write_type (info, fns, fhandle, type, name) { for (i = 0; type->u.kmethod->arg_types[i] != NULL; i++) { - if (! debug_write_type (info, fns, fhandle, - type->u.kmethod->arg_types[i], - (struct debug_name *) NULL)) - return false; + if (ELLIPSIS_P (type->u.kmethod->arg_types[i])) + { + if (! (*fns->ellipsis_type) (fhandle)) + return false; + } + else + { + if (! debug_write_type (info, fns, fhandle, + type->u.kmethod->arg_types[i], + (struct debug_name *) NULL)) + return false; + } } } if (type->u.kmethod->domain_type != NULL) @@ -2410,32 +2640,45 @@ debug_write_class_type (info, fns, fhandle, type, tag) const char *tag; { unsigned int i; + unsigned int id; + struct debug_type *vptrbase; - if (type->u.kclass != NULL) + if (type->u.kclass == NULL) { - if (info->class_mark == type->u.kclass->mark) + id = 0; + vptrbase = NULL; + } + else + { + if (info->class_mark == type->u.kclass->mark + || type->u.kclass->id > info->base_id) { - /* We are currently outputting this class. This can happen - when there are methods for an anonymous class. */ - return (*fns->tag_type) (fhandle, "?defining?", type->kind); + /* We are currently outputting this class, or we have + already output it. This can happen when there are + methods for an anonymous class. */ + assert (type->u.kclass->id > info->base_id); + return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, + type->kind); } type->u.kclass->mark = info->class_mark; + ++info->class_id; + id = info->class_id; + type->u.kclass->id = id; - if (type->u.kclass->vptrbase != NULL - && type->u.kclass->vptrbase != type) + vptrbase = type->u.kclass->vptrbase; + if (vptrbase != NULL && vptrbase != type) { - if (! debug_write_type (info, fns, fhandle, - type->u.kclass->vptrbase, + if (! debug_write_type (info, fns, fhandle, vptrbase, (struct debug_name *) NULL)) return false; } } - if (! (*fns->start_class_type) (fhandle, tag, + if (! (*fns->start_class_type) (fhandle, tag, id, type->kind == DEBUG_KIND_CLASS, type->size, - type->u.kclass->vptrbase != NULL, - type->u.kclass->vptrbase == type)) + vptrbase != NULL, + vptrbase == type)) return false; if (type->u.kclass != NULL) @@ -2508,7 +2751,7 @@ debug_write_class_type (info, fns, fhandle, type, tag) return false; if (v->voffset != VOFFSET_STATIC_METHOD) { - if (! (*fns->class_method_variant) (fhandle, v->argtypes, + if (! (*fns->class_method_variant) (fhandle, v->physname, v->visibility, v->constp, v->volatilep, @@ -2519,7 +2762,7 @@ debug_write_class_type (info, fns, fhandle, type, tag) else { if (! (*fns->class_static_method_variant) (fhandle, - v->argtypes, + v->physname, v->visibility, v->constp, v->volatilep)) diff --git a/binutils/debug.h b/binutils/debug.h index 0c3a692258d..d40679bb57b 100644 --- a/binutils/debug.h +++ b/binutils/debug.h @@ -32,6 +32,8 @@ enum debug_type_kind { + /* Not used. */ + DEBUG_KIND_ILLEGAL, /* Indirect via a pointer. */ DEBUG_KIND_INDIRECT, /* Void. */ @@ -172,6 +174,11 @@ struct debug_write_fns /* Each writer must keep a stack of types. */ + /* Push an ellipsis type onto the type stack. This is not a real + type, but is used when a method takes a variable number of + arguments. */ + boolean (*ellipsis_type) PARAMS ((PTR)); + /* Push an empty type onto the type stack. This type can appear if there is a reference to a type which is never defined. */ boolean (*empty_type) PARAMS ((PTR)); @@ -258,13 +265,14 @@ 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 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. If this is an undefined struct or union, the size will - be 0 and struct_field will not be called before end_struct_type - is called. */ - boolean (*start_struct_type) PARAMS ((PTR, const char *, boolean, - unsigned int)); + will be NULL if there isn't one. If the second argument is NULL, + the third argument is a constant identifying this struct for use + with tag_type. The fourth argument is true for a struct, false + for a union. The fifth argument is the size. If this is an + undefined struct or union, the size will be 0 and struct_field + will not be called before end_struct_type is called. */ + boolean (*start_struct_type) PARAMS ((PTR, const char *, unsigned int, + 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 @@ -280,16 +288,16 @@ 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 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)); + finished by a call to end_class_type. The first five arguments + are the same as for start_struct_type. The sixth argument is + true if there is a virtual function table; if there is, the + seventh 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 *, unsigned int, + 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 @@ -314,12 +322,11 @@ struct debug_write_fns /* Describe a variant to the class method currently being built. The type of the variant must be popped off the type stack. The - second argument is a string which is either the physical name of - the function or describes the argument types; see the comment for - debug_make_method variant. The following arguments are the - visibility, whether the variant is const, whether the variant is - volatile, the offset in the virtual function table, and whether - the context is on the type stack (below the variant type). */ + second argument is the physical name of the function. The + following arguments are the visibility, whether the variant is + const, whether the variant is volatile, the offset in the virtual + function table, and whether the context is on the type stack + (below the variant type). */ boolean (*class_method_variant) PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, @@ -343,9 +350,17 @@ struct debug_write_fns call to typdef. */ boolean (*typedef_type) PARAMS ((PTR, const char *)); - /* Push a type on the stack which was given a name by an earlier - call to tag. */ - boolean (*tag_type) PARAMS ((PTR, const char *, enum debug_type_kind)); + /* Push a tagged type on the stack which was defined earlier. If + the second argument is not NULL, the type was defined by a call + to tag. If the second argument is NULL, the type was defined by + a call to start_struct_type or start_class_type with a tag of + NULL and the number of the third argument. Either way, the + fourth argument is the tag kind. Note that this may be called + for a struct (class) being defined, in between the call to + start_struct_type (start_class_type) and the call to + end_struct_type (end_class_type). */ + boolean (*tag_type) PARAMS ((PTR, const char *, unsigned int, + enum debug_type_kind)); /* Pop the type stack, and typedef it to the given name. */ boolean (*typdef) PARAMS ((PTR, const char *)); @@ -504,6 +519,13 @@ extern boolean debug_record_variable extern debug_type debug_make_indirect_type PARAMS ((PTR, debug_type *, const char *)); +/* Make an ellipsis type. This is not a type at all, but is a marker + suitable for appearing in the list of argument types passed to + debug_make_method_type. It should be used to indicate a method + which takes a variable number of arguments. */ + +extern debug_type debug_make_ellipsis_type PARAMS ((PTR)); + /* Make a void type. */ extern debug_type debug_make_void_type PARAMS ((PTR)); @@ -656,10 +678,9 @@ extern debug_field debug_make_static_member extern debug_method debug_make_method PARAMS ((PTR, const char *, debug_method_variant *)); -/* Make a method variant. The second argument is either the physical - name of the function, or the encoded argument types, depending upon - whether the third argument specifies the argument types or not. - The third argument is the type of the function. The fourth +/* Make a method variant. The second argument is the physical name of + the function. The third argument is the type of the function, + probably constructed by debug_make_method_type. The fourth argument is the visibility. The fifth argument is whether this is a const function. The sixth argument is whether this is a volatile function. The seventh argument is the offset in the virtual @@ -693,15 +714,43 @@ extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type)); extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int)); +/* Find a named type. */ + +extern debug_type debug_find_named_type PARAMS ((PTR, const char *)); + /* Find a tagged type. */ extern debug_type debug_find_tagged_type PARAMS ((PTR, const char *, enum debug_type_kind)); +/* Get the kind of a type. */ + +extern enum debug_type_kind debug_get_type_kind PARAMS ((PTR, debug_type)); + /* Get the name of a type. */ extern const char *debug_get_type_name PARAMS ((PTR, debug_type)); +/* Get the return type of a function or method type. */ + +extern debug_type debug_get_return_type PARAMS ((PTR, debug_type)); + +/* Get the NULL terminated array of parameter types for a function or + method type (actually, parameter types are not currently stored for + function types). This may be used to determine whether a method + type is a stub method or not. */ + +extern const debug_type *debug_get_parameter_types PARAMS ((PTR, debug_type)); + +/* Get the NULL terminated array of fields for a struct, union, or + class. */ + +extern const debug_field *debug_get_fields PARAMS ((PTR, debug_type)); + +/* Get the type of a field. */ + +extern debug_type debug_get_field_type PARAMS ((PTR, debug_field)); + /* Write out the recorded debugging information. This takes a set of function pointers which are called to do the actual writing. The first PTR is the debugging handle. The second PTR is a handle diff --git a/binutils/ieee.c b/binutils/ieee.c index ac85f7320d1..0006460b4cc 100644 --- a/binutils/ieee.c +++ b/binutils/ieee.c @@ -2267,7 +2267,7 @@ struct ieee_name_type /* Type. */ struct ieee_write_type type; /* If this is a tag which has not yet been defined, this is the - kind. If the tag has been defined, this is DEBUG_KIND_VOID. */ + kind. If the tag has been defined, this is DEBUG_KIND_ILLEGAL. */ enum debug_type_kind kind; }; @@ -2357,6 +2357,7 @@ static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *)); static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *)); static boolean ieee_start_source PARAMS ((PTR, const char *)); +static boolean ieee_ellipsis_type PARAMS ((PTR)); static boolean ieee_empty_type PARAMS ((PTR)); static boolean ieee_void_type PARAMS ((PTR)); static boolean ieee_int_type PARAMS ((PTR, unsigned int, boolean)); @@ -2377,12 +2378,13 @@ static boolean ieee_method_type PARAMS ((PTR, boolean, int)); static boolean ieee_const_type PARAMS ((PTR)); static boolean ieee_volatile_type PARAMS ((PTR)); static boolean ieee_start_struct_type - PARAMS ((PTR, const char *, boolean, unsigned int)); + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int)); static boolean ieee_struct_field PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); static boolean ieee_end_struct_type PARAMS ((PTR)); static boolean ieee_start_class_type - PARAMS ((PTR, const char *, boolean, unsigned int, boolean, boolean)); + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, + boolean)); static boolean ieee_class_static_member PARAMS ((PTR, const char *, const char *, enum debug_visibility)); static boolean ieee_class_baseclass @@ -2397,7 +2399,7 @@ static boolean ieee_class_end_method PARAMS ((PTR)); static boolean ieee_end_class_type PARAMS ((PTR)); static boolean ieee_typedef_type PARAMS ((PTR, const char *)); static boolean ieee_tag_type - PARAMS ((PTR, const char *, enum debug_type_kind)); + PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); static boolean ieee_typdef PARAMS ((PTR, const char *)); static boolean ieee_tag PARAMS ((PTR, const char *)); static boolean ieee_int_constant PARAMS ((PTR, const char *, bfd_vma)); @@ -2418,6 +2420,7 @@ static const struct debug_write_fns ieee_fns = { ieee_start_compilation_unit, ieee_start_source, + ieee_ellipsis_type, ieee_empty_type, ieee_void_type, ieee_int_type, @@ -2797,7 +2800,7 @@ ieee_define_named_type (info, name, tagp, size, unsignedp, ppbuf) nt->type.size = size; nt->type.unsignedp = unsignedp; - nt->kind = DEBUG_KIND_VOID; + nt->kind = DEBUG_KIND_ILLEGAL; type_indx = nt->type.indx; } @@ -2878,7 +2881,7 @@ write_ieee_debugging_info (abfd, dhandle) unsigned int name_indx; char code; - if (nt->kind == DEBUG_KIND_VOID) + if (nt->kind == DEBUG_KIND_ILLEGAL) continue; if (tags == NULL) { @@ -3158,6 +3161,15 @@ ieee_start_source (p, filename) return true; } +/* Make an ellipsis type. */ + +static boolean +ieee_ellipsis_type (p) + PTR p; +{ + abort (); +} + /* Make an empty type. */ static boolean @@ -3598,9 +3610,10 @@ ieee_volatile_type (p) fields with the struct type itself. */ static boolean -ieee_start_struct_type (p, tag, structp, size) +ieee_start_struct_type (p, tag, id, structp, size) PTR p; const char *tag; + unsigned int id; boolean structp; unsigned int size; { @@ -3699,9 +3712,10 @@ ieee_end_struct_type (p) /* Start a class type. */ static boolean -ieee_start_class_type (p, tag, structp, size, vptr, ownvptr) +ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr) PTR p; const char *tag; + unsigned int id; boolean structp; unsigned int size; boolean vptr; @@ -3712,7 +3726,7 @@ ieee_start_class_type (p, tag, structp, size, vptr, ownvptr) /* FIXME. */ if (vptr && ! ownvptr) (void) ieee_pop_type (info); - return ieee_start_struct_type (p, tag, structp, size); + return ieee_start_struct_type (p, tag, id, structp, size); } /* Add a static member to a class. */ @@ -3761,10 +3775,10 @@ ieee_class_start_method (p, name) /* Define a new method variant. */ static boolean -ieee_class_method_variant (p, name, visibility, constp, volatilep, +ieee_class_method_variant (p, physname, visibility, constp, volatilep, voffset, context) PTR p; - const char *name; + const char *physname; enum debug_visibility visibility; boolean constp; boolean volatilep; @@ -3783,9 +3797,9 @@ ieee_class_method_variant (p, name, visibility, constp, volatilep, /* Define a new static method variant. */ static boolean -ieee_class_static_method_variant (p, name, visibility, constp, volatilep) +ieee_class_static_method_variant (p, physname, visibility, constp, volatilep) PTR p; - const char *name; + const char *physname; enum debug_visibility visibility; boolean constp; boolean volatilep; @@ -3846,14 +3860,18 @@ ieee_typedef_type (p, name) /* Push a tagged type onto the type stack. */ static boolean -ieee_tag_type (p, name, kind) +ieee_tag_type (p, name, id, kind) PTR p; const char *name; + unsigned int id; enum debug_type_kind kind; { struct ieee_handle *info = (struct ieee_handle *) p; register struct ieee_name_type *nt; + if (name == NULL) + return true; + for (nt = info->tags; nt != NULL; nt = nt->next) { if (nt->name[0] == name[0] @@ -3899,7 +3917,7 @@ ieee_typdef (p, name) memset (nt, 0, sizeof *nt); nt->name = name; nt->type = info->type_stack->type; - nt->kind = DEBUG_KIND_VOID; + nt->kind = DEBUG_KIND_ILLEGAL; nt->next = info->typedefs; info->typedefs = nt; diff --git a/binutils/prdbg.c b/binutils/prdbg.c index 133973ca0a7..f7383bb3367 100644 --- a/binutils/prdbg.c +++ b/binutils/prdbg.c @@ -72,6 +72,7 @@ static boolean pr_fix_visibility static boolean pr_start_compilation_unit PARAMS ((PTR, const char *)); static boolean pr_start_source PARAMS ((PTR, const char *)); +static boolean pr_ellipsis_type PARAMS ((PTR)); static boolean pr_empty_type PARAMS ((PTR)); static boolean pr_void_type PARAMS ((PTR)); static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean)); @@ -92,12 +93,13 @@ 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, const char *, boolean, unsigned int)); + PARAMS ((PTR, const char *, unsigned int, 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, const char *, boolean, unsigned int, boolean, boolean)); + PARAMS ((PTR, const char *, unsigned int, 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 @@ -111,7 +113,8 @@ static boolean pr_class_static_method_variant static boolean pr_class_end_method PARAMS ((PTR)); static boolean pr_end_class_type PARAMS ((PTR)); static boolean pr_typedef_type PARAMS ((PTR, const char *)); -static boolean pr_tag_type PARAMS ((PTR, const char *, enum debug_type_kind)); +static boolean pr_tag_type + PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); static boolean pr_typdef PARAMS ((PTR, const char *)); static boolean pr_tag PARAMS ((PTR, const char *)); static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma)); @@ -131,6 +134,7 @@ static const struct debug_write_fns pr_fns = { pr_start_compilation_unit, pr_start_source, + pr_ellipsis_type, pr_empty_type, pr_void_type, pr_int_type, @@ -409,6 +413,17 @@ pr_start_source (p, filename) return true; } +/* Push an ellipsis type onto the type stack. */ + +static boolean +pr_ellipsis_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + return push_type (info, "..."); +} + /* Push an empty type onto the type stack. */ static boolean @@ -563,9 +578,13 @@ pr_pointer_type (p) PTR p; { struct pr_handle *info = (struct pr_handle *) p; + char *s; assert (info->stack != NULL); + s = strchr (info->stack->type, '|'); + if (s != NULL && s[1] == '[') + return substitute_type (info, "(*|)"); return substitute_type (info, "*|"); } @@ -838,9 +857,10 @@ pr_volatile_type (p) /* Start accumulating a struct type. */ static boolean -pr_start_struct_type (p, tag, structp, size) +pr_start_struct_type (p, tag, id, structp, size) PTR p; const char *tag; + unsigned int id; boolean structp; unsigned int size; { @@ -853,14 +873,22 @@ pr_start_struct_type (p, tag, structp, size) return false; if (tag != NULL) { - if (! append_type (info, tag) - || ! append_type (info, " ")) + if (! append_type (info, tag)) + return false; + } + else + { + char idbuf[20]; + + sprintf (idbuf, "%%anon%u", id); + if (! append_type (info, idbuf)) return false; } + if (size != 0) - sprintf (ab, "{ /* size %u */\n", size); + sprintf (ab, " { /* size %u */\n", size); else - strcpy (ab, "{\n"); + strcpy (ab, " {\n"); if (! append_type (info, ab)) return false; info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; @@ -875,16 +903,15 @@ pr_fix_visibility (info, visibility) enum debug_visibility visibility; { const char *s; - struct pr_stack *top; char *t; unsigned int len; - assert (info->stack != NULL && info->stack->next != NULL); + assert (info->stack != NULL); - if (info->stack->next->visibility == visibility) + if (info->stack->visibility == visibility) return true; - assert (info->stack->next->visibility != DEBUG_VISIBILITY_IGNORE); + assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE); switch (visibility) { @@ -903,12 +930,7 @@ pr_fix_visibility (info, visibility) } /* Trim off a trailing space in the struct string, to make the - output look a bit better, then stick on the visibility string. - Pop the stack temporarily to make the string manipulation - simpler. */ - - top = info->stack; - info->stack = top->next; + output look a bit better, then stick on the visibility string. */ t = info->stack->type; len = strlen (t); @@ -922,8 +944,6 @@ pr_fix_visibility (info, visibility) info->stack->visibility = visibility; - info->stack = top; - return true; } @@ -939,9 +959,7 @@ pr_struct_field (p, name, bitpos, bitsize, visibility) { struct pr_handle *info = (struct pr_handle *) p; char ab[20]; - - if (! pr_fix_visibility (info, visibility)) - return false; + char *t; if (! substitute_type (info, name)) return false; @@ -965,7 +983,14 @@ pr_struct_field (p, name, bitpos, bitsize, visibility) || ! indent_type (info)) return false; - return append_type (info, pop_type (info)); + t = pop_type (info); + if (t == NULL) + return false; + + if (! pr_fix_visibility (info, visibility)) + return false; + + return append_type (info, t); } /* Finish a struct type. */ @@ -995,9 +1020,10 @@ pr_end_struct_type (p) /* Start a class type. */ static boolean -pr_start_class_type (p, tag, structp, size, vptr, ownvptr) +pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr) PTR p; const char *tag; + unsigned int id; boolean structp; unsigned int size; boolean vptr; @@ -1019,11 +1045,19 @@ pr_start_class_type (p, tag, structp, size, vptr, ownvptr) return false; if (tag != NULL) { - if (! append_type (info, tag) - || ! append_type (info, " ")) + if (! append_type (info, tag)) return false; } - if (! append_type (info, "{")) + else + { + char idbuf[20]; + + sprintf (idbuf, "%%anon%u", id); + if (! append_type (info, idbuf)) + return false; + } + + if (! append_type (info, " {")) return false; if (size != 0 || vptr || ownvptr) { @@ -1077,19 +1111,26 @@ pr_class_static_member (p, name, physname, visibility) enum debug_visibility visibility; { struct pr_handle *info = (struct pr_handle *) p; + char *t; - if (! pr_fix_visibility (info, visibility)) + if (! substitute_type (info, name)) return false; - if (! substitute_type (info, name)) + if (! prepend_type (info, "static ") + || ! append_type (info, "; /* ") + || ! append_type (info, physname) + || ! append_type (info, " */\n") + || ! indent_type (info)) return false; - return (prepend_type (info, "static ") - && append_type (info, "; /* physname ") - && append_type (info, physname) - && append_type (info, " */\n") - && indent_type (info) - && append_type (info, pop_type (info))); + t = pop_type (info); + if (t == NULL) + return false; + + if (! pr_fix_visibility (info, visibility)) + return false; + + return append_type (info, t); } /* Add a base class to a class. */ @@ -1200,8 +1241,7 @@ pr_class_start_method (p, name) { struct pr_handle *info = (struct pr_handle *) p; - if (! push_type (info, "")) - return false; + assert (info->stack != NULL); info->stack->method = name; return true; } @@ -1209,10 +1249,10 @@ pr_class_start_method (p, name) /* Add a variant to a method. */ static boolean -pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset, +pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset, context) PTR p; - const char *argtypes; + const char *physname; enum debug_visibility visibility; boolean constp; boolean volatilep; @@ -1229,12 +1269,12 @@ pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset, /* Put the const and volatile qualifiers on the type. */ if (volatilep) { - if (! prepend_type (info, "volatile ")) + if (! append_type (info, " volatile")) return false; } if (constp) { - if (! prepend_type (info, "const ")) + if (! append_type (info, " const")) return false; } @@ -1260,15 +1300,15 @@ pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset, return false; } - /* Now the top of the stack is the holder for the method, and the - second element on the stack is the class. */ + /* Now the top of the stack is the class. */ if (! pr_fix_visibility (info, visibility)) return false; if (! append_type (info, method_type) || ! append_type (info, " /* ") - || ! append_type (info, argtypes)) + || ! append_type (info, physname) + || ! append_type (info, " ")) return false; if (context || voffset != 0) { @@ -1294,9 +1334,9 @@ pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset, /* Add a static variant to a method. */ static boolean -pr_class_static_method_variant (p, argtypes, visibility, constp, volatilep) +pr_class_static_method_variant (p, physname, visibility, constp, volatilep) PTR p; - const char *argtypes; + const char *physname; enum debug_visibility visibility; boolean constp; boolean volatilep; @@ -1311,12 +1351,12 @@ pr_class_static_method_variant (p, argtypes, visibility, constp, volatilep) /* Put the const and volatile qualifiers on the type. */ if (volatilep) { - if (! prepend_type (info, "volatile ")) + if (! append_type (info, " volatile")) return false; } if (constp) { - if (! prepend_type (info, "const ")) + if (! append_type (info, " const")) return false; } @@ -1333,15 +1373,14 @@ pr_class_static_method_variant (p, argtypes, visibility, constp, volatilep) if (method_type == NULL) return false; - /* Now the top of the stack is the holder for the method, and the - second element on the stack is the class. */ + /* Now the top of the stack is the class. */ if (! pr_fix_visibility (info, visibility)) return false; return (append_type (info, method_type) && append_type (info, " /* ") - && append_type (info, argtypes) + && append_type (info, physname) && append_type (info, " */;\n") && indent_type (info)); } @@ -1354,11 +1393,8 @@ pr_class_end_method (p) { struct pr_handle *info = (struct pr_handle *) p; - /* The method variants have been appended to the string on top of - the stack with the correct indentation. We just need the append - the string on top of the stack to the class string that is second - on the stack. */ - return append_type (info, pop_type (info)); + info->stack->method = NULL; + return true; } /* Finish up a class. */ @@ -1385,13 +1421,15 @@ pr_typedef_type (p, name) /* Push a type on the stack using a tag name. */ static boolean -pr_tag_type (p, name, kind) +pr_tag_type (p, name, id, kind) PTR p; const char *name; + unsigned int id; enum debug_type_kind kind; { struct pr_handle *info = (struct pr_handle *) p; - const char *t; + const char *t, *tag; + char idbuf[20]; switch (kind) { @@ -1415,8 +1453,17 @@ pr_tag_type (p, name, kind) return false; } - return (push_type (info, t) - && append_type (info, name)); + if (! push_type (info, t)) + return false; + if (name != NULL) + tag = name; + else + { + sprintf (idbuf, "%%anon%u", id); + tag = idbuf; + } + + return append_type (info, tag); } /* Output a typedef. */ -- 2.30.2