diff options
-rw-r--r-- | gdb/ChangeLog | 19 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 122 |
2 files changed, 130 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5fe8c64..12d2a29 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2010-08-20 Keith Seitz <keiths@redhat.com> + + PR symtab/11465: + * dwarf2read.c (struct delayed_method_info): New struct. + (struct dwarf2_cu): Add vector method_list. + (scan_partial_symbols): Count methods for union, class, structure, + and interface types. + (add_to_method_list): New function. + (free_delayed_list): New function. + (compute_delayed_physnames): New function. + (process_full_comp_unit): Make a cleanup for the CU's delayed + physname list, compute the delayed physnames, and free the + the list. + (dwarf2_add_member_fn): For C++ and Java, delay the computation + of the physname until after the CU is read. + + * dwarf2read.c (read_structure_type): Check if the current + DIE's type was already completed after dwarf2_full_name + was called. 2010-08-19 Stan Shebs <stan@codesourcery.com> * NEWS: Mention some additional changes. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 6ea1704..ec623a7 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -266,6 +266,29 @@ struct comp_unit_head unsigned int first_die_offset; }; +/* Type used for delaying computation of method physnames. + See comments for compute_delayed_physnames. */ +struct delayed_method_info +{ + /* The type to which the method is attached, i.e., its parent class. */ + struct type *type; + + /* The index of the method in the type's function fieldlists. */ + int fnfield_index; + + /* The index of the method in the fieldlist. */ + int index; + + /* The name of the DIE. */ + const char *name; + + /* The DIE associated with this method. */ + struct die_info *die; +}; + +typedef struct delayed_method_info delayed_method_info; +DEF_VEC_O (delayed_method_info); + /* Internal state when decoding a particular compilation unit. */ struct dwarf2_cu { @@ -344,6 +367,10 @@ struct dwarf2_cu /* Header data from the line table, during full symbol processing. */ struct line_header *line_header; + /* A list of methods which need to have physnames computed + after all type information has been read. */ + VEC (delayed_method_info) *method_list; + /* Mark used when releasing cached dies. */ unsigned int mark : 1; @@ -1289,6 +1316,9 @@ byte_swap (offset_type value) /* The suffix for an index file. */ #define INDEX_SUFFIX ".gdb-index" +static const char *dwarf2_physname (char *name, struct die_info *die, + struct dwarf2_cu *cu); + /* Try to locate the sections we need for DWARF 2 debugging information and return true if we have enough to do something. */ @@ -4342,6 +4372,56 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) } } +/* Add a DIE to the delayed physname list. */ + +static void +add_to_method_list (struct type *type, int fnfield_index, int index, + const char *name, struct die_info *die, + struct dwarf2_cu *cu) +{ + struct delayed_method_info mi; + mi.type = type; + mi.fnfield_index = fnfield_index; + mi.index = index; + mi.name = name; + mi.die = die; + VEC_safe_push (delayed_method_info, cu->method_list, &mi); +} + +/* A cleanup for freeing the delayed method list. */ + +static void +free_delayed_list (void *ptr) +{ + struct dwarf2_cu *cu = (struct dwarf2_cu *) ptr; + if (cu->method_list != NULL) + { + VEC_free (delayed_method_info, cu->method_list); + cu->method_list = NULL; + } +} + +/* Compute the physnames of any methods on the CU's method list. + + The computation of method physnames is delayed in order to avoid the + (bad) condition that one of the method's formal parameters is of an as yet + incomplete type. */ + +static void +compute_delayed_physnames (struct dwarf2_cu *cu) +{ + int i; + struct delayed_method_info *mi; + for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i) + { + char *physname; + struct fn_fieldlist *fn_flp + = &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index); + physname = (char *) dwarf2_physname ((char *) mi->name, mi->die, cu); + fn_flp->fn_fields[mi->index].physname = physname ? physname : ""; + } +} + /* Generate full symbol information for PST and CU, whose DIEs have already been loaded into memory. */ @@ -4352,13 +4432,14 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) struct objfile *objfile = per_cu->objfile; CORE_ADDR lowpc, highpc; struct symtab *symtab; - struct cleanup *back_to; + struct cleanup *back_to, *delayed_list_cleanup; CORE_ADDR baseaddr; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); buildsym_init (); back_to = make_cleanup (really_free_pendings, NULL); + delayed_list_cleanup = make_cleanup (free_delayed_list, cu); cu->list_in_scope = &file_symbols; @@ -4367,6 +4448,12 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) /* Do line number decoding in read_file_scope () */ process_die (cu->dies, cu); + /* Now that we have processed all the DIEs in the CU, all the types + should be complete, and it should now be safe to compute all of the + physnames. */ + compute_delayed_physnames (cu); + do_cleanups (delayed_list_cleanup); + /* Some compilers don't define a DW_AT_high_pc attribute for the compilation unit. If the DW_AT_high_pc is missing, synthesize it, by scanning the DIE's below the compilation unit. */ @@ -6249,7 +6336,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, int i; struct fn_field *fnp; char *fieldname; - char *physname; struct nextfnfield *new_fnfield; struct type *this_type; @@ -6261,9 +6347,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, if (fieldname == NULL) return; - /* Get the mangled name. */ - physname = (char *) dwarf2_physname (fieldname, die, cu); - /* Look up member function name in fieldlist. */ for (i = 0; i < fip->nfnfields; i++) { @@ -6289,7 +6372,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, flp->name = fieldname; flp->length = 0; flp->head = NULL; - fip->nfnfields++; + i = fip->nfnfields++; } /* Create a new member function field and chain it to the field list @@ -6303,9 +6386,19 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, /* Fill in the member function field info. */ fnp = &new_fnfield->fnfield; - /* The name is already allocated along with this objfile, so we don't - need to duplicate it for the type. */ - fnp->physname = physname ? physname : ""; + + /* Delay processing of the physname until later. */ + if (cu->language == language_cplus || cu->language == language_java) + { + add_to_method_list (type, i, flp->length - 1, fieldname, + die, cu); + } + else + { + char *physname = (char *) dwarf2_physname (fieldname, die, cu); + fnp->physname = physname ? physname : ""; + } + fnp->type = alloc_type (objfile); this_type = read_type_die (die, cu); if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) @@ -6331,7 +6424,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, } else complaint (&symfile_complaints, _("member function type missing for '%s'"), - physname); + dwarf2_full_name (fieldname, die, cu)); /* Get fcontext from DW_AT_containing_type if present. */ if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) @@ -6579,7 +6672,14 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) if (cu->language == language_cplus || cu->language == language_java) { - TYPE_TAG_NAME (type) = (char *) dwarf2_full_name (name, die, cu); + char *full_name = (char *) dwarf2_full_name (name, die, cu); + + /* dwarf2_full_name might have already finished building the DIE's + type. If so, there is no need to continue. */ + if (get_die_type (die, cu) != NULL) + return get_die_type (die, cu); + + TYPE_TAG_NAME (type) = full_name; if (die->tag == DW_TAG_structure_type || die->tag == DW_TAG_class_type) TYPE_NAME (type) = TYPE_TAG_NAME (type); |