|  | /* debug.c -- Handle generic debugging information. | 
|  | Copyright (C) 1995-2023 Free Software Foundation, Inc. | 
|  | Written by Ian Lance Taylor <ian@cygnus.com>. | 
|  |  | 
|  | This file is part of GNU Binutils. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program; if not, write to the Free Software | 
|  | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA | 
|  | 02110-1301, USA.  */ | 
|  |  | 
|  |  | 
|  | /* This file implements a generic debugging format.  We may eventually | 
|  | have readers which convert different formats into this generic | 
|  | format, and writers which write it out.  The initial impetus for | 
|  | this was writing a converter from stabs to HP IEEE-695 debugging | 
|  | format.  */ | 
|  |  | 
|  | #include "sysdep.h" | 
|  | #include <assert.h> | 
|  | #include "bfd.h" | 
|  | #include "libiberty.h" | 
|  | #include "filenames.h" | 
|  | #include "bucomm.h" | 
|  | #include "debug.h" | 
|  |  | 
|  | /* Global information we keep for debugging.  A pointer to this | 
|  | structure is the debugging handle passed to all the routines.  */ | 
|  |  | 
|  | struct debug_handle | 
|  | { | 
|  | /* The bfd where we objalloc memory.  */ | 
|  | bfd *abfd; | 
|  | /* A linked list of compilation units.  */ | 
|  | struct debug_unit *units; | 
|  | /* The current compilation unit.  */ | 
|  | struct debug_unit *current_unit; | 
|  | /* The current source file.  */ | 
|  | struct debug_file *current_file; | 
|  | /* The current function.  */ | 
|  | struct debug_function *current_function; | 
|  | /* The current block.  */ | 
|  | struct debug_block *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; | 
|  | /* 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; | 
|  | /* The current line number in debug_write.  */ | 
|  | struct debug_lineno *current_write_lineno; | 
|  | unsigned int current_write_lineno_index; | 
|  | /* A list of classes which have assigned ID's during debug_write. | 
|  | This is linked through the next_id field of debug_class_type.  */ | 
|  | struct debug_class_id *id_list; | 
|  | /* A list used to avoid recursion during debug_type_samep.  */ | 
|  | struct debug_type_compare_list *compare_list; | 
|  | }; | 
|  |  | 
|  | /* Information we keep for a single compilation unit.  */ | 
|  |  | 
|  | struct debug_unit | 
|  | { | 
|  | /* The next compilation unit.  */ | 
|  | struct debug_unit *next; | 
|  | /* A list of files included in this compilation unit.  The first | 
|  | 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.  */ | 
|  |  | 
|  | struct debug_file | 
|  | { | 
|  | /* The next source file in this compilation unit.  */ | 
|  | struct debug_file *next; | 
|  | /* The name of the source file.  */ | 
|  | const char *filename; | 
|  | /* Global functions, variables, types, etc.  */ | 
|  | struct debug_namespace *globals; | 
|  | }; | 
|  |  | 
|  | /* A type.  */ | 
|  |  | 
|  | struct debug_type_s | 
|  | { | 
|  | /* Kind of type.  */ | 
|  | enum debug_type_kind kind; | 
|  | /* Size of type (0 if not known).  */ | 
|  | unsigned int size; | 
|  | /* Type which is a pointer to this type.  */ | 
|  | debug_type pointer; | 
|  | /* Tagged union with additional information about the type.  */ | 
|  | union | 
|  | { | 
|  | /* DEBUG_KIND_INDIRECT.  */ | 
|  | struct debug_indirect_type *kindirect; | 
|  | /* DEBUG_KIND_INT.  */ | 
|  | /* Whether the integer is unsigned.  */ | 
|  | bool kint; | 
|  | /* DEBUG_KIND_STRUCT, DEBUG_KIND_UNION, DEBUG_KIND_CLASS, | 
|  | DEBUG_KIND_UNION_CLASS.  */ | 
|  | struct debug_class_type *kclass; | 
|  | /* DEBUG_KIND_ENUM.  */ | 
|  | struct debug_enum_type *kenum; | 
|  | /* DEBUG_KIND_POINTER.  */ | 
|  | struct debug_type_s *kpointer; | 
|  | /* DEBUG_KIND_FUNCTION.  */ | 
|  | struct debug_function_type *kfunction; | 
|  | /* DEBUG_KIND_REFERENCE.  */ | 
|  | struct debug_type_s *kreference; | 
|  | /* DEBUG_KIND_RANGE.  */ | 
|  | struct debug_range_type *krange; | 
|  | /* DEBUG_KIND_ARRAY.  */ | 
|  | struct debug_array_type *karray; | 
|  | /* DEBUG_KIND_SET.  */ | 
|  | struct debug_set_type *kset; | 
|  | /* DEBUG_KIND_OFFSET.  */ | 
|  | struct debug_offset_type *koffset; | 
|  | /* DEBUG_KIND_METHOD.  */ | 
|  | struct debug_method_type *kmethod; | 
|  | /* DEBUG_KIND_CONST.  */ | 
|  | struct debug_type_s *kconst; | 
|  | /* DEBUG_KIND_VOLATILE.  */ | 
|  | struct debug_type_s *kvolatile; | 
|  | /* DEBUG_KIND_NAMED, DEBUG_KIND_TAGGED.  */ | 
|  | struct debug_named_type *knamed; | 
|  | } u; | 
|  | }; | 
|  |  | 
|  | /* Information kept for an indirect type.  */ | 
|  |  | 
|  | struct debug_indirect_type | 
|  | { | 
|  | /* Slot where the final type will appear.  */ | 
|  | debug_type *slot; | 
|  | /* Tag.  */ | 
|  | const char *tag; | 
|  | }; | 
|  |  | 
|  | /* Information kept for a struct, union, or class.  */ | 
|  |  | 
|  | struct debug_class_type | 
|  | { | 
|  | /* NULL terminated array of fields.  */ | 
|  | debug_field *fields; | 
|  | /* A mark field which indicates whether the struct has already been | 
|  | printed.  */ | 
|  | 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.  */ | 
|  | debug_baseclass *baseclasses; | 
|  | /* NULL terminated array of methods.  */ | 
|  | debug_method *methods; | 
|  | /* The type of the class providing the virtual function table for | 
|  | this class.  This may point to the type itself.  */ | 
|  | debug_type vptrbase; | 
|  | }; | 
|  |  | 
|  | /* Information kept for an enum.  */ | 
|  |  | 
|  | struct debug_enum_type | 
|  | { | 
|  | /* NULL terminated array of names.  */ | 
|  | const char **names; | 
|  | /* Array of corresponding values.  */ | 
|  | bfd_signed_vma *values; | 
|  | }; | 
|  |  | 
|  | /* Information kept for a function.  FIXME: We should be able to | 
|  | record the parameter types.  */ | 
|  |  | 
|  | struct debug_function_type | 
|  | { | 
|  | /* Return type.  */ | 
|  | debug_type return_type; | 
|  | /* NULL terminated array of argument types.  */ | 
|  | debug_type *arg_types; | 
|  | /* Whether the function takes a variable number of arguments.  */ | 
|  | bool varargs; | 
|  | }; | 
|  |  | 
|  | /* Information kept for a range.  */ | 
|  |  | 
|  | struct debug_range_type | 
|  | { | 
|  | /* Range base type.  */ | 
|  | debug_type type; | 
|  | /* Lower bound.  */ | 
|  | bfd_signed_vma lower; | 
|  | /* Upper bound.  */ | 
|  | bfd_signed_vma upper; | 
|  | }; | 
|  |  | 
|  | /* Information kept for an array.  */ | 
|  |  | 
|  | struct debug_array_type | 
|  | { | 
|  | /* Element type.  */ | 
|  | debug_type element_type; | 
|  | /* Range type.  */ | 
|  | debug_type range_type; | 
|  | /* Lower bound.  */ | 
|  | bfd_signed_vma lower; | 
|  | /* Upper bound.  */ | 
|  | bfd_signed_vma upper; | 
|  | /* Whether this array is really a string.  */ | 
|  | bool stringp; | 
|  | }; | 
|  |  | 
|  | /* Information kept for a set.  */ | 
|  |  | 
|  | struct debug_set_type | 
|  | { | 
|  | /* Base type.  */ | 
|  | debug_type type; | 
|  | /* Whether this set is really a bitstring.  */ | 
|  | bool bitstringp; | 
|  | }; | 
|  |  | 
|  | /* Information kept for an offset type (a based pointer).  */ | 
|  |  | 
|  | struct debug_offset_type | 
|  | { | 
|  | /* The type the pointer is an offset from.  */ | 
|  | debug_type base_type; | 
|  | /* The type the pointer points to.  */ | 
|  | debug_type target_type; | 
|  | }; | 
|  |  | 
|  | /* Information kept for a method type.  */ | 
|  |  | 
|  | struct debug_method_type | 
|  | { | 
|  | /* The return type.  */ | 
|  | debug_type return_type; | 
|  | /* The object type which this method is for.  */ | 
|  | debug_type domain_type; | 
|  | /* A NULL terminated array of argument types.  */ | 
|  | debug_type *arg_types; | 
|  | /* Whether the method takes a variable number of arguments.  */ | 
|  | bool varargs; | 
|  | }; | 
|  |  | 
|  | /* Information kept for a named type.  */ | 
|  |  | 
|  | struct debug_named_type | 
|  | { | 
|  | /* Name.  */ | 
|  | struct debug_name *name; | 
|  | /* Real type.  */ | 
|  | debug_type type; | 
|  | }; | 
|  |  | 
|  | /* A field in a struct or union.  */ | 
|  |  | 
|  | struct debug_field_s | 
|  | { | 
|  | /* Name of the field.  */ | 
|  | const char *name; | 
|  | /* Type of the field.  */ | 
|  | struct debug_type_s *type; | 
|  | /* Visibility of the field.  */ | 
|  | enum debug_visibility visibility; | 
|  | /* Whether this is a static member.  */ | 
|  | bool static_member; | 
|  | union | 
|  | { | 
|  | /* If static_member is false.  */ | 
|  | struct | 
|  | { | 
|  | /* Bit position of the field in the struct.  */ | 
|  | unsigned int bitpos; | 
|  | /* Size of the field in bits.  */ | 
|  | unsigned int bitsize; | 
|  | } f; | 
|  | /* If static_member is true.  */ | 
|  | struct | 
|  | { | 
|  | const char *physname; | 
|  | } s; | 
|  | } u; | 
|  | }; | 
|  |  | 
|  | /* A base class for an object.  */ | 
|  |  | 
|  | struct debug_baseclass_s | 
|  | { | 
|  | /* Type of the base class.  */ | 
|  | struct debug_type_s *type; | 
|  | /* Bit position of the base class in the object.  */ | 
|  | unsigned int bitpos; | 
|  | /* Whether the base class is virtual.  */ | 
|  | bool is_virtual; | 
|  | /* Visibility of the base class.  */ | 
|  | enum debug_visibility visibility; | 
|  | }; | 
|  |  | 
|  | /* A method of an object.  */ | 
|  |  | 
|  | struct debug_method_s | 
|  | { | 
|  | /* The name of the method.  */ | 
|  | const char *name; | 
|  | /* A NULL terminated array of different types of variants.  */ | 
|  | struct debug_method_variant_s **variants; | 
|  | }; | 
|  |  | 
|  | /* The variants of a method function of an object.  These indicate | 
|  | which method to run.  */ | 
|  |  | 
|  | struct debug_method_variant_s | 
|  | { | 
|  | /* The physical name of the function.  */ | 
|  | const char *physname; | 
|  | /* The type of the function.  */ | 
|  | struct debug_type_s *type; | 
|  | /* The visibility of the function.  */ | 
|  | enum debug_visibility visibility; | 
|  | /* Whether the function is const.  */ | 
|  | bool constp; | 
|  | /* Whether the function is volatile.  */ | 
|  | bool volatilep; | 
|  | /* The offset to the function in the virtual function table.  */ | 
|  | bfd_vma voffset; | 
|  | /* If voffset is VOFFSET_STATIC_METHOD, this is a static method.  */ | 
|  | #define VOFFSET_STATIC_METHOD ((bfd_vma) -1) | 
|  | /* Context of a virtual method function.  */ | 
|  | struct debug_type_s *context; | 
|  | }; | 
|  |  | 
|  | /* A variable.  This is the information we keep for a variable object. | 
|  | This has no name; a name is associated with a variable in a | 
|  | debug_name structure.  */ | 
|  |  | 
|  | struct debug_variable | 
|  | { | 
|  | /* Kind of variable.  */ | 
|  | enum debug_var_kind kind; | 
|  | /* Type.  */ | 
|  | debug_type type; | 
|  | /* Value.  The interpretation of the value depends upon kind.  */ | 
|  | bfd_vma val; | 
|  | }; | 
|  |  | 
|  | /* A function.  This has no name; a name is associated with a function | 
|  | in a debug_name structure.  */ | 
|  |  | 
|  | struct debug_function | 
|  | { | 
|  | /* Return type.  */ | 
|  | debug_type return_type; | 
|  | /* Parameter information.  */ | 
|  | struct debug_parameter *parameters; | 
|  | /* Block information.  The first structure on the list is the main | 
|  | block of the function, and describes function local variables.  */ | 
|  | struct debug_block *blocks; | 
|  | }; | 
|  |  | 
|  | /* A function parameter.  */ | 
|  |  | 
|  | struct debug_parameter | 
|  | { | 
|  | /* Next parameter.  */ | 
|  | struct debug_parameter *next; | 
|  | /* Name.  */ | 
|  | const char *name; | 
|  | /* Type.  */ | 
|  | debug_type type; | 
|  | /* Kind.  */ | 
|  | enum debug_parm_kind kind; | 
|  | /* Value (meaning depends upon kind).  */ | 
|  | bfd_vma val; | 
|  | }; | 
|  |  | 
|  | /* A typed constant.  */ | 
|  |  | 
|  | struct debug_typed_constant | 
|  | { | 
|  | /* Type.  */ | 
|  | debug_type type; | 
|  | /* Value.  FIXME: We may eventually need to support non-integral | 
|  | values.  */ | 
|  | bfd_vma val; | 
|  | }; | 
|  |  | 
|  | /* Information about a block within a function.  */ | 
|  |  | 
|  | struct debug_block | 
|  | { | 
|  | /* Next block with the same parent.  */ | 
|  | struct debug_block *next; | 
|  | /* Parent block.  */ | 
|  | struct debug_block *parent; | 
|  | /* List of child blocks.  */ | 
|  | struct debug_block *children; | 
|  | /* Start address of the block.  */ | 
|  | bfd_vma start; | 
|  | /* End address of the block.  */ | 
|  | bfd_vma end; | 
|  | /* Local variables.  */ | 
|  | struct debug_namespace *locals; | 
|  | }; | 
|  |  | 
|  | /* 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 | 
|  | { | 
|  | /* More line number information for this block.  */ | 
|  | struct debug_lineno *next; | 
|  | /* Source file.  */ | 
|  | struct debug_file *file; | 
|  | /* Line numbers, terminated by a -1 or the end of the array.  */ | 
|  | #define DEBUG_LINENO_COUNT 10 | 
|  | unsigned long linenos[DEBUG_LINENO_COUNT]; | 
|  | /* Addresses for the line numbers.  */ | 
|  | bfd_vma addrs[DEBUG_LINENO_COUNT]; | 
|  | }; | 
|  |  | 
|  | /* A namespace.  This is a mapping from names to objects.  FIXME: This | 
|  | should be implemented as a hash table.  */ | 
|  |  | 
|  | struct debug_namespace | 
|  | { | 
|  | /* List of items in this namespace.  */ | 
|  | struct debug_name *list; | 
|  | /* Pointer to where the next item in this namespace should go.  */ | 
|  | struct debug_name **tail; | 
|  | }; | 
|  |  | 
|  | /* Kinds of objects that appear in a namespace.  */ | 
|  |  | 
|  | enum debug_object_kind | 
|  | { | 
|  | /* A type.  */ | 
|  | DEBUG_OBJECT_TYPE, | 
|  | /* A tagged type (really a different sort of namespace).  */ | 
|  | DEBUG_OBJECT_TAG, | 
|  | /* A variable.  */ | 
|  | DEBUG_OBJECT_VARIABLE, | 
|  | /* A function.  */ | 
|  | DEBUG_OBJECT_FUNCTION, | 
|  | /* An integer constant.  */ | 
|  | DEBUG_OBJECT_INT_CONSTANT, | 
|  | /* A floating point constant.  */ | 
|  | DEBUG_OBJECT_FLOAT_CONSTANT, | 
|  | /* A typed constant.  */ | 
|  | DEBUG_OBJECT_TYPED_CONSTANT | 
|  | }; | 
|  |  | 
|  | /* Linkage of an object that appears in a namespace.  */ | 
|  |  | 
|  | enum debug_object_linkage | 
|  | { | 
|  | /* Local variable.  */ | 
|  | DEBUG_LINKAGE_AUTOMATIC, | 
|  | /* Static--either file static or function static, depending upon the | 
|  | namespace is.  */ | 
|  | DEBUG_LINKAGE_STATIC, | 
|  | /* Global.  */ | 
|  | DEBUG_LINKAGE_GLOBAL, | 
|  | /* No linkage.  */ | 
|  | DEBUG_LINKAGE_NONE | 
|  | }; | 
|  |  | 
|  | /* A name in a namespace.  */ | 
|  |  | 
|  | struct debug_name | 
|  | { | 
|  | /* Next name in this namespace.  */ | 
|  | struct debug_name *next; | 
|  | /* Name.  */ | 
|  | const char *name; | 
|  | /* Mark.  This is used by debug_write.  */ | 
|  | unsigned int mark; | 
|  | /* Kind of object.  */ | 
|  | enum debug_object_kind kind; | 
|  | /* Linkage of object.  */ | 
|  | enum debug_object_linkage linkage; | 
|  | /* Tagged union with additional information about the object.  */ | 
|  | union | 
|  | { | 
|  | /* DEBUG_OBJECT_TYPE.  */ | 
|  | struct debug_type_s *type; | 
|  | /* DEBUG_OBJECT_TAG.  */ | 
|  | struct debug_type_s *tag; | 
|  | /* DEBUG_OBJECT_VARIABLE.  */ | 
|  | struct debug_variable *variable; | 
|  | /* DEBUG_OBJECT_FUNCTION.  */ | 
|  | struct debug_function *function; | 
|  | /* DEBUG_OBJECT_INT_CONSTANT.  */ | 
|  | bfd_vma int_constant; | 
|  | /* DEBUG_OBJECT_FLOAT_CONSTANT.  */ | 
|  | double float_constant; | 
|  | /* DEBUG_OBJECT_TYPED_CONSTANT.  */ | 
|  | struct debug_typed_constant *typed_constant; | 
|  | } u; | 
|  | }; | 
|  |  | 
|  | /* During debug_write, a linked list of these structures is used to | 
|  | keep track of ID numbers that have been assigned to classes.  */ | 
|  |  | 
|  | struct debug_class_id | 
|  | { | 
|  | /* Next ID number.  */ | 
|  | struct debug_class_id *next; | 
|  | /* The type with the ID.  */ | 
|  | struct debug_type_s *type; | 
|  | /* The tag; NULL if no tag.  */ | 
|  | const char *tag; | 
|  | }; | 
|  |  | 
|  | /* During debug_type_samep, a linked list of these structures is kept | 
|  | on the stack to avoid infinite recursion.  */ | 
|  |  | 
|  | struct debug_type_compare_list | 
|  | { | 
|  | /* Next type on list.  */ | 
|  | struct debug_type_compare_list *next; | 
|  | /* The types we are comparing.  */ | 
|  | struct debug_type_s *t1; | 
|  | struct debug_type_s *t2; | 
|  | }; | 
|  |  | 
|  | /* During debug_get_real_type, a linked list of these structures is | 
|  | kept on the stack to avoid infinite recursion.  */ | 
|  |  | 
|  | struct debug_type_real_list | 
|  | { | 
|  | /* Next type on list.  */ | 
|  | struct debug_type_real_list *next; | 
|  | /* The type we are checking.  */ | 
|  | struct debug_type_s *t; | 
|  | }; | 
|  |  | 
|  | /* Local functions.  */ | 
|  |  | 
|  | static void debug_error (const char *); | 
|  | static struct debug_name *debug_add_to_namespace | 
|  | (struct debug_handle *, struct debug_namespace **, const char *, | 
|  | enum debug_object_kind, enum debug_object_linkage); | 
|  | static struct debug_name *debug_add_to_current_namespace | 
|  | (struct debug_handle *, const char *, enum debug_object_kind, | 
|  | enum debug_object_linkage); | 
|  | static struct debug_type_s *debug_make_type | 
|  | (struct debug_handle *, enum debug_type_kind, unsigned int); | 
|  | static struct debug_type_s *debug_get_real_type | 
|  | (void *, debug_type, struct debug_type_real_list *); | 
|  | static bool debug_write_name | 
|  | (struct debug_handle *, const struct debug_write_fns *, void *, | 
|  | struct debug_name *); | 
|  | static bool debug_write_type | 
|  | (struct debug_handle *, const struct debug_write_fns *, void *, | 
|  | struct debug_type_s *, struct debug_name *); | 
|  | static bool debug_write_class_type | 
|  | (struct debug_handle *, const struct debug_write_fns *, void *, | 
|  | struct debug_type_s *, const char *); | 
|  | static bool debug_write_function | 
|  | (struct debug_handle *, const struct debug_write_fns *, void *, | 
|  | const char *, enum debug_object_linkage, struct debug_function *); | 
|  | static bool debug_write_block | 
|  | (struct debug_handle *, const struct debug_write_fns *, void *, | 
|  | struct debug_block *); | 
|  | static bool debug_write_linenos | 
|  | (struct debug_handle *, const struct debug_write_fns *, void *, bfd_vma); | 
|  | static bool debug_set_class_id | 
|  | (struct debug_handle *, const char *, struct debug_type_s *); | 
|  | static bool debug_type_samep | 
|  | (struct debug_handle *, struct debug_type_s *, struct debug_type_s *); | 
|  | static bool debug_class_type_samep | 
|  | (struct debug_handle *, struct debug_type_s *, struct debug_type_s *); | 
|  |  | 
|  | /* Issue an error message.  */ | 
|  |  | 
|  | static void | 
|  | debug_error (const char *message) | 
|  | { | 
|  | fprintf (stderr, "%s\n", message); | 
|  | } | 
|  |  | 
|  | /* Add an object to a namespace.  */ | 
|  |  | 
|  | static struct debug_name * | 
|  | debug_add_to_namespace (struct debug_handle *info, | 
|  | struct debug_namespace **nsp, const char *name, | 
|  | enum debug_object_kind kind, | 
|  | enum debug_object_linkage linkage) | 
|  | { | 
|  | struct debug_name *n; | 
|  | struct debug_namespace *ns; | 
|  |  | 
|  | n = debug_xzalloc (info, sizeof (*n)); | 
|  |  | 
|  | n->name = name; | 
|  | n->kind = kind; | 
|  | n->linkage = linkage; | 
|  |  | 
|  | ns = *nsp; | 
|  | if (ns == NULL) | 
|  | { | 
|  | ns = debug_xzalloc (info, sizeof (*ns)); | 
|  |  | 
|  | ns->tail = &ns->list; | 
|  |  | 
|  | *nsp = ns; | 
|  | } | 
|  |  | 
|  | *ns->tail = n; | 
|  | ns->tail = &n->next; | 
|  |  | 
|  | return n; | 
|  | } | 
|  |  | 
|  | /* Add an object to the current namespace.  */ | 
|  |  | 
|  | static struct debug_name * | 
|  | debug_add_to_current_namespace (struct debug_handle *info, const char *name, | 
|  | enum debug_object_kind kind, | 
|  | enum debug_object_linkage linkage) | 
|  | { | 
|  | struct debug_namespace **nsp; | 
|  |  | 
|  | if (info->current_unit == NULL | 
|  | || info->current_file == NULL) | 
|  | { | 
|  | debug_error (_("debug_add_to_current_namespace: no current file")); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if (info->current_block != NULL) | 
|  | nsp = &info->current_block->locals; | 
|  | else | 
|  | nsp = &info->current_file->globals; | 
|  |  | 
|  | return debug_add_to_namespace (info, nsp, name, kind, linkage); | 
|  | } | 
|  |  | 
|  | /* Return a handle for debugging information.  */ | 
|  |  | 
|  | void * | 
|  | debug_init (bfd *abfd) | 
|  | { | 
|  | struct debug_handle *ret; | 
|  |  | 
|  | ret = bfd_xalloc (abfd, sizeof (*ret)); | 
|  | memset (ret, 0, sizeof (*ret)); | 
|  | ret->abfd = abfd; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | void * | 
|  | debug_xalloc (void *handle, size_t size) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | return bfd_xalloc (info->abfd, size); | 
|  | } | 
|  |  | 
|  | void * | 
|  | debug_xzalloc (void *handle, size_t size) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | void *mem = bfd_xalloc (info->abfd, size); | 
|  | memset (mem, 0, size); | 
|  | return mem; | 
|  | } | 
|  |  | 
|  | /* Set the source filename.  This implicitly starts a new compilation | 
|  | unit.  */ | 
|  |  | 
|  | bool | 
|  | debug_set_filename (void *handle, const char *name) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_file *nfile; | 
|  | struct debug_unit *nunit; | 
|  |  | 
|  | if (name == NULL) | 
|  | name = ""; | 
|  |  | 
|  | nfile = debug_xzalloc (info, sizeof (*nfile)); | 
|  |  | 
|  | nfile->filename = name; | 
|  |  | 
|  | nunit = debug_xzalloc (info, sizeof (*nunit)); | 
|  |  | 
|  | nunit->files = nfile; | 
|  | info->current_file = nfile; | 
|  |  | 
|  | if (info->current_unit != NULL) | 
|  | info->current_unit->next = nunit; | 
|  | else | 
|  | { | 
|  | assert (info->units == NULL); | 
|  | info->units = nunit; | 
|  | } | 
|  |  | 
|  | info->current_unit = nunit; | 
|  |  | 
|  | info->current_function = NULL; | 
|  | info->current_block = NULL; | 
|  | info->current_lineno = NULL; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Change source files to the given file name.  This is used for | 
|  | include files in a single compilation unit.  */ | 
|  |  | 
|  | bool | 
|  | debug_start_source (void *handle, const char *name) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_file *f, **pf; | 
|  |  | 
|  | if (name == NULL) | 
|  | name = ""; | 
|  |  | 
|  | if (info->current_unit == NULL) | 
|  | { | 
|  | debug_error (_("debug_start_source: no debug_set_filename call")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | for (f = info->current_unit->files; f != NULL; f = f->next) | 
|  | { | 
|  | if (filename_cmp (f->filename, name) == 0) | 
|  | { | 
|  | info->current_file = f; | 
|  | return true; | 
|  | } | 
|  | } | 
|  |  | 
|  | f = debug_xzalloc (info, sizeof (*f)); | 
|  | f->filename = name; | 
|  |  | 
|  | for (pf = &info->current_file->next; | 
|  | *pf != NULL; | 
|  | pf = &(*pf)->next) | 
|  | ; | 
|  | *pf = f; | 
|  |  | 
|  | info->current_file = f; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Record a function definition.  This implicitly starts a function | 
|  | block.  The debug_type argument is the type of the return value. | 
|  | The boolean indicates whether the function is globally visible. | 
|  | The bfd_vma is the address of the start of the function.  Currently | 
|  | the parameter types are specified by calls to | 
|  | debug_record_parameter.  FIXME: There is no way to specify nested | 
|  | functions.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_function (void *handle, const char *name, | 
|  | debug_type return_type, bool global, | 
|  | bfd_vma addr) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_function *f; | 
|  | struct debug_block *b; | 
|  | struct debug_name *n; | 
|  |  | 
|  | if (name == NULL) | 
|  | name = ""; | 
|  | if (return_type == NULL) | 
|  | return false; | 
|  |  | 
|  | if (info->current_unit == NULL) | 
|  | { | 
|  | debug_error (_("debug_record_function: no debug_set_filename call")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | f = debug_xzalloc (info, sizeof (*f)); | 
|  |  | 
|  | f->return_type = return_type; | 
|  |  | 
|  | b = debug_xzalloc (info, sizeof (*b)); | 
|  |  | 
|  | b->start = addr; | 
|  | b->end = (bfd_vma) -1; | 
|  |  | 
|  | f->blocks = b; | 
|  |  | 
|  | info->current_function = f; | 
|  | info->current_block = b; | 
|  |  | 
|  | /* FIXME: If we could handle nested functions, this would be the | 
|  | place: we would want to use a different namespace.  */ | 
|  | n = debug_add_to_namespace (info, | 
|  | &info->current_file->globals, | 
|  | name, | 
|  | DEBUG_OBJECT_FUNCTION, | 
|  | (global | 
|  | ? DEBUG_LINKAGE_GLOBAL | 
|  | : DEBUG_LINKAGE_STATIC)); | 
|  | if (n == NULL) | 
|  | return false; | 
|  |  | 
|  | n->u.function = f; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Record a parameter for the current function.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_parameter (void *handle, const char *name, debug_type type, | 
|  | enum debug_parm_kind kind, bfd_vma val) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_parameter *p, **pp; | 
|  |  | 
|  | if (name == NULL || type == NULL) | 
|  | return false; | 
|  |  | 
|  | if (info->current_unit == NULL | 
|  | || info->current_function == NULL) | 
|  | { | 
|  | debug_error (_("debug_record_parameter: no current function")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | p = debug_xzalloc (info, sizeof (*p)); | 
|  |  | 
|  | p->name = name; | 
|  | p->type = type; | 
|  | p->kind = kind; | 
|  | p->val = val; | 
|  |  | 
|  | for (pp = &info->current_function->parameters; | 
|  | *pp != NULL; | 
|  | pp = &(*pp)->next) | 
|  | ; | 
|  | *pp = p; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* End a function.  FIXME: This should handle function nesting.  */ | 
|  |  | 
|  | bool | 
|  | debug_end_function (void *handle, bfd_vma addr) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  |  | 
|  | if (info->current_unit == NULL | 
|  | || info->current_block == NULL | 
|  | || info->current_function == NULL) | 
|  | { | 
|  | debug_error (_("debug_end_function: no current function")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (info->current_block->parent != NULL) | 
|  | { | 
|  | debug_error (_("debug_end_function: some blocks were not closed")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | info->current_block->end = addr; | 
|  |  | 
|  | info->current_function = NULL; | 
|  | info->current_block = NULL; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Start a block in a function.  All local information will be | 
|  | recorded in this block, until the matching call to debug_end_block. | 
|  | debug_start_block and debug_end_block may be nested.  The bfd_vma | 
|  | argument is the address at which this block starts.  */ | 
|  |  | 
|  | bool | 
|  | debug_start_block (void *handle, bfd_vma addr) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_block *b, **pb; | 
|  |  | 
|  | /* We must always have a current block: debug_record_function sets | 
|  | one up.  */ | 
|  | if (info->current_unit == NULL | 
|  | || info->current_block == NULL) | 
|  | { | 
|  | debug_error (_("debug_start_block: no current block")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | b = debug_xzalloc (info, sizeof (*b)); | 
|  |  | 
|  | b->parent = info->current_block; | 
|  | b->start = addr; | 
|  | b->end = (bfd_vma) -1; | 
|  |  | 
|  | /* This new block is a child of the current block.  */ | 
|  | for (pb = &info->current_block->children; | 
|  | *pb != NULL; | 
|  | pb = &(*pb)->next) | 
|  | ; | 
|  | *pb = b; | 
|  |  | 
|  | info->current_block = b; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Finish a block in a function.  This matches the call to | 
|  | debug_start_block.  The argument is the address at which this block | 
|  | ends.  */ | 
|  |  | 
|  | bool | 
|  | debug_end_block (void *handle, bfd_vma addr) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_block *parent; | 
|  |  | 
|  | if (info->current_unit == NULL | 
|  | || info->current_block == NULL) | 
|  | { | 
|  | debug_error (_("debug_end_block: no current block")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | parent = info->current_block->parent; | 
|  | if (parent == NULL) | 
|  | { | 
|  | debug_error (_("debug_end_block: attempt to close top level block")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | info->current_block->end = addr; | 
|  |  | 
|  | info->current_block = parent; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Associate a line number in the current source file and function | 
|  | with a given address.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_line (void *handle, unsigned long lineno, bfd_vma addr) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_lineno *l; | 
|  | unsigned int i; | 
|  |  | 
|  | if (info->current_unit == NULL) | 
|  | { | 
|  | debug_error (_("debug_record_line: no current unit")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | l = info->current_lineno; | 
|  | if (l != NULL && l->file == info->current_file) | 
|  | { | 
|  | for (i = 0; i < DEBUG_LINENO_COUNT; i++) | 
|  | { | 
|  | if (l->linenos[i] == (unsigned long) -1) | 
|  | { | 
|  | l->linenos[i] = lineno; | 
|  | l->addrs[i] = addr; | 
|  | return true; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* If we get here, then either 1) there is no current_lineno | 
|  | 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 = debug_xzalloc (info, sizeof (*l)); | 
|  |  | 
|  | l->file = info->current_file; | 
|  | l->linenos[0] = lineno; | 
|  | l->addrs[0] = addr; | 
|  | for (i = 1; i < DEBUG_LINENO_COUNT; i++) | 
|  | l->linenos[i] = (unsigned long) -1; | 
|  |  | 
|  | if (info->current_lineno != NULL) | 
|  | info->current_lineno->next = l; | 
|  | else | 
|  | info->current_unit->linenos = l; | 
|  |  | 
|  | info->current_lineno = l; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Start a named common block.  This is a block of variables that may | 
|  | move in memory.  */ | 
|  |  | 
|  | bool | 
|  | debug_start_common_block (void *handle ATTRIBUTE_UNUSED, | 
|  | const char *name ATTRIBUTE_UNUSED) | 
|  | { | 
|  | /* FIXME */ | 
|  | debug_error (_("debug_start_common_block: not implemented")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* End a named common block.  */ | 
|  |  | 
|  | bool | 
|  | debug_end_common_block (void *handle ATTRIBUTE_UNUSED, | 
|  | const char *name ATTRIBUTE_UNUSED) | 
|  | { | 
|  | /* FIXME */ | 
|  | debug_error (_("debug_end_common_block: not implemented")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Record a named integer constant.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_int_const (void *handle, const char *name, bfd_vma val) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_name *n; | 
|  |  | 
|  | if (name == NULL) | 
|  | return false; | 
|  |  | 
|  | n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_INT_CONSTANT, | 
|  | DEBUG_LINKAGE_NONE); | 
|  | if (n == NULL) | 
|  | return false; | 
|  |  | 
|  | n->u.int_constant = val; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Record a named floating point constant.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_float_const (void *handle, const char *name, double val) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_name *n; | 
|  |  | 
|  | if (name == NULL) | 
|  | return false; | 
|  |  | 
|  | n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_FLOAT_CONSTANT, | 
|  | DEBUG_LINKAGE_NONE); | 
|  | if (n == NULL) | 
|  | return false; | 
|  |  | 
|  | n->u.float_constant = val; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Record a typed constant with an integral value.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_typed_const (void *handle, const char *name, debug_type type, | 
|  | bfd_vma val) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_name *n; | 
|  | struct debug_typed_constant *tc; | 
|  |  | 
|  | if (name == NULL || type == NULL) | 
|  | return false; | 
|  |  | 
|  | n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPED_CONSTANT, | 
|  | DEBUG_LINKAGE_NONE); | 
|  | if (n == NULL) | 
|  | return false; | 
|  |  | 
|  | tc = debug_xzalloc (info, sizeof (*tc)); | 
|  |  | 
|  | tc->type = type; | 
|  | tc->val = val; | 
|  |  | 
|  | n->u.typed_constant = tc; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Record a label.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_label (void *handle ATTRIBUTE_UNUSED, | 
|  | const char *name ATTRIBUTE_UNUSED, | 
|  | debug_type type ATTRIBUTE_UNUSED, | 
|  | bfd_vma addr ATTRIBUTE_UNUSED) | 
|  | { | 
|  | /* FIXME.  */ | 
|  | debug_error (_("debug_record_label: not implemented")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Record a variable.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_variable (void *handle, const char *name, debug_type type, | 
|  | enum debug_var_kind kind, bfd_vma val) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_namespace **nsp; | 
|  | enum debug_object_linkage linkage; | 
|  | struct debug_name *n; | 
|  | struct debug_variable *v; | 
|  |  | 
|  | if (name == NULL || type == NULL) | 
|  | return false; | 
|  |  | 
|  | if (info->current_unit == NULL | 
|  | || info->current_file == NULL) | 
|  | { | 
|  | debug_error (_("debug_record_variable: no current file")); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (kind == DEBUG_GLOBAL || kind == DEBUG_STATIC) | 
|  | { | 
|  | nsp = &info->current_file->globals; | 
|  | if (kind == DEBUG_GLOBAL) | 
|  | linkage = DEBUG_LINKAGE_GLOBAL; | 
|  | else | 
|  | linkage = DEBUG_LINKAGE_STATIC; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (info->current_block == NULL) | 
|  | nsp = &info->current_file->globals; | 
|  | else | 
|  | nsp = &info->current_block->locals; | 
|  | linkage = DEBUG_LINKAGE_AUTOMATIC; | 
|  | } | 
|  |  | 
|  | n = debug_add_to_namespace (info, nsp, name, DEBUG_OBJECT_VARIABLE, linkage); | 
|  | if (n == NULL) | 
|  | return false; | 
|  |  | 
|  | v = debug_xzalloc (info, sizeof (*v)); | 
|  |  | 
|  | v->kind = kind; | 
|  | v->type = type; | 
|  | v->val = val; | 
|  |  | 
|  | n->u.variable = v; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Make a type with a given kind and size.  */ | 
|  |  | 
|  | static struct debug_type_s * | 
|  | debug_make_type (struct debug_handle *info, | 
|  | enum debug_type_kind kind, unsigned int size) | 
|  | { | 
|  | struct debug_type_s *t; | 
|  |  | 
|  | t = debug_xzalloc (info, sizeof (*t)); | 
|  |  | 
|  | t->kind = kind; | 
|  | t->size = size; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make an indirect type which may be used as a placeholder for a type | 
|  | which is referenced before it is defined.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_indirect_type (void *handle, debug_type *slot, const char *tag) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_indirect_type *i; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_INDIRECT, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | i = debug_xzalloc (info, sizeof (*i)); | 
|  |  | 
|  | i->slot = slot; | 
|  | i->tag = tag; | 
|  |  | 
|  | t->u.kindirect = i; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a void type.  There is only one of these.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_void_type (void *handle) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  |  | 
|  | return debug_make_type (info, DEBUG_KIND_VOID, 0); | 
|  | } | 
|  |  | 
|  | /* Make an integer type of a given size.  The boolean argument is true | 
|  | if the integer is unsigned.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_int_type (void *handle, unsigned int size, bool unsignedp) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_INT, size); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t->u.kint = unsignedp; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a floating point type of a given size.  FIXME: On some | 
|  | platforms, like an Alpha, you probably need to be able to specify | 
|  | the format.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_float_type (void *handle, unsigned int size) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  |  | 
|  | return debug_make_type (info, DEBUG_KIND_FLOAT, size); | 
|  | } | 
|  |  | 
|  | /* Make a boolean type of a given size.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_bool_type (void *handle, unsigned int size) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  |  | 
|  | return debug_make_type (info, DEBUG_KIND_BOOL, size); | 
|  | } | 
|  |  | 
|  | /* Make a complex type of a given size.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_complex_type (void *handle, unsigned int size) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  |  | 
|  | return debug_make_type (info, DEBUG_KIND_COMPLEX, size); | 
|  | } | 
|  |  | 
|  | /* Make a structure type.  The second argument is true for a struct, | 
|  | false for a union.  The third argument is the size of the struct. | 
|  | The fourth argument is a NULL terminated array of fields.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_struct_type (void *handle, bool structp, bfd_vma size, | 
|  | debug_field *fields) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_class_type *c; | 
|  |  | 
|  | t = debug_make_type (info, | 
|  | structp ? DEBUG_KIND_STRUCT : DEBUG_KIND_UNION, | 
|  | size); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | c = debug_xzalloc (info, sizeof (*c)); | 
|  |  | 
|  | c->fields = fields; | 
|  |  | 
|  | t->u.kclass = c; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make an object type.  The first three arguments after the handle | 
|  | are the same as for debug_make_struct_type.  The next arguments are | 
|  | a NULL terminated array of base classes, a NULL terminated array of | 
|  | methods, the type of the object holding the virtual function table | 
|  | if it is not this object, and a boolean which is true if this | 
|  | object has its own virtual function table.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_object_type (void *handle, bool structp, bfd_vma size, | 
|  | debug_field *fields, debug_baseclass *baseclasses, | 
|  | debug_method *methods, debug_type vptrbase, | 
|  | bool ownvptr) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_class_type *c; | 
|  |  | 
|  | t = debug_make_type (info, | 
|  | structp ? DEBUG_KIND_CLASS : DEBUG_KIND_UNION_CLASS, | 
|  | size); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | c = debug_xzalloc (info, sizeof (*c)); | 
|  |  | 
|  | c->fields = fields; | 
|  | c->baseclasses = baseclasses; | 
|  | c->methods = methods; | 
|  | if (ownvptr) | 
|  | c->vptrbase = t; | 
|  | else | 
|  | c->vptrbase = vptrbase; | 
|  |  | 
|  | t->u.kclass = c; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make an enumeration type.  The arguments are a null terminated | 
|  | array of strings, and an array of corresponding values.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_enum_type (void *handle, const char **names, | 
|  | bfd_signed_vma *values) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_enum_type *e; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_ENUM, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | e = debug_xzalloc (info, sizeof (*e)); | 
|  |  | 
|  | e->names = names; | 
|  | e->values = values; | 
|  |  | 
|  | t->u.kenum = e; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a pointer to a given type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_pointer_type (void *handle, debug_type type) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  |  | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | if (type->pointer != DEBUG_TYPE_NULL) | 
|  | return type->pointer; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_POINTER, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t->u.kpointer = type; | 
|  |  | 
|  | type->pointer = t; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a function returning a given type.  FIXME: We should be able | 
|  | to record the parameter types.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_function_type (void *handle, debug_type type, | 
|  | debug_type *arg_types, bool varargs) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_function_type *f; | 
|  |  | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_FUNCTION, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | f = debug_xzalloc (info, sizeof (*f)); | 
|  |  | 
|  | f->return_type = type; | 
|  | f->arg_types = arg_types; | 
|  | f->varargs = varargs; | 
|  |  | 
|  | t->u.kfunction = f; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a reference to a given type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_reference_type (void *handle, debug_type type) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  |  | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_REFERENCE, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t->u.kreference = type; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a range of a given type from a lower to an upper bound.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_range_type (void *handle, debug_type type, bfd_signed_vma lower, | 
|  | bfd_signed_vma upper) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_range_type *r; | 
|  |  | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_RANGE, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | r = debug_xzalloc (info, sizeof (*r)); | 
|  |  | 
|  | r->type = type; | 
|  | r->lower = lower; | 
|  | r->upper = upper; | 
|  |  | 
|  | t->u.krange = r; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make an array type.  The second argument is the type of an element | 
|  | of the array.  The third argument is the type of a range of the | 
|  | array.  The fourth and fifth argument are the lower and upper | 
|  | bounds, respectively.  The sixth argument is true if this array is | 
|  | actually a string, as in C.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_array_type (void *handle, debug_type element_type, | 
|  | debug_type range_type, bfd_signed_vma lower, | 
|  | bfd_signed_vma upper, bool stringp) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_array_type *a; | 
|  |  | 
|  | if (element_type == NULL || range_type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_ARRAY, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | a = debug_xzalloc (info, sizeof (*a)); | 
|  |  | 
|  | a->element_type = element_type; | 
|  | a->range_type = range_type; | 
|  | a->lower = lower; | 
|  | a->upper = upper; | 
|  | a->stringp = stringp; | 
|  |  | 
|  | t->u.karray = a; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a set of a given type.  For example, a Pascal set type.  The | 
|  | boolean argument is true if this set is actually a bitstring, as in | 
|  | CHILL.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_set_type (void *handle, debug_type type, bool bitstringp) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_set_type *s; | 
|  |  | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_SET, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | s = debug_xzalloc (info, sizeof (*s)); | 
|  |  | 
|  | s->type = type; | 
|  | s->bitstringp = bitstringp; | 
|  |  | 
|  | t->u.kset = s; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a type for a pointer which is relative to an object.  The | 
|  | second argument is the type of the object to which the pointer is | 
|  | relative.  The third argument is the type that the pointer points | 
|  | to.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_offset_type (void *handle, debug_type base_type, | 
|  | debug_type target_type) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_offset_type *o; | 
|  |  | 
|  | if (base_type == NULL || target_type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_OFFSET, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | o = debug_xzalloc (info, sizeof (*o)); | 
|  |  | 
|  | o->base_type = base_type; | 
|  | o->target_type = target_type; | 
|  |  | 
|  | t->u.koffset = o; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a type for a method function.  The second argument is the | 
|  | return type, the third argument is the domain, and the fourth | 
|  | argument is a NULL terminated array of argument types.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_method_type (void *handle, debug_type return_type, | 
|  | debug_type domain_type, debug_type *arg_types, | 
|  | bool varargs) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_method_type *m; | 
|  |  | 
|  | if (return_type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_METHOD, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | m = debug_xzalloc (info, sizeof (*m)); | 
|  |  | 
|  | m->return_type = return_type; | 
|  | m->domain_type = domain_type; | 
|  | m->arg_types = arg_types; | 
|  | m->varargs = varargs; | 
|  |  | 
|  | t->u.kmethod = m; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a const qualified version of a given type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_const_type (void *handle, debug_type type) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  |  | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_CONST, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t->u.kconst = type; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make a volatile qualified version of a given type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_volatile_type (void *handle, debug_type type) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  |  | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_VOLATILE, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | t->u.kvolatile = type; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Make an undefined tagged type.  For example, a struct which has | 
|  | been mentioned, but not defined.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_make_undefined_tagged_type (void *handle, const char *name, | 
|  | enum debug_type_kind kind) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  |  | 
|  | if (name == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | switch (kind) | 
|  | { | 
|  | case DEBUG_KIND_STRUCT: | 
|  | case DEBUG_KIND_UNION: | 
|  | case DEBUG_KIND_CLASS: | 
|  | case DEBUG_KIND_UNION_CLASS: | 
|  | case DEBUG_KIND_ENUM: | 
|  | break; | 
|  |  | 
|  | default: | 
|  | debug_error (_("debug_make_undefined_type: unsupported kind")); | 
|  | return DEBUG_TYPE_NULL; | 
|  | } | 
|  |  | 
|  | t = debug_make_type (info, kind, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | return debug_tag_type (handle, name, t); | 
|  | } | 
|  |  | 
|  | /* Make a base class for an object.  The second argument is the base | 
|  | class type.  The third argument is the bit position of this base | 
|  | class in the object (always 0 unless doing multiple inheritance). | 
|  | The fourth argument is whether this is a virtual class.  The fifth | 
|  | argument is the visibility of the base class.  */ | 
|  |  | 
|  | debug_baseclass | 
|  | debug_make_baseclass (void *handle, debug_type type, | 
|  | bfd_vma bitpos, bool is_virtual, | 
|  | enum debug_visibility visibility) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_baseclass_s *b; | 
|  |  | 
|  | b = debug_xzalloc (info, sizeof (*b)); | 
|  |  | 
|  | b->type = type; | 
|  | b->bitpos = bitpos; | 
|  | b->is_virtual = is_virtual; | 
|  | b->visibility = visibility; | 
|  |  | 
|  | return b; | 
|  | } | 
|  |  | 
|  | /* Make a field for a struct.  The second argument is the name.  The | 
|  | third argument is the type of the field.  The fourth argument is | 
|  | the bit position of the field.  The fifth argument is the size of | 
|  | the field (it may be zero).  The sixth argument is the visibility | 
|  | of the field.  */ | 
|  |  | 
|  | debug_field | 
|  | debug_make_field (void *handle, const char *name, | 
|  | debug_type type, bfd_vma bitpos, bfd_vma bitsize, | 
|  | enum debug_visibility visibility) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_field_s *f; | 
|  |  | 
|  | f = debug_xzalloc (info, sizeof (*f)); | 
|  |  | 
|  | f->name = name; | 
|  | f->type = type; | 
|  | f->static_member = false; | 
|  | f->u.f.bitpos = bitpos; | 
|  | f->u.f.bitsize = bitsize; | 
|  | f->visibility = visibility; | 
|  |  | 
|  | return f; | 
|  | } | 
|  |  | 
|  | /* Make a static member of an object.  The second argument is the | 
|  | name.  The third argument is the type of the member.  The fourth | 
|  | argument is the physical name of the member (i.e., the name as a | 
|  | global variable).  The fifth argument is the visibility of the | 
|  | member.  */ | 
|  |  | 
|  | debug_field | 
|  | debug_make_static_member (void *handle, const char *name, | 
|  | debug_type type, const char *physname, | 
|  | enum debug_visibility visibility) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_field_s *f; | 
|  |  | 
|  | f = debug_xzalloc (info, sizeof (*f)); | 
|  |  | 
|  | f->name = name; | 
|  | f->type = type; | 
|  | f->static_member = true; | 
|  | f->u.s.physname = physname; | 
|  | f->visibility = visibility; | 
|  |  | 
|  | return f; | 
|  | } | 
|  |  | 
|  | /* Make a method.  The second argument is the name, and the third | 
|  | argument is a NULL terminated array of method variants.  */ | 
|  |  | 
|  | debug_method | 
|  | debug_make_method (void *handle, const char *name, | 
|  | debug_method_variant *variants) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_method_s *m; | 
|  |  | 
|  | m = debug_xzalloc (info, sizeof (*m)); | 
|  |  | 
|  | m->name = name; | 
|  | m->variants = variants; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /* Make a method argument.  The second argument is the real name of | 
|  | the function.  The third argument is the type of the function.  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 function table, if any.  The eighth argument is the virtual | 
|  | function context.  FIXME: Are the const and volatile arguments | 
|  | necessary?  Could we just use debug_make_const_type?  */ | 
|  |  | 
|  | debug_method_variant | 
|  | debug_make_method_variant (void *handle, | 
|  | const char *physname, debug_type type, | 
|  | enum debug_visibility visibility, | 
|  | bool constp, bool volatilep, | 
|  | bfd_vma voffset, debug_type context) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_method_variant_s *m; | 
|  |  | 
|  | m = debug_xzalloc (info, sizeof (*m)); | 
|  |  | 
|  | m->physname = physname; | 
|  | m->type = type; | 
|  | m->visibility = visibility; | 
|  | m->constp = constp; | 
|  | m->volatilep = volatilep; | 
|  | m->voffset = voffset; | 
|  | m->context = context; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /* Make a static method argument.  The arguments are the same as for | 
|  | debug_make_method_variant, except that the last two are omitted | 
|  | since a static method can not also be virtual.  */ | 
|  |  | 
|  | debug_method_variant | 
|  | debug_make_static_method_variant (void *handle, | 
|  | const char *physname, debug_type type, | 
|  | enum debug_visibility visibility, | 
|  | bool constp, bool volatilep) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_method_variant_s *m; | 
|  |  | 
|  | m = debug_xzalloc (info, sizeof (*m)); | 
|  |  | 
|  | m->physname = physname; | 
|  | m->type = type; | 
|  | m->visibility = visibility; | 
|  | m->constp = constp; | 
|  | m->volatilep = volatilep; | 
|  | m->voffset = VOFFSET_STATIC_METHOD; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /* Name a type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_name_type (void *handle, const char *name, debug_type type) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_named_type *n; | 
|  | struct debug_name *nm; | 
|  |  | 
|  | if (name == NULL || type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | if (info->current_unit == NULL | 
|  | || info->current_file == NULL) | 
|  | { | 
|  | debug_error (_("debug_name_type: no current file")); | 
|  | return DEBUG_TYPE_NULL; | 
|  | } | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_NAMED, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | n = debug_xzalloc (info, sizeof (*n)); | 
|  |  | 
|  | n->type = type; | 
|  |  | 
|  | t->u.knamed = n; | 
|  |  | 
|  | /* 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_namespace (info, &info->current_file->globals, name, | 
|  | DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE); | 
|  | if (nm == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | nm->u.type = t; | 
|  |  | 
|  | n->name = nm; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Tag a type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_tag_type (void *handle, const char *name, debug_type type) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_type_s *t; | 
|  | struct debug_named_type *n; | 
|  | struct debug_name *nm; | 
|  |  | 
|  | if (name == NULL || type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | if (info->current_file == NULL) | 
|  | { | 
|  | debug_error (_("debug_tag_type: no current file")); | 
|  | return DEBUG_TYPE_NULL; | 
|  | } | 
|  |  | 
|  | if (type->kind == DEBUG_KIND_TAGGED) | 
|  | { | 
|  | if (strcmp (type->u.knamed->name->name, name) == 0) | 
|  | return type; | 
|  | debug_error (_("debug_tag_type: extra tag attempted")); | 
|  | return DEBUG_TYPE_NULL; | 
|  | } | 
|  |  | 
|  | t = debug_make_type (info, DEBUG_KIND_TAGGED, 0); | 
|  | if (t == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | n = debug_xzalloc (info, sizeof (*n)); | 
|  |  | 
|  | n->type = type; | 
|  |  | 
|  | t->u.knamed = n; | 
|  |  | 
|  | /* We keep a global namespace of tags for each compilation unit.  I | 
|  | don't know if that is the right thing to do.  */ | 
|  |  | 
|  | nm = debug_add_to_namespace (info, &info->current_file->globals, name, | 
|  | DEBUG_OBJECT_TAG, DEBUG_LINKAGE_NONE); | 
|  | if (nm == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | nm->u.tag = t; | 
|  |  | 
|  | n->name = nm; | 
|  |  | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Record the size of a given type.  */ | 
|  |  | 
|  | bool | 
|  | debug_record_type_size (void *handle ATTRIBUTE_UNUSED, debug_type type, | 
|  | unsigned int size) | 
|  | { | 
|  | if (type->size != 0 && type->size != size) | 
|  | fprintf (stderr, _("Warning: changing type size from %d to %d\n"), | 
|  | type->size, size); | 
|  |  | 
|  | type->size = size; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Find a named type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_find_named_type (void *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 | 
|  | debug_find_tagged_type (void *handle, const char *name, | 
|  | enum debug_type_kind kind) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_unit *u; | 
|  |  | 
|  | /* We search the globals of all the compilation units.  I don't know | 
|  | if this is correct or not.  It would be easy to change.  */ | 
|  |  | 
|  | for (u = info->units; u != NULL; u = u->next) | 
|  | { | 
|  | struct debug_file *f; | 
|  |  | 
|  | for (f = u->files; f != NULL; f = f->next) | 
|  | { | 
|  | struct debug_name *n; | 
|  |  | 
|  | if (f->globals != NULL) | 
|  | { | 
|  | for (n = f->globals->list; n != NULL; n = n->next) | 
|  | { | 
|  | if (n->kind == DEBUG_OBJECT_TAG | 
|  | && (kind == DEBUG_KIND_ILLEGAL | 
|  | || n->u.tag->kind == kind) | 
|  | && n->name[0] == name[0] | 
|  | && strcmp (n->name, name) == 0) | 
|  | return n->u.tag; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return DEBUG_TYPE_NULL; | 
|  | } | 
|  |  | 
|  | /* Get a base type.  We build a linked list on the stack to avoid | 
|  | crashing if the type is defined circularly.  */ | 
|  |  | 
|  | static struct debug_type_s * | 
|  | debug_get_real_type (void *handle, debug_type type, | 
|  | struct debug_type_real_list *list) | 
|  | { | 
|  | struct debug_type_real_list *l; | 
|  | struct debug_type_real_list rl; | 
|  |  | 
|  | switch (type->kind) | 
|  | { | 
|  | default: | 
|  | return type; | 
|  |  | 
|  | case DEBUG_KIND_INDIRECT: | 
|  | case DEBUG_KIND_NAMED: | 
|  | case DEBUG_KIND_TAGGED: | 
|  | break; | 
|  | } | 
|  |  | 
|  | for (l = list; l != NULL; l = l->next) | 
|  | { | 
|  | if (l->t == type || l == l->next) | 
|  | { | 
|  | fprintf (stderr, | 
|  | _("debug_get_real_type: circular debug information for %s\n"), | 
|  | debug_get_type_name (handle, type)); | 
|  | return NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | rl.next = list; | 
|  | rl.t = type; | 
|  |  | 
|  | switch (type->kind) | 
|  | { | 
|  | /* The default case is just here to avoid warnings.  */ | 
|  | default: | 
|  | case DEBUG_KIND_INDIRECT: | 
|  | /* A valid non-self-referencing indirect type.  */ | 
|  | if (*type->u.kindirect->slot != NULL | 
|  | && *type->u.kindirect->slot != type) | 
|  | return debug_get_real_type (handle, *type->u.kindirect->slot, &rl); | 
|  | return type; | 
|  | case DEBUG_KIND_NAMED: | 
|  | case DEBUG_KIND_TAGGED: | 
|  | return debug_get_real_type (handle, type->u.knamed->type, &rl); | 
|  | } | 
|  | /*NOTREACHED*/ | 
|  | } | 
|  |  | 
|  | /* Get the kind of a type.  */ | 
|  |  | 
|  | enum debug_type_kind | 
|  | debug_get_type_kind (void *handle, debug_type type) | 
|  | { | 
|  | if (type == NULL) | 
|  | return DEBUG_KIND_ILLEGAL; | 
|  | type = debug_get_real_type (handle, type, NULL); | 
|  | if (type == NULL) | 
|  | return DEBUG_KIND_ILLEGAL; | 
|  | return type->kind; | 
|  | } | 
|  |  | 
|  | /* Get the name of a type.  */ | 
|  |  | 
|  | const char * | 
|  | debug_get_type_name (void *handle, debug_type type) | 
|  | { | 
|  | if (type->kind == DEBUG_KIND_INDIRECT) | 
|  | { | 
|  | /* A valid non-self-referencing indirect type.  */ | 
|  | if (*type->u.kindirect->slot != NULL | 
|  | && *type->u.kindirect->slot != type) | 
|  | return debug_get_type_name (handle, *type->u.kindirect->slot); | 
|  | return type->u.kindirect->tag; | 
|  | } | 
|  | if (type->kind == DEBUG_KIND_NAMED | 
|  | || type->kind == DEBUG_KIND_TAGGED) | 
|  | return type->u.knamed->name->name; | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /* Get the size of a type.  */ | 
|  |  | 
|  | bfd_vma | 
|  | debug_get_type_size (void *handle, debug_type type) | 
|  | { | 
|  | if (type == NULL) | 
|  | return 0; | 
|  |  | 
|  | /* We don't call debug_get_real_type, because somebody might have | 
|  | called debug_record_type_size on a named or indirect type.  */ | 
|  |  | 
|  | if (type->size != 0) | 
|  | return type->size; | 
|  |  | 
|  | switch (type->kind) | 
|  | { | 
|  | default: | 
|  | return 0; | 
|  | case DEBUG_KIND_INDIRECT: | 
|  | /* A valid non-self-referencing indirect type.  */ | 
|  | if (*type->u.kindirect->slot != NULL | 
|  | && *type->u.kindirect->slot != type) | 
|  | return debug_get_type_size (handle, *type->u.kindirect->slot); | 
|  | return 0; | 
|  | case DEBUG_KIND_NAMED: | 
|  | case DEBUG_KIND_TAGGED: | 
|  | return debug_get_type_size (handle, type->u.knamed->type); | 
|  | } | 
|  | /*NOTREACHED*/ | 
|  | } | 
|  |  | 
|  | /* Get the return type of a function or method type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_get_return_type (void *handle, debug_type type) | 
|  | { | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | type = debug_get_real_type (handle, type, NULL); | 
|  | if (type == NULL) | 
|  | return DEBUG_TYPE_NULL; | 
|  |  | 
|  | 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 (void *handle, debug_type type, | 
|  | bool *pvarargs) | 
|  | { | 
|  | if (type == NULL) | 
|  | return NULL; | 
|  |  | 
|  | type = debug_get_real_type (handle, type, NULL); | 
|  | if (type == NULL) | 
|  | return NULL; | 
|  |  | 
|  | switch (type->kind) | 
|  | { | 
|  | default: | 
|  | return NULL; | 
|  | case DEBUG_KIND_FUNCTION: | 
|  | *pvarargs = type->u.kfunction->varargs; | 
|  | return type->u.kfunction->arg_types; | 
|  | case DEBUG_KIND_METHOD: | 
|  | *pvarargs = type->u.kmethod->varargs; | 
|  | return type->u.kmethod->arg_types; | 
|  | } | 
|  | /*NOTREACHED*/ | 
|  | } | 
|  |  | 
|  | /* Get the target type of a type.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_get_target_type (void *handle, debug_type type) | 
|  | { | 
|  | if (type == NULL) | 
|  | return NULL; | 
|  |  | 
|  | type = debug_get_real_type (handle, type, NULL); | 
|  | if (type == NULL) | 
|  | return NULL; | 
|  |  | 
|  | switch (type->kind) | 
|  | { | 
|  | default: | 
|  | return NULL; | 
|  | case DEBUG_KIND_POINTER: | 
|  | return type->u.kpointer; | 
|  | case DEBUG_KIND_REFERENCE: | 
|  | return type->u.kreference; | 
|  | case DEBUG_KIND_CONST: | 
|  | return type->u.kconst; | 
|  | case DEBUG_KIND_VOLATILE: | 
|  | return type->u.kvolatile; | 
|  | } | 
|  | /*NOTREACHED*/ | 
|  | } | 
|  |  | 
|  | /* Get the NULL terminated array of fields for a struct, union, or | 
|  | class.  */ | 
|  |  | 
|  | const debug_field * | 
|  | debug_get_fields (void *handle, debug_type type) | 
|  | { | 
|  | if (type == NULL) | 
|  | return NULL; | 
|  |  | 
|  | type = debug_get_real_type (handle, type, NULL); | 
|  | if (type == NULL) | 
|  | return NULL; | 
|  |  | 
|  | 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.  */ | 
|  |  | 
|  | debug_type | 
|  | debug_get_field_type (void *handle ATTRIBUTE_UNUSED, debug_field field) | 
|  | { | 
|  | if (field == NULL) | 
|  | return NULL; | 
|  | return field->type; | 
|  | } | 
|  |  | 
|  | /* Get the name of a field.  */ | 
|  |  | 
|  | const char * | 
|  | debug_get_field_name (void *handle ATTRIBUTE_UNUSED, debug_field field) | 
|  | { | 
|  | if (field == NULL) | 
|  | return NULL; | 
|  | return field->name; | 
|  | } | 
|  |  | 
|  | /* Get the bit position of a field.  */ | 
|  |  | 
|  | bfd_vma | 
|  | debug_get_field_bitpos (void *handle ATTRIBUTE_UNUSED, debug_field field) | 
|  | { | 
|  | if (field == NULL || field->static_member) | 
|  | return (bfd_vma) -1; | 
|  | return field->u.f.bitpos; | 
|  | } | 
|  |  | 
|  | /* Get the bit size of a field.  */ | 
|  |  | 
|  | bfd_vma | 
|  | debug_get_field_bitsize (void *handle ATTRIBUTE_UNUSED, debug_field field) | 
|  | { | 
|  | if (field == NULL || field->static_member) | 
|  | return (bfd_vma) -1; | 
|  | return field->u.f.bitsize; | 
|  | } | 
|  |  | 
|  | /* Get the visibility of a field.  */ | 
|  |  | 
|  | enum debug_visibility | 
|  | debug_get_field_visibility (void *handle ATTRIBUTE_UNUSED, debug_field field) | 
|  | { | 
|  | if (field == NULL) | 
|  | return DEBUG_VISIBILITY_IGNORE; | 
|  | return field->visibility; | 
|  | } | 
|  |  | 
|  | /* Get the physical name of a field.  */ | 
|  |  | 
|  | const char * | 
|  | debug_get_field_physname (void *handle ATTRIBUTE_UNUSED, debug_field field) | 
|  | { | 
|  | if (field == NULL || ! field->static_member) | 
|  | return NULL; | 
|  | return field->u.s.physname; | 
|  | } | 
|  |  | 
|  | /* Write out the debugging information.  This is given a handle to | 
|  | debugging information, and a set of function pointers to call.  */ | 
|  |  | 
|  | bool | 
|  | debug_write (void *handle, const struct debug_write_fns *fns, void *fhandle) | 
|  | { | 
|  | struct debug_handle *info = (struct debug_handle *) handle; | 
|  | struct debug_unit *u; | 
|  |  | 
|  | /* We use a mark to tell whether we have already written out a | 
|  | particular name.  We use an integer, so that we don't have to | 
|  | clear the mark fields if we happen to write out the same | 
|  | 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; | 
|  |  | 
|  | /* We keep a linked list of classes for which was have assigned ID's | 
|  | during this call to debug_write.  */ | 
|  | info->id_list = NULL; | 
|  |  | 
|  | for (u = info->units; u != NULL; u = u->next) | 
|  | { | 
|  | struct debug_file *f; | 
|  | bool first_file; | 
|  |  | 
|  | info->current_write_lineno = u->linenos; | 
|  | info->current_write_lineno_index = 0; | 
|  |  | 
|  | if (! (*fns->start_compilation_unit) (fhandle, u->files->filename)) | 
|  | return false; | 
|  |  | 
|  | first_file = true; | 
|  | for (f = u->files; f != NULL; f = f->next) | 
|  | { | 
|  | struct debug_name *n; | 
|  |  | 
|  | if (first_file) | 
|  | first_file = false; | 
|  | else if (! (*fns->start_source) (fhandle, f->filename)) | 
|  | return false; | 
|  |  | 
|  | if (f->globals != NULL) | 
|  | for (n = f->globals->list; n != NULL; n = n->next) | 
|  | if (! debug_write_name (info, fns, fhandle, n)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Output any line number information which hasn't already been | 
|  | handled.  */ | 
|  | if (! debug_write_linenos (info, fns, fhandle, (bfd_vma) -1)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Write out an element in a namespace.  */ | 
|  |  | 
|  | static bool | 
|  | debug_write_name (struct debug_handle *info, | 
|  | const struct debug_write_fns *fns, void *fhandle, | 
|  | struct debug_name *n) | 
|  | { | 
|  | switch (n->kind) | 
|  | { | 
|  | case DEBUG_OBJECT_TYPE: | 
|  | if (! debug_write_type (info, fns, fhandle, n->u.type, n) | 
|  | || ! (*fns->typdef) (fhandle, n->name)) | 
|  | return false; | 
|  | return true; | 
|  | case DEBUG_OBJECT_TAG: | 
|  | if (! debug_write_type (info, fns, fhandle, n->u.tag, n)) | 
|  | return false; | 
|  | return (*fns->tag) (fhandle, n->name); | 
|  | case DEBUG_OBJECT_VARIABLE: | 
|  | if (! debug_write_type (info, fns, fhandle, n->u.variable->type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->variable) (fhandle, n->name, n->u.variable->kind, | 
|  | n->u.variable->val); | 
|  | case DEBUG_OBJECT_FUNCTION: | 
|  | return debug_write_function (info, fns, fhandle, n->name, | 
|  | n->linkage, n->u.function); | 
|  | case DEBUG_OBJECT_INT_CONSTANT: | 
|  | return (*fns->int_constant) (fhandle, n->name, n->u.int_constant); | 
|  | case DEBUG_OBJECT_FLOAT_CONSTANT: | 
|  | return (*fns->float_constant) (fhandle, n->name, n->u.float_constant); | 
|  | case DEBUG_OBJECT_TYPED_CONSTANT: | 
|  | if (! debug_write_type (info, fns, fhandle, n->u.typed_constant->type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->typed_constant) (fhandle, n->name, | 
|  | n->u.typed_constant->val); | 
|  | default: | 
|  | abort (); | 
|  | return false; | 
|  | } | 
|  | /*NOTREACHED*/ | 
|  | } | 
|  |  | 
|  | /* 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 bool | 
|  | debug_write_type (struct debug_handle *info, | 
|  | const struct debug_write_fns *fns, void *fhandle, | 
|  | struct debug_type_s *type, struct debug_name *name) | 
|  | { | 
|  | unsigned int i; | 
|  | int is; | 
|  | const char *tag = NULL; | 
|  |  | 
|  | if (type == DEBUG_TYPE_NULL) | 
|  | return (*fns->empty_type) (fhandle); | 
|  |  | 
|  | /* 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 | 
|  | whenever we are not actually defining them.  */ | 
|  | if ((type->kind == DEBUG_KIND_NAMED | 
|  | || type->kind == DEBUG_KIND_TAGGED) | 
|  | && (type->u.knamed->name->mark == info->mark | 
|  | || (type->kind == DEBUG_KIND_TAGGED | 
|  | && type->u.knamed->name != name))) | 
|  | { | 
|  | if (type->kind == DEBUG_KIND_NAMED) | 
|  | return (*fns->typedef_type) (fhandle, type->u.knamed->name->name); | 
|  | else | 
|  | { | 
|  | struct debug_type_s *real; | 
|  | unsigned int id; | 
|  |  | 
|  | real = debug_get_real_type ((void *) info, type, NULL); | 
|  | if (real == NULL) | 
|  | return (*fns->empty_type) (fhandle); | 
|  | id = 0; | 
|  | if ((real->kind == DEBUG_KIND_STRUCT | 
|  | || real->kind == DEBUG_KIND_UNION | 
|  | || real->kind == DEBUG_KIND_CLASS | 
|  | || real->kind == DEBUG_KIND_UNION_CLASS) | 
|  | && real->u.kclass != NULL) | 
|  | { | 
|  | if (real->u.kclass->id <= info->base_id) | 
|  | { | 
|  | if (! debug_set_class_id (info, | 
|  | type->u.knamed->name->name, | 
|  | real)) | 
|  | return false; | 
|  | } | 
|  | id = real->u.kclass->id; | 
|  | } | 
|  |  | 
|  | return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id, | 
|  | real->kind); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Mark the name after we have already looked for a known name, so | 
|  | that we don't just define a type in terms of itself.  We need to | 
|  | mark the name here so that a struct containing a pointer to | 
|  | itself will work.  */ | 
|  | if (name != NULL) | 
|  | name->mark = info->mark; | 
|  |  | 
|  | 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_ILLEGAL: | 
|  | debug_error (_("debug_write_type: illegal type encountered")); | 
|  | return false; | 
|  | case DEBUG_KIND_INDIRECT: | 
|  | /* Prevent infinite recursion.  */ | 
|  | if (*type->u.kindirect->slot == type) | 
|  | return (*fns->empty_type) (fhandle); | 
|  | return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot, | 
|  | name); | 
|  | case DEBUG_KIND_VOID: | 
|  | return (*fns->void_type) (fhandle); | 
|  | case DEBUG_KIND_INT: | 
|  | return (*fns->int_type) (fhandle, type->size, type->u.kint); | 
|  | case DEBUG_KIND_FLOAT: | 
|  | return (*fns->float_type) (fhandle, type->size); | 
|  | case DEBUG_KIND_COMPLEX: | 
|  | return (*fns->complex_type) (fhandle, type->size); | 
|  | case DEBUG_KIND_BOOL: | 
|  | return (*fns->bool_type) (fhandle, type->size); | 
|  | case DEBUG_KIND_STRUCT: | 
|  | case DEBUG_KIND_UNION: | 
|  | if (type->u.kclass != NULL) | 
|  | { | 
|  | if (type->u.kclass->id <= info->base_id) | 
|  | { | 
|  | if (! debug_set_class_id (info, tag, type)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (info->mark == type->u.kclass->mark) | 
|  | { | 
|  | /* 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->mark; | 
|  | } | 
|  |  | 
|  | 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; | 
|  | if (type->u.kclass != NULL | 
|  | && type->u.kclass->fields != NULL) | 
|  | { | 
|  | for (i = 0; type->u.kclass->fields[i] != NULL; i++) | 
|  | { | 
|  | struct debug_field_s *f; | 
|  |  | 
|  | f = type->u.kclass->fields[i]; | 
|  | if (! debug_write_type (info, fns, fhandle, f->type, | 
|  | (struct debug_name *) NULL) | 
|  | || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, | 
|  | f->u.f.bitsize, f->visibility)) | 
|  | 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, tag); | 
|  | case DEBUG_KIND_ENUM: | 
|  | if (type->u.kenum == NULL) | 
|  | return (*fns->enum_type) (fhandle, tag, (const char **) NULL, | 
|  | (bfd_signed_vma *) NULL); | 
|  | 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, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->pointer_type) (fhandle); | 
|  | case DEBUG_KIND_FUNCTION: | 
|  | if (! debug_write_type (info, fns, fhandle, | 
|  | type->u.kfunction->return_type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | if (type->u.kfunction->arg_types == NULL) | 
|  | is = -1; | 
|  | else | 
|  | { | 
|  | for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++) | 
|  | if (! debug_write_type (info, fns, fhandle, | 
|  | type->u.kfunction->arg_types[is], | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | } | 
|  | return (*fns->function_type) (fhandle, is, | 
|  | type->u.kfunction->varargs); | 
|  | case DEBUG_KIND_REFERENCE: | 
|  | if (! debug_write_type (info, fns, fhandle, type->u.kreference, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->reference_type) (fhandle); | 
|  | case DEBUG_KIND_RANGE: | 
|  | if (! debug_write_type (info, fns, fhandle, type->u.krange->type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->range_type) (fhandle, type->u.krange->lower, | 
|  | type->u.krange->upper); | 
|  | case DEBUG_KIND_ARRAY: | 
|  | if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type, | 
|  | (struct debug_name *) NULL) | 
|  | || ! debug_write_type (info, fns, fhandle, | 
|  | type->u.karray->range_type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->array_type) (fhandle, type->u.karray->lower, | 
|  | type->u.karray->upper, | 
|  | type->u.karray->stringp); | 
|  | case DEBUG_KIND_SET: | 
|  | if (! debug_write_type (info, fns, fhandle, type->u.kset->type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->set_type) (fhandle, type->u.kset->bitstringp); | 
|  | case DEBUG_KIND_OFFSET: | 
|  | if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type, | 
|  | (struct debug_name *) NULL) | 
|  | || ! debug_write_type (info, fns, fhandle, | 
|  | type->u.koffset->target_type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->offset_type) (fhandle); | 
|  | case DEBUG_KIND_METHOD: | 
|  | if (! debug_write_type (info, fns, fhandle, | 
|  | type->u.kmethod->return_type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | if (type->u.kmethod->arg_types == NULL) | 
|  | is = -1; | 
|  | else | 
|  | { | 
|  | for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++) | 
|  | if (! debug_write_type (info, fns, fhandle, | 
|  | type->u.kmethod->arg_types[is], | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | } | 
|  | if (type->u.kmethod->domain_type != NULL) | 
|  | { | 
|  | if (! debug_write_type (info, fns, fhandle, | 
|  | type->u.kmethod->domain_type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | } | 
|  | return (*fns->method_type) (fhandle, | 
|  | type->u.kmethod->domain_type != NULL, | 
|  | is, | 
|  | type->u.kmethod->varargs); | 
|  | case DEBUG_KIND_CONST: | 
|  | if (! debug_write_type (info, fns, fhandle, type->u.kconst, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->const_type) (fhandle); | 
|  | case DEBUG_KIND_VOLATILE: | 
|  | if (! debug_write_type (info, fns, fhandle, type->u.kvolatile, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | return (*fns->volatile_type) (fhandle); | 
|  | case DEBUG_KIND_NAMED: | 
|  | 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 bool | 
|  | debug_write_class_type (struct debug_handle *info, | 
|  | const struct debug_write_fns *fns, void *fhandle, | 
|  | struct debug_type_s *type, const char *tag) | 
|  | { | 
|  | unsigned int i; | 
|  | unsigned int id; | 
|  | struct debug_type_s *vptrbase; | 
|  |  | 
|  | if (type->u.kclass == NULL) | 
|  | { | 
|  | id = 0; | 
|  | vptrbase = NULL; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (type->u.kclass->id <= info->base_id) | 
|  | { | 
|  | if (! debug_set_class_id (info, tag, type)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (info->mark == type->u.kclass->mark) | 
|  | { | 
|  | /* 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->mark; | 
|  | id = type->u.kclass->id; | 
|  |  | 
|  | vptrbase = type->u.kclass->vptrbase; | 
|  | if (vptrbase != NULL && vptrbase != type) | 
|  | { | 
|  | if (! debug_write_type (info, fns, fhandle, vptrbase, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (! (*fns->start_class_type) (fhandle, tag, id, | 
|  | type->kind == DEBUG_KIND_CLASS, | 
|  | type->size, | 
|  | vptrbase != NULL, | 
|  | vptrbase == type)) | 
|  | return false; | 
|  |  | 
|  | if (type->u.kclass != NULL) | 
|  | { | 
|  | if (type->u.kclass->fields != NULL) | 
|  | { | 
|  | for (i = 0; type->u.kclass->fields[i] != NULL; i++) | 
|  | { | 
|  | struct debug_field_s *f; | 
|  |  | 
|  | f = type->u.kclass->fields[i]; | 
|  | if (! debug_write_type (info, fns, fhandle, f->type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | if (f->static_member) | 
|  | { | 
|  | if (! (*fns->class_static_member) (fhandle, f->name, | 
|  | f->u.s.physname, | 
|  | f->visibility)) | 
|  | return false; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, | 
|  | f->u.f.bitsize, f->visibility)) | 
|  | return false; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (type->u.kclass->baseclasses != NULL) | 
|  | { | 
|  | for (i = 0; type->u.kclass->baseclasses[i] != NULL; i++) | 
|  | { | 
|  | struct debug_baseclass_s *b; | 
|  |  | 
|  | b = type->u.kclass->baseclasses[i]; | 
|  | if (! debug_write_type (info, fns, fhandle, b->type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | if (! (*fns->class_baseclass) (fhandle, b->bitpos, b->is_virtual, | 
|  | b->visibility)) | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (type->u.kclass->methods != NULL) | 
|  | { | 
|  | for (i = 0; type->u.kclass->methods[i] != NULL; i++) | 
|  | { | 
|  | struct debug_method_s *m; | 
|  | unsigned int j; | 
|  |  | 
|  | m = type->u.kclass->methods[i]; | 
|  | if (! (*fns->class_start_method) (fhandle, m->name)) | 
|  | return false; | 
|  | for (j = 0; m->variants[j] != NULL; j++) | 
|  | { | 
|  | struct debug_method_variant_s *v; | 
|  |  | 
|  | v = m->variants[j]; | 
|  | if (v->context != NULL) | 
|  | { | 
|  | if (! debug_write_type (info, fns, fhandle, v->context, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | } | 
|  | if (! debug_write_type (info, fns, fhandle, v->type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  | if (v->voffset != VOFFSET_STATIC_METHOD) | 
|  | { | 
|  | if (! (*fns->class_method_variant) (fhandle, v->physname, | 
|  | v->visibility, | 
|  | v->constp, | 
|  | v->volatilep, | 
|  | v->voffset, | 
|  | v->context != NULL)) | 
|  | return false; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (! (*fns->class_static_method_variant) (fhandle, | 
|  | v->physname, | 
|  | v->visibility, | 
|  | v->constp, | 
|  | v->volatilep)) | 
|  | return false; | 
|  | } | 
|  | } | 
|  | if (! (*fns->class_end_method) (fhandle)) | 
|  | return false; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return (*fns->end_class_type) (fhandle); | 
|  | } | 
|  |  | 
|  | /* Write out information for a function.  */ | 
|  |  | 
|  | static bool | 
|  | debug_write_function (struct debug_handle *info, | 
|  | const struct debug_write_fns *fns, void *fhandle, | 
|  | const char *name, enum debug_object_linkage linkage, | 
|  | struct debug_function *function) | 
|  | { | 
|  | struct debug_parameter *p; | 
|  | struct debug_block *b; | 
|  |  | 
|  | if (! debug_write_linenos (info, fns, fhandle, function->blocks->start)) | 
|  | return false; | 
|  |  | 
|  | if (! debug_write_type (info, fns, fhandle, function->return_type, | 
|  | (struct debug_name *) NULL)) | 
|  | return false; | 
|  |  | 
|  | if (! (*fns->start_function) (fhandle, name, | 
|  | linkage == DEBUG_LINKAGE_GLOBAL)) | 
|  | return false; | 
|  |  | 
|  | for (p = function->parameters; p != NULL; p = p->next) | 
|  | { | 
|  | if (! debug_write_type (info, fns, fhandle, p->type, | 
|  | (struct debug_name *) NULL) | 
|  | || ! (*fns->function_parameter) (fhandle, p->name, p->kind, p->val)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | for (b = function->blocks; b != NULL; b = b->next) | 
|  | { | 
|  | if (! debug_write_block (info, fns, fhandle, b)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return (*fns->end_function) (fhandle); | 
|  | } | 
|  |  | 
|  | /* Write out information for a block.  */ | 
|  |  | 
|  | static bool | 
|  | debug_write_block (struct debug_handle *info, | 
|  | const struct debug_write_fns *fns, void *fhandle, | 
|  | struct debug_block *block) | 
|  | { | 
|  | struct debug_name *n; | 
|  | struct debug_block *b; | 
|  |  | 
|  | if (! debug_write_linenos (info, fns, fhandle, block->start)) | 
|  | return false; | 
|  |  | 
|  | /* I can't see any point to writing out a block with no local | 
|  | variables, so we don't bother, except for the top level block.  */ | 
|  | if (block->locals != NULL || block->parent == NULL) | 
|  | { | 
|  | if (! (*fns->start_block) (fhandle, block->start)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (block->locals != NULL) | 
|  | { | 
|  | for (n = block->locals->list; n != NULL; n = n->next) | 
|  | { | 
|  | if (! debug_write_name (info, fns, fhandle, n)) | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | for (b = block->children; b != NULL; b = b->next) | 
|  | { | 
|  | if (! debug_write_block (info, fns, fhandle, b)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (! debug_write_linenos (info, fns, fhandle, block->end)) | 
|  | return false; | 
|  |  | 
|  | if (block->locals != NULL || block->parent == NULL) | 
|  | { | 
|  | if (! (*fns->end_block) (fhandle, block->end)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Write out line number information up to ADDRESS.  */ | 
|  |  | 
|  | static bool | 
|  | debug_write_linenos (struct debug_handle *info, | 
|  | const struct debug_write_fns *fns, void *fhandle, | 
|  | bfd_vma address) | 
|  | { | 
|  | while (info->current_write_lineno != NULL) | 
|  | { | 
|  | struct debug_lineno *l; | 
|  |  | 
|  | l = info->current_write_lineno; | 
|  |  | 
|  | while (info->current_write_lineno_index < DEBUG_LINENO_COUNT) | 
|  | { | 
|  | if (l->linenos[info->current_write_lineno_index] | 
|  | == (unsigned long) -1) | 
|  | break; | 
|  |  | 
|  | if (l->addrs[info->current_write_lineno_index] >= address) | 
|  | return true; | 
|  |  | 
|  | if (! (*fns->lineno) (fhandle, l->file->filename, | 
|  | l->linenos[info->current_write_lineno_index], | 
|  | l->addrs[info->current_write_lineno_index])) | 
|  | return false; | 
|  |  | 
|  | ++info->current_write_lineno_index; | 
|  | } | 
|  |  | 
|  | info->current_write_lineno = l->next; | 
|  | info->current_write_lineno_index = 0; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Get the ID number for a class.  If during the same call to | 
|  | debug_write we find a struct with the same definition with the same | 
|  | name, we use the same ID.  This type of things happens because the | 
|  | same struct will be defined by multiple compilation units.  */ | 
|  |  | 
|  | static bool | 
|  | debug_set_class_id (struct debug_handle *info, const char *tag, | 
|  | struct debug_type_s *type) | 
|  | { | 
|  | struct debug_class_type *c; | 
|  | struct debug_class_id *l; | 
|  |  | 
|  | assert (type->kind == DEBUG_KIND_STRUCT | 
|  | || type->kind == DEBUG_KIND_UNION | 
|  | || type->kind == DEBUG_KIND_CLASS | 
|  | || type->kind == DEBUG_KIND_UNION_CLASS); | 
|  |  | 
|  | c = type->u.kclass; | 
|  |  | 
|  | if (c->id > info->base_id) | 
|  | return true; | 
|  |  | 
|  | for (l = info->id_list; l != NULL; l = l->next) | 
|  | { | 
|  | if (l->type->kind != type->kind) | 
|  | continue; | 
|  |  | 
|  | if (tag == NULL) | 
|  | { | 
|  | if (l->tag != NULL) | 
|  | continue; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (l->tag == NULL | 
|  | || l->tag[0] != tag[0] | 
|  | || strcmp (l->tag, tag) != 0) | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (debug_type_samep (info, l->type, type)) | 
|  | { | 
|  | c->id = l->type->u.kclass->id; | 
|  | return true; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* There are no identical types.  Use a new ID, and add it to the | 
|  | list.  */ | 
|  | ++info->class_id; | 
|  | c->id = info->class_id; | 
|  |  | 
|  | l = debug_xzalloc (info, sizeof (*l)); | 
|  |  | 
|  | l->type = type; | 
|  | l->tag = tag; | 
|  |  | 
|  | l->next = info->id_list; | 
|  | info->id_list = l; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* See if two types are the same.  At this point, we don't care about | 
|  | tags and the like.  */ | 
|  |  | 
|  | static bool | 
|  | debug_type_samep (struct debug_handle *info, struct debug_type_s *t1, | 
|  | struct debug_type_s *t2) | 
|  | { | 
|  | struct debug_type_compare_list *l; | 
|  | struct debug_type_compare_list top; | 
|  | bool ret; | 
|  |  | 
|  | if (t1 == NULL) | 
|  | return t2 == NULL; | 
|  | if (t2 == NULL) | 
|  | return false; | 
|  |  | 
|  | while (t1->kind == DEBUG_KIND_INDIRECT) | 
|  | { | 
|  | t1 = *t1->u.kindirect->slot; | 
|  | if (t1 == NULL) | 
|  | return false; | 
|  | } | 
|  | while (t2->kind == DEBUG_KIND_INDIRECT) | 
|  | { | 
|  | t2 = *t2->u.kindirect->slot; | 
|  | if (t2 == NULL) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (t1 == t2) | 
|  | return true; | 
|  |  | 
|  | /* As a special case, permit a typedef to match a tag, since C++ | 
|  | debugging output will sometimes add a typedef where C debugging | 
|  | output will not.  */ | 
|  | if (t1->kind == DEBUG_KIND_NAMED | 
|  | && t2->kind == DEBUG_KIND_TAGGED) | 
|  | return debug_type_samep (info, t1->u.knamed->type, t2); | 
|  | else if (t1->kind == DEBUG_KIND_TAGGED | 
|  | && t2->kind == DEBUG_KIND_NAMED) | 
|  | return debug_type_samep (info, t1, t2->u.knamed->type); | 
|  |  | 
|  | if (t1->kind != t2->kind | 
|  | || t1->size != t2->size) | 
|  | return false; | 
|  |  | 
|  | /* Get rid of the trivial cases first.  */ | 
|  | switch (t1->kind) | 
|  | { | 
|  | default: | 
|  | break; | 
|  | case DEBUG_KIND_VOID: | 
|  | case DEBUG_KIND_FLOAT: | 
|  | case DEBUG_KIND_COMPLEX: | 
|  | case DEBUG_KIND_BOOL: | 
|  | return true; | 
|  | case DEBUG_KIND_INT: | 
|  | return t1->u.kint == t2->u.kint; | 
|  | } | 
|  |  | 
|  | /* We have to avoid an infinite recursion.  We do this by keeping a | 
|  | list of types which we are comparing.  We just keep the list on | 
|  | the stack.  If we encounter a pair of types we are currently | 
|  | comparing, we just assume that they are equal.  */ | 
|  | for (l = info->compare_list; l != NULL; l = l->next) | 
|  | { | 
|  | if (l->t1 == t1 && l->t2 == t2) | 
|  | return true; | 
|  | } | 
|  |  | 
|  | top.t1 = t1; | 
|  | top.t2 = t2; | 
|  | top.next = info->compare_list; | 
|  | info->compare_list = ⊤ | 
|  |  | 
|  | switch (t1->kind) | 
|  | { | 
|  | default: | 
|  | abort (); | 
|  | ret = false; | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_STRUCT: | 
|  | case DEBUG_KIND_UNION: | 
|  | case DEBUG_KIND_CLASS: | 
|  | case DEBUG_KIND_UNION_CLASS: | 
|  | if (t1->u.kclass == NULL) | 
|  | ret = t2->u.kclass == NULL; | 
|  | else if (t2->u.kclass == NULL) | 
|  | ret = false; | 
|  | else if (t1->u.kclass->id > info->base_id | 
|  | && t1->u.kclass->id == t2->u.kclass->id) | 
|  | ret = true; | 
|  | else | 
|  | ret = debug_class_type_samep (info, t1, t2); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_ENUM: | 
|  | if (t1->u.kenum == NULL) | 
|  | ret = t2->u.kenum == NULL; | 
|  | else if (t2->u.kenum == NULL) | 
|  | ret = false; | 
|  | else | 
|  | { | 
|  | const char **pn1, **pn2; | 
|  | bfd_signed_vma *pv1, *pv2; | 
|  |  | 
|  | pn1 = t1->u.kenum->names; | 
|  | pn2 = t2->u.kenum->names; | 
|  | pv1 = t1->u.kenum->values; | 
|  | pv2 = t2->u.kenum->values; | 
|  | while (*pn1 != NULL && *pn2 != NULL) | 
|  | { | 
|  | if (**pn1 != **pn2 | 
|  | || *pv1 != *pv2 | 
|  | || strcmp (*pn1, *pn2) != 0) | 
|  | break; | 
|  | ++pn1; | 
|  | ++pn2; | 
|  | ++pv1; | 
|  | ++pv2; | 
|  | } | 
|  | ret = *pn1 == NULL && *pn2 == NULL; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_POINTER: | 
|  | ret = debug_type_samep (info, t1->u.kpointer, t2->u.kpointer); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_FUNCTION: | 
|  | if (t1->u.kfunction->varargs != t2->u.kfunction->varargs | 
|  | || ! debug_type_samep (info, t1->u.kfunction->return_type, | 
|  | t2->u.kfunction->return_type) | 
|  | || ((t1->u.kfunction->arg_types == NULL) | 
|  | != (t2->u.kfunction->arg_types == NULL))) | 
|  | ret = false; | 
|  | else if (t1->u.kfunction->arg_types == NULL) | 
|  | ret = true; | 
|  | else | 
|  | { | 
|  | struct debug_type_s **a1, **a2; | 
|  |  | 
|  | a1 = t1->u.kfunction->arg_types; | 
|  | a2 = t2->u.kfunction->arg_types; | 
|  | while (*a1 != NULL && *a2 != NULL) | 
|  | { | 
|  | if (! debug_type_samep (info, *a1, *a2)) | 
|  | break; | 
|  | ++a1; | 
|  | ++a2; | 
|  | } | 
|  | ret = *a1 == NULL && *a2 == NULL; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_REFERENCE: | 
|  | ret = debug_type_samep (info, t1->u.kreference, t2->u.kreference); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_RANGE: | 
|  | ret = (t1->u.krange->lower == t2->u.krange->lower | 
|  | && t1->u.krange->upper == t2->u.krange->upper | 
|  | && debug_type_samep (info, t1->u.krange->type, | 
|  | t2->u.krange->type)); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_ARRAY: | 
|  | ret = (t1->u.karray->lower == t2->u.karray->lower | 
|  | && t1->u.karray->upper == t2->u.karray->upper | 
|  | && t1->u.karray->stringp == t2->u.karray->stringp | 
|  | && debug_type_samep (info, t1->u.karray->element_type, | 
|  | t2->u.karray->element_type)); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_SET: | 
|  | ret = (t1->u.kset->bitstringp == t2->u.kset->bitstringp | 
|  | && debug_type_samep (info, t1->u.kset->type, t2->u.kset->type)); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_OFFSET: | 
|  | ret = (debug_type_samep (info, t1->u.koffset->base_type, | 
|  | t2->u.koffset->base_type) | 
|  | && debug_type_samep (info, t1->u.koffset->target_type, | 
|  | t2->u.koffset->target_type)); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_METHOD: | 
|  | if (t1->u.kmethod->varargs != t2->u.kmethod->varargs | 
|  | || ! debug_type_samep (info, t1->u.kmethod->return_type, | 
|  | t2->u.kmethod->return_type) | 
|  | || ! debug_type_samep (info, t1->u.kmethod->domain_type, | 
|  | t2->u.kmethod->domain_type) | 
|  | || ((t1->u.kmethod->arg_types == NULL) | 
|  | != (t2->u.kmethod->arg_types == NULL))) | 
|  | ret = false; | 
|  | else if (t1->u.kmethod->arg_types == NULL) | 
|  | ret = true; | 
|  | else | 
|  | { | 
|  | struct debug_type_s **a1, **a2; | 
|  |  | 
|  | a1 = t1->u.kmethod->arg_types; | 
|  | a2 = t2->u.kmethod->arg_types; | 
|  | while (*a1 != NULL && *a2 != NULL) | 
|  | { | 
|  | if (! debug_type_samep (info, *a1, *a2)) | 
|  | break; | 
|  | ++a1; | 
|  | ++a2; | 
|  | } | 
|  | ret = *a1 == NULL && *a2 == NULL; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_CONST: | 
|  | ret = debug_type_samep (info, t1->u.kconst, t2->u.kconst); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_VOLATILE: | 
|  | ret = debug_type_samep (info, t1->u.kvolatile, t2->u.kvolatile); | 
|  | break; | 
|  |  | 
|  | case DEBUG_KIND_NAMED: | 
|  | case DEBUG_KIND_TAGGED: | 
|  | ret = (strcmp (t1->u.knamed->name->name, t2->u.knamed->name->name) == 0 | 
|  | && debug_type_samep (info, t1->u.knamed->type, | 
|  | t2->u.knamed->type)); | 
|  | break; | 
|  | } | 
|  |  | 
|  | info->compare_list = top.next; | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* See if two classes are the same.  This is a subroutine of | 
|  | debug_type_samep.  */ | 
|  |  | 
|  | static bool | 
|  | debug_class_type_samep (struct debug_handle *info, struct debug_type_s *t1, | 
|  | struct debug_type_s *t2) | 
|  | { | 
|  | struct debug_class_type *c1, *c2; | 
|  |  | 
|  | c1 = t1->u.kclass; | 
|  | c2 = t2->u.kclass; | 
|  |  | 
|  | if ((c1->fields == NULL) != (c2->fields == NULL) | 
|  | || (c1->baseclasses == NULL) != (c2->baseclasses == NULL) | 
|  | || (c1->methods == NULL) != (c2->methods == NULL) | 
|  | || (c1->vptrbase == NULL) != (c2->vptrbase == NULL)) | 
|  | return false; | 
|  |  | 
|  | if (c1->fields != NULL) | 
|  | { | 
|  | struct debug_field_s **pf1, **pf2; | 
|  |  | 
|  | for (pf1 = c1->fields, pf2 = c2->fields; | 
|  | *pf1 != NULL && *pf2 != NULL; | 
|  | pf1++, pf2++) | 
|  | { | 
|  | struct debug_field_s *f1, *f2; | 
|  |  | 
|  | f1 = *pf1; | 
|  | f2 = *pf2; | 
|  | if (f1->name[0] != f2->name[0] | 
|  | || f1->visibility != f2->visibility | 
|  | || f1->static_member != f2->static_member) | 
|  | return false; | 
|  | if (f1->static_member) | 
|  | { | 
|  | if (strcmp (f1->u.s.physname, f2->u.s.physname) != 0) | 
|  | return false; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (f1->u.f.bitpos != f2->u.f.bitpos | 
|  | || f1->u.f.bitsize != f2->u.f.bitsize) | 
|  | return false; | 
|  | } | 
|  | /* We do the checks which require function calls last.  We | 
|  | don't require that the types of fields have the same | 
|  | names, since that sometimes fails in the presence of | 
|  | typedefs and we really don't care.  */ | 
|  | if (strcmp (f1->name, f2->name) != 0 | 
|  | || f1->type == NULL | 
|  | || f2->type == NULL | 
|  | || ! debug_type_samep (info, | 
|  | debug_get_real_type ((void *) info, | 
|  | f1->type, NULL), | 
|  | debug_get_real_type ((void *) info, | 
|  | f2->type, NULL))) | 
|  | return false; | 
|  | } | 
|  | if (*pf1 != NULL || *pf2 != NULL) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (c1->vptrbase != NULL) | 
|  | { | 
|  | if (! debug_type_samep (info, c1->vptrbase, c2->vptrbase)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (c1->baseclasses != NULL) | 
|  | { | 
|  | struct debug_baseclass_s **pb1, **pb2; | 
|  |  | 
|  | for (pb1 = c1->baseclasses, pb2 = c2->baseclasses; | 
|  | *pb1 != NULL && *pb2 != NULL; | 
|  | ++pb1, ++pb2) | 
|  | { | 
|  | struct debug_baseclass_s *b1, *b2; | 
|  |  | 
|  | b1 = *pb1; | 
|  | b2 = *pb2; | 
|  | if (b1->bitpos != b2->bitpos | 
|  | || b1->is_virtual != b2->is_virtual | 
|  | || b1->visibility != b2->visibility | 
|  | || ! debug_type_samep (info, b1->type, b2->type)) | 
|  | return false; | 
|  | } | 
|  | if (*pb1 != NULL || *pb2 != NULL) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (c1->methods != NULL) | 
|  | { | 
|  | struct debug_method_s **pm1, **pm2; | 
|  |  | 
|  | for (pm1 = c1->methods, pm2 = c2->methods; | 
|  | *pm1 != NULL && *pm2 != NULL; | 
|  | ++pm1, ++pm2) | 
|  | { | 
|  | struct debug_method_s *m1, *m2; | 
|  |  | 
|  | m1 = *pm1; | 
|  | m2 = *pm2; | 
|  | if (m1->name[0] != m2->name[0] | 
|  | || strcmp (m1->name, m2->name) != 0 | 
|  | || (m1->variants == NULL) != (m2->variants == NULL)) | 
|  | return false; | 
|  | if (m1->variants != NULL) | 
|  | { | 
|  | struct debug_method_variant_s **pv1, **pv2; | 
|  |  | 
|  | for (pv1 = m1->variants, pv2 = m2->variants; | 
|  | *pv1 != NULL && *pv2 != NULL; | 
|  | ++pv1, ++pv2) | 
|  | { | 
|  | struct debug_method_variant_s *v1, *v2; | 
|  |  | 
|  | v1 = *pv1; | 
|  | v2 = *pv2; | 
|  | if (v1->physname[0] != v2->physname[0] | 
|  | || v1->visibility != v2->visibility | 
|  | || v1->constp != v2->constp | 
|  | || v1->volatilep != v2->volatilep | 
|  | || v1->voffset != v2->voffset | 
|  | || (v1->context == NULL) != (v2->context == NULL) | 
|  | || strcmp (v1->physname, v2->physname) != 0 | 
|  | || ! debug_type_samep (info, v1->type, v2->type)) | 
|  | return false; | 
|  | if (v1->context != NULL) | 
|  | { | 
|  | if (! debug_type_samep (info, v1->context, | 
|  | v2->context)) | 
|  | return false; | 
|  | } | 
|  | } | 
|  | if (*pv1 != NULL || *pv2 != NULL) | 
|  | return false; | 
|  | } | 
|  | } | 
|  | if (*pm1 != NULL || *pm2 != NULL) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } |