This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [patch] DWARF-3+ DW_AT_accessibility defaults #2 (GCC PR debug/45124)
On Tue, 22 Mar 2011 19:16:20 +0100, Jan Kratochvil wrote:
> If GCC 4.6.0 GA still will not produce DW_AT_producer for DW_TAG_type_unit
> there will be no way to distinguish what does DW_TAG_type_unit assume as
> a default for DW_AT_accessibility.
which has happened now with 4.6.0 GA.
Posted now:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48229#c5
# It cannot work as GDB often looks up the type without any referrer from
# DW_TAG_compile_unit, such as during the `ptype' GDB command. A draft patch
# thus has many regressions such as:
# -PASS: gdb.base/nofield.exp: ptype struct not_empty
# +FAIL: gdb.base/nofield.exp: ptype struct not_empty (GDB internal error)
#
# This means GDB will have to start full read (like -readnow) of CUs till it
# finds some CU referencing the specific type to find its DW_AT_producer. During
# scan of .debug_info for GDB partial symbols GDB currently skips over subtrees
# of DIEs which reference the type signature for performance reasons, it no
# longer can.
#
# With .gdb_index there is no GDB partial symbols scan but .gdb_index also
# indexes types by their name and there is no referrer ever seen during the
# `ptype' GDB command.
#
# So it means performance regression for non-.gdb_index case and a possible new
# extension/version of .gdb_index to handle it.
So any solution is not easy now. While playing with it one should have:
[patch] Fix -readnow for -gdwarf-4 unused type units
http://sourceware.org/ml/gdb-patches/2011-03/msg01119.html
Thanks,
Jan
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -446,6 +446,11 @@ struct dwarf2_per_cu_data
/* Data needed by the "quick" functions. */
struct dwarf2_per_cu_quick_data *quick;
} v;
+
+ /* Track the .debug_info CUs referring to .debug_types CUs, even
+ transitively. If unknown it is NULL, otherwise it points to
+ a .debug_info CU. */
+ struct dwarf2_per_cu_data *referrer;
};
/* Entry in the signatured_types hash table. */
@@ -2446,8 +2451,22 @@ dw2_expand_all_symtabs (struct objfile *objfile)
dw2_setup (objfile);
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_comp_units); ++i)
+ /* N_TYPE_COMP_UNITS - .debug_types CUs - do not have to be read in as each
+ such PER_CU belongs into one of these cases:
+ (1) per_cu->referrer == NULL
+ It is an unused DW_TAG_type_unit which no referrers. Such unit
+ cannot be read-in even just for a verification by OBJF_READNOW as
+ producer_is_gxx_lt_4_6 would not know how to read it.
+ (2) per_cu->referrer->cu == NULL
+ This DW_TAG_type_unit has been already read it before as a dependency
+ for some DW_TAG_compile_unit. producer_is_gxx_lt_4_6 would no longer
+ know how to read it with DW_TAG_compile_unit no longer available.
+ And also:
+ (3) per_cu->referrer->cu != NULL
+ We can read this DW_TAG_type_unit but it would be read in the second
+ time, there is no need to do so. */
+
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
@@ -6216,6 +6235,83 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
}
}
+/* Check for GCC PR debug/45124 fix which is not present in any G++ version up
+ to 4.5.any while it is present already in G++ 4.6.0 - the PR has been fixed
+ during 4.6.0 experimental. */
+
+static int
+producer_is_gxx_lt_4_6 (struct dwarf2_cu *cu)
+{
+ int major, minor;
+
+ if (cu->producer == NULL && cu->per_cu->from_debug_types)
+ {
+ struct dwarf2_per_cu_data *referrer;
+
+ /* We may get to a .debug_types CU only through a pointer from
+ a .debug_info CU. .debug_types CUs without such pointer are skipped
+ in dw2_expand_all_symtabs. */
+ referrer = cu->per_cu->referrer;
+ gdb_assert (referrer != NULL);
+
+ /* On a second and further referrer the first referrer stored in
+ referrer may have its CU already freed. But that time
+ DEBUG_TYPES_TYPE_HASH is used to look up the type and the
+ .debug_types CU is not read in the second time at all. */
+ gdb_assert (referrer->cu != NULL);
+
+ cu = referrer->cu;
+ }
+
+ if (cu->producer == NULL)
+ {
+ /* For unknown compilers expect their behavior is DWARF version
+ compliant. */
+
+ return 0;
+ }
+
+ /* Whitespaces are ignored in both PRODUCER and the format string. */
+ if (sscanf (cu->producer, "GNU C++ %d.%d", &major, &minor) != 2)
+ {
+ /* For non-GCC compilers expect their behavior is DWARF version
+ compliant. */
+
+ return 0;
+ }
+
+ return major < 4 || (major == 4 && minor < 6);
+}
+
+/* Return the default accessibility type if it is not overriden by
+ DW_AT_accessibility. */
+
+static enum dwarf_access_attribute
+dwarf2_default_access_attribute (struct die_info *die, struct dwarf2_cu *cu)
+{
+ if (cu->header.version < 3 || producer_is_gxx_lt_4_6 (cu))
+ {
+ /* The default DWARF 2 accessibility for members is public, the default
+ accessibility for inheritance is private. */
+
+ if (die->tag != DW_TAG_inheritance)
+ return DW_ACCESS_public;
+ else
+ return DW_ACCESS_private;
+ }
+ else
+ {
+ /* DWARF 3+ defines the default accessibility a different way. The same
+ rules apply now for DW_TAG_inheritance as for the members and it only
+ depends on the container kind. */
+
+ if (die->parent->tag == DW_TAG_class_type)
+ return DW_ACCESS_private;
+ else
+ return DW_ACCESS_public;
+ }
+}
+
/* Add an aggregate field to the field list. */
static void
@@ -6246,23 +6342,19 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
}
fip->nfields++;
- /* Handle accessibility and virtuality of field.
- The default accessibility for members is public, the default
- accessibility for inheritance is private. */
- if (die->tag != DW_TAG_inheritance)
- new_field->accessibility = DW_ACCESS_public;
- else
- new_field->accessibility = DW_ACCESS_private;
- new_field->virtuality = DW_VIRTUALITY_none;
-
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
new_field->accessibility = DW_UNSND (attr);
+ else
+ new_field->accessibility = dwarf2_default_access_attribute (die, cu);
if (new_field->accessibility != DW_ACCESS_public)
fip->non_public_fields = 1;
+
attr = dwarf2_attr (die, DW_AT_virtuality, cu);
if (attr)
new_field->virtuality = DW_UNSND (attr);
+ else
+ new_field->virtuality = DW_VIRTUALITY_none;
fp = &new_field->field;
@@ -6578,6 +6670,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
char *fieldname;
struct nextfnfield *new_fnfield;
struct type *this_type;
+ enum dwarf_access_attribute accessibility;
if (cu->language == language_ada)
error (_("unexpected member function in Ada type"));
@@ -6676,16 +6769,17 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
/* Get accessibility. */
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
+ accessibility = DW_UNSND (attr);
+ else
+ accessibility = dwarf2_default_access_attribute (die, cu);
+ switch (accessibility)
{
- switch (DW_UNSND (attr))
- {
- case DW_ACCESS_private:
- fnp->is_private = 1;
- break;
- case DW_ACCESS_protected:
- fnp->is_protected = 1;
- break;
- }
+ case DW_ACCESS_private:
+ fnp->is_private = 1;
+ break;
+ case DW_ACCESS_protected:
+ fnp->is_protected = 1;
+ break;
}
/* Check for artificial methods. */
@@ -13254,6 +13348,17 @@ static int
maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
struct dwarf2_per_cu_data *per_cu)
{
+ /* Try to fill-in referrer for .debug_types CUs. While
+ THIS_CU->CU may become NULL soon it should be already processed by
+ producer_is_gxx_lt_4_6 that time. */
+ if (per_cu->from_debug_types && per_cu->referrer == NULL)
+ {
+ if (!this_cu->per_cu->from_debug_types)
+ per_cu->referrer = this_cu->per_cu;
+ else
+ per_cu->referrer = this_cu->per_cu->referrer;
+ }
+
/* We may arrive here during partial symbol reading, if we need full
DIEs to process an unusual case (e.g. template arguments). Do
not queue PER_CU, just tell our caller to load its DIEs. */