summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2004-02-22 23:04:57 +0000
committerDaniel Jacobowitz <dan@debian.org>2004-02-22 23:04:57 +0000
commit2a25b749add8be38fa7b1cc17f66d5652173587b (patch)
tree155b176839bb7757d3b1465aa263b4fe6ebbdbb2
parent552562ed0fcd71cd9c8a58f7644b4e7729d4b61f (diff)
downloadgdb-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.intercu25
-rw-r--r--gdb/dwarf2read.c138
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;