diff options
author | Daniel Jacobowitz <dan@debian.org> | 2004-02-22 23:04:57 +0000 |
---|---|---|
committer | Daniel Jacobowitz <dan@debian.org> | 2004-02-22 23:04:57 +0000 |
commit | 2a25b749add8be38fa7b1cc17f66d5652173587b (patch) | |
tree | 155b176839bb7757d3b1465aa263b4fe6ebbdbb2 | |
parent | 552562ed0fcd71cd9c8a58f7644b4e7729d4b61f (diff) | |
download | gdb-2a25b749add8be38fa7b1cc17f66d5652173587b.tar.gz |
* dwarf2read.c (dwarf2_attr_with_cu): New function, renamed
from dwarf2_attr. Also return the compilation unit associated
with the attribute if we have followed a reference. Complain
if we return a reference attribute and the caller does not want
the target compilation unit.
(dwarf2_attr): Call dwarf2_attr_with_cu.
(die_specification, dwarf2_extension): Also return a compilation
unit.
(follow_die_ref): Take attribute and compilation unit arguments.
Call dwarf2_get_ref_die_offset. Also return the target
compilation unit.
(read_func_scope, read_structure_scope): Update calls to
die_specification. Use the result.
(read_namespace): Update call to dwarf2_extension.
(namespace_name): Likewise. Use the result.
(new_symbol): Call dwarf2_attr_with_cu to check for DIE type.
(die_type): Likewise. Update call to follow_die_ref. Use the
results.
(dwarf2_add_member_fn, read_structure_scope): Likewise for
DW_AT_containing_type.
(die_containing_type): Likewise.
(die_is_declaration): Likewise for DW_AT_specification.
-rw-r--r-- | gdb/ChangeLog.intercu | 25 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 138 |
2 files changed, 119 insertions, 44 deletions
diff --git a/gdb/ChangeLog.intercu b/gdb/ChangeLog.intercu index 8dffa9d911e..f2eaf24af18 100644 --- a/gdb/ChangeLog.intercu +++ b/gdb/ChangeLog.intercu @@ -1,5 +1,30 @@ 2004-02-22 Daniel Jacobowitz <drow@mvista.com> + * dwarf2read.c (dwarf2_attr_with_cu): New function, renamed + from dwarf2_attr. Also return the compilation unit associated + with the attribute if we have followed a reference. Complain + if we return a reference attribute and the caller does not want + the target compilation unit. + (dwarf2_attr): Call dwarf2_attr_with_cu. + (die_specification, dwarf2_extension): Also return a compilation + unit. + (follow_die_ref): Take attribute and compilation unit arguments. + Call dwarf2_get_ref_die_offset. Also return the target + compilation unit. + (read_func_scope, read_structure_scope): Update calls to + die_specification. Use the result. + (read_namespace): Update call to dwarf2_extension. + (namespace_name): Likewise. Use the result. + (new_symbol): Call dwarf2_attr_with_cu to check for DIE type. + (die_type): Likewise. Update call to follow_die_ref. Use the + results. + (dwarf2_add_member_fn, read_structure_scope): Likewise for + DW_AT_containing_type. + (die_containing_type): Likewise. + (die_is_declaration): Likewise for DW_AT_specification. + +2004-02-22 Daniel Jacobowitz <drow@mvista.com> + * dwarf2read.c (MAX_CACHE_AGE): Define. (struct dwarf2_cu): Add last_used counter. (free_comp_units_worker): New function, based on diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 5da07cdd4e4..332001d5119 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -776,10 +776,16 @@ static void set_cu_language (unsigned int, struct dwarf2_cu *); static struct attribute *dwarf2_attr (struct die_info *, unsigned int, struct dwarf2_cu *); +static struct attribute *dwarf2_attr_with_cu (struct die_info *, + unsigned int, + struct dwarf2_cu *, + struct dwarf2_cu **); + static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu); static struct die_info *die_specification (struct die_info *die, - struct dwarf2_cu *); + struct dwarf2_cu *, + struct dwarf2_cu **); static void free_line_header (struct line_header *lh); @@ -910,7 +916,8 @@ static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *); static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *); static struct die_info *dwarf2_extension (struct die_info *die, - struct dwarf2_cu *); + struct dwarf2_cu *, + struct dwarf2_cu **); static char *dwarf_tag_name (unsigned int); @@ -945,7 +952,9 @@ static unsigned int dwarf2_get_ref_die_offset (struct attribute *, static int dwarf2_get_attr_constant_value (struct attribute *, int); -static struct die_info *follow_die_ref (unsigned int); +static struct die_info *follow_die_ref (struct attribute *, + struct dwarf2_cu *, + struct dwarf2_cu **); static struct type *dwarf2_fundamental_type (struct objfile *, int, struct dwarf2_cu *); @@ -2625,7 +2634,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) if (cu->language == language_cplus) { - struct die_info *spec_die = die_specification (die, cu); + struct dwarf2_cu *spec_cu; + struct die_info *spec_die = die_specification (die, cu, &spec_cu); /* NOTE: carlton/2004-01-23: We have to be careful in the presence of DW_AT_specification. For example, with GCC 3.4, @@ -2651,7 +2661,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) if (spec_die != NULL) { - char *specification_prefix = determine_prefix (spec_die, cu); + char *specification_prefix = determine_prefix (spec_die, spec_cu); processing_current_prefix = specification_prefix; back_to = make_cleanup (xfree, specification_prefix); } @@ -3258,6 +3268,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, char *fieldname; char *physname; struct nextfnfield *new_fnfield; + struct dwarf2_cu *spec_cu; /* Get name of member function. */ attr = dwarf2_attr (die, DW_AT_name, cu); @@ -3337,7 +3348,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, physname); /* Get fcontext from DW_AT_containing_type if present. */ - if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) + if (dwarf2_attr_with_cu (die, DW_AT_containing_type, cu, &spec_cu) != NULL) fnp->fcontext = die_containing_type (die, cu); /* dwarf2 doesn't have stubbed physical names, so the setting of is_const @@ -3458,11 +3469,13 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu) if (cu->language == language_cplus) { - struct die_info *spec_die = die_specification (die, cu); + struct dwarf2_cu *spec_cu; + struct die_info *spec_die = die_specification (die, cu, &spec_cu); if (spec_die != NULL) { - char *specification_prefix = determine_prefix (spec_die, cu); + char *specification_prefix = determine_prefix (spec_die, + spec_cu); processing_current_prefix = specification_prefix; back_to = make_cleanup (xfree, specification_prefix); } @@ -3601,13 +3614,16 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu) dwarf2_attach_fields_to_type (&fi, type, cu); if (fi.nfnfields) { + struct dwarf2_cu *spec_cu; + dwarf2_attach_fn_fields_to_type (&fi, type, cu); /* Get the type which refers to the base class (possibly this class itself) which contains the vtable pointer for the current class from the DW_AT_containing_type attribute. */ - if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) + if (dwarf2_attr_with_cu (die, DW_AT_containing_type, + cu, &spec_cu) != NULL) { struct type *t = die_containing_type (die, cu); @@ -3913,6 +3929,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) const char *name; int is_anonymous; struct die_info *current_die; + struct dwarf2_cu *spec_cu; name = namespace_name (die, &is_anonymous, cu); @@ -3939,7 +3956,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) before. Also, add a using directive if it's an anonymous namespace. */ - if (dwarf2_extension (die, cu) == NULL) + if (dwarf2_extension (die, cu, &spec_cu) == NULL) { struct type *type; @@ -3981,14 +3998,15 @@ namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu) { struct die_info *current_die; const char *name = NULL; + struct dwarf2_cu *spec_cu; /* Loop through the extensions until we find a name. */ - for (current_die = die; + for (current_die = die, spec_cu = cu; current_die != NULL; - current_die = dwarf2_extension (die, cu)) + current_die = dwarf2_extension (die, spec_cu, &spec_cu)) { - name = dwarf2_name (current_die, cu); + name = dwarf2_name (current_die, spec_cu); if (name != NULL) break; } @@ -5679,7 +5697,8 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu) /* Return the named attribute or NULL if not there. */ static struct attribute * -dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu) +dwarf2_attr_with_cu (struct die_info *die, unsigned int name, + struct dwarf2_cu *cu, struct dwarf2_cu **spec_cu) { unsigned int i; struct attribute *spec = NULL; @@ -5688,6 +5707,20 @@ dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu) { if (die->attrs[i].name == name) { + if (spec_cu == NULL + && (die->attrs[i].form == DW_FORM_ref_addr + || die->attrs[i].form == DW_FORM_ref1 + || die->attrs[i].form == DW_FORM_ref2 + || die->attrs[i].form == DW_FORM_ref4 + || die->attrs[i].form == DW_FORM_ref8 + || die->attrs[i].form == DW_FORM_ref_udata)) + internal_error (__FILE__, __LINE__, + "attempt to follow a dwarf2 DIE reference " + "discards compilation unit"); + + if (spec_cu != NULL) + *spec_cu = cu; + return &die->attrs[i]; } if (die->attrs[i].name == DW_AT_specification @@ -5696,35 +5729,45 @@ dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu) } if (spec) { - struct die_info *ref_die = - follow_die_ref (dwarf2_get_ref_die_offset (spec, cu)); + struct dwarf2_cu *ref_cu; + struct die_info *ref_die = follow_die_ref (spec, cu, &ref_cu); - if (ref_die) - return dwarf2_attr (ref_die, name, cu); + return dwarf2_attr_with_cu (ref_die, name, ref_cu, spec_cu); } return NULL; } +/* Return the named attribute or NULL if not there. */ + +static struct attribute * +dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu) +{ + return dwarf2_attr_with_cu (die, name, cu, NULL); +} + static int die_is_declaration (struct die_info *die, struct dwarf2_cu *cu) { + struct dwarf2_cu *spec_cu; return (dwarf2_attr (die, DW_AT_declaration, cu) - && ! dwarf2_attr (die, DW_AT_specification, cu)); + && ! dwarf2_attr_with_cu (die, DW_AT_specification, cu, &spec_cu)); } /* Return the die giving the specification for DIE, if there is one. */ static struct die_info * -die_specification (struct die_info *die, struct dwarf2_cu *cu) +die_specification (struct die_info *die, struct dwarf2_cu *cu, + struct dwarf2_cu **spec_cu) { - struct attribute *spec_attr = dwarf2_attr (die, DW_AT_specification, cu); + struct attribute *spec_attr + = dwarf2_attr_with_cu (die, DW_AT_specification, cu, spec_cu); if (spec_attr == NULL) return NULL; else - return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr, cu)); + return follow_die_ref (spec_attr, *spec_cu, spec_cu); } /* Free the line_header structure *LH, and any arrays and strings it @@ -6334,6 +6377,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) } else { + struct dwarf2_cu *spec_cu; + /* We do not know the address of this symbol. If it is an external symbol and we have type information for it, enter the symbol as a LOC_UNRESOLVED symbol. @@ -6342,7 +6387,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) referenced. */ attr2 = dwarf2_attr (die, DW_AT_external, cu); if (attr2 && (DW_UNSND (attr2) != 0) - && dwarf2_attr (die, DW_AT_type, cu) != NULL) + && dwarf2_attr_with_cu (die, DW_AT_type, + cu, &spec_cu) != NULL) { SYMBOL_CLASS (sym) = LOC_UNRESOLVED; add_symbol_to_list (sym, &global_symbols); @@ -6608,9 +6654,9 @@ die_type (struct die_info *die, struct dwarf2_cu *cu) struct type *type; struct attribute *type_attr; struct die_info *type_die; - unsigned int ref; + struct dwarf2_cu *spec_cu; - type_attr = dwarf2_attr (die, DW_AT_type, cu); + type_attr = dwarf2_attr_with_cu (die, DW_AT_type, cu, &spec_cu); if (!type_attr) { /* A missing DW_AT_type represents a void type. */ @@ -6618,16 +6664,16 @@ die_type (struct die_info *die, struct dwarf2_cu *cu) } else { - ref = dwarf2_get_ref_die_offset (type_attr, cu); - type_die = follow_die_ref (ref); + type_die = follow_die_ref (type_attr, spec_cu, &spec_cu); if (!type_die) { - error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", - ref, cu->objfile->name); + error ("Dwarf Error: Cannot find referent from DIE " + "at offset %d [in module %s]", + die->offset, cu->objfile->name); return NULL; } } - type = tag_type_to_type (type_die, cu); + type = tag_type_to_type (type_die, spec_cu); if (!type) { dump_die (type_die); @@ -6646,20 +6692,19 @@ die_containing_type (struct die_info *die, struct dwarf2_cu *cu) struct type *type = NULL; struct attribute *type_attr; struct die_info *type_die = NULL; - unsigned int ref; + struct dwarf2_cu *spec_cu; - type_attr = dwarf2_attr (die, DW_AT_containing_type, cu); + type_attr = dwarf2_attr_with_cu (die, DW_AT_containing_type, cu, &spec_cu); if (type_attr) { - ref = dwarf2_get_ref_die_offset (type_attr, cu); - type_die = follow_die_ref (ref); + type_die = follow_die_ref (type_attr, spec_cu, &spec_cu); if (!type_die) { - error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref, - cu->objfile->name); + error ("Dwarf Error: Cannot find referent from DIE at offset %d " + "[in module %s]", die->offset, cu->objfile->name); return NULL; } - type = tag_type_to_type (type_die, cu); + type = tag_type_to_type (type_die, spec_cu); } if (!type) { @@ -7043,21 +7088,21 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) is none. */ static struct die_info * -dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu) +dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu, + struct dwarf2_cu **spec_cu) { struct attribute *attr; struct die_info *extension_die; - unsigned int ref; - attr = dwarf2_attr (die, DW_AT_extension, cu); + attr = dwarf2_attr_with_cu (die, DW_AT_extension, cu, spec_cu); if (attr == NULL) return NULL; - ref = dwarf2_get_ref_die_offset (attr, cu); - extension_die = follow_die_ref (ref); + extension_die = follow_die_ref (attr, *spec_cu, spec_cu); if (!extension_die) { - error ("Dwarf Error: Cannot find referent at offset %d.", ref); + error ("Dwarf Error: Cannot find referent from DIE at offset %d.", + die->offset); } return extension_die; @@ -8013,17 +8058,22 @@ dwarf2_get_attr_constant_value (struct attribute *attr, int default_value) } static struct die_info * -follow_die_ref (unsigned int offset) +follow_die_ref (struct attribute *attr, struct dwarf2_cu *cu, + struct dwarf2_cu **spec_cu) { struct die_info *die; + unsigned int offset; int h; + offset = dwarf2_get_ref_die_offset (attr, cu); + h = (offset % REF_HASH_SIZE); die = die_ref_table[h]; while (die) { if (die->offset == offset) { + *spec_cu = cu; return die; } die = die->next_ref; |