[RFA] template names with arguments out of DW_AT_name

Pedro Alves
2010-07-30T19:18:00Z

Daniel says:

RVCT uses a struct DIE with name "foo" and a DW_AT_template_type_parameter
child DIE with a reference to type "T", where GCC would just have a struct
DIE with name "foo<T>". When we see this, we have to read in the child
DIEs using a less compact structure; generate full type information, though
not symbols; and reconstruct the full name of the type.

This fixes around 150 template related FAILs with RealView.

Also tested on x86_64-linux, ubuntu's gcc 4.4.3 without regressions.

Okay to apply?

I needed to export dwarf2_evaluate_loc_desc, due to recent
change in dwarf2_const_value to rewrite a location expression
in place. The patch splits the guts out of
dwarf2_const_value into a function that extracts the data
of an attribute into a `long', a gdb_byte array or (since recently)
a location expression, and into couple of different contexts that
either create a `struct value' or fill a struct symbol with that
extracted attribute data.

--
Pedro Alves

2010-07-30 Daniel Jacobowitz <dan@codesourcery.com>
Pedro Alves <pedro@codesourcery.com>

gdb/
* dwarf2read.c: Include "c-lang.h" and "valprint.h".
(reading_partial_symbols): New.
(struct partial_die_info) <has_template_arguments>: New field.
<num_attrs>: Change type to unsigned char.
<building_fullname>: New field.
(dwarf2_build_psymtabs_hard): Set reading_partial_symbols. Only
allocate a CU if we don't have one already. Add a cleanup for the
CU.
(partial_die_full_name): Handle template arguments not in
DW_AT_name.
(dwarf2_psymtab_to_symtab): Clear reading_partial_symbols.
(load_full_comp_unit): Only allocate a CU if we don't have one
already.
(do_ui_file_peek_last): New.
(dwarf2_compute_name): Handle template parameters not in
DW_AT_name.
(read_comp_unit): Read and free abbrevs if not read yet.
(load_partial_dies): Handle template arguments not in DW_AT_name.
(find_partial_die): If we have a CU, but no a partial dies yet,
also read in the CU.
(dwarf2_const_value_attr): New, abstracted out from
dwarf2_const_value.
(dwarf2_const_value, dwarf2_const_value_data): Adjust to use
dwarf2_const_value_attr.
(determine_prefix): Detect and break loops created by RCVT's debug
info.
(maybe_queue_comp_unit): Bail out early if reading partial
symbols.
(follow_die_offset): Load full CU if we have no dies.
* dwarf2loc.c (dwarf2_evaluate_loc_desc): Make public.
* dwarf2loc.h (dwarf2_evaluate_loc_desc): Declare.

---
gdb/dwarf2loc.c | 2
gdb/dwarf2loc.h | 10
gdb/dwarf2read.c | 605 ++++++++++++++++++++++++++++++++++++++++++++-----------
3 files changed, 498 insertions(+), 119 deletions(-)

Index: src/gdb/dwarf2read.c
===================================================================
--- src.orig/gdb/dwarf2read.c 2010-07-30 00:39:47.000000000 +0100
+++ src/gdb/dwarf2read.c 2010-07-30 18:58:21.000000000 +0100
@@ -55,6 +55,8 @@
#include "gdb_stat.h"
#include "completer.h"
#include "vec.h"
+#include "c-lang.h"
+#include "valprint.h"

#include <fcntl.h>
#include "gdb_string.h"
@@ -211,6 +213,10 @@ struct dwarf2_per_objfile

static struct dwarf2_per_objfile *dwarf2_per_objfile;

+/* Set during partial symbol reading, to prevent queueing of full
+ symbols. */
+static int reading_partial_symbols;
+
/* names of the debugging sections */

/* Note that if the debugging section has been compressed, it might
@@ -542,6 +548,9 @@ struct partial_die_info
/* Flag set if the DIE has a byte_size attribute. */
unsigned int has_byte_size : 1;

+ /* Flag set if any of the DIE's children are template arguments. */
+ unsigned int has_template_arguments : 1;
+
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes a default name for unnamed DIEs. */
char *name;
@@ -619,7 +628,11 @@ struct die_info
ENUM_BITFIELD(dwarf_tag) tag : 16;

/* Number of attributes */
- unsigned short num_attrs;
+ unsigned char num_attrs;
+
+ /* True if we're presently building the full type name for the
+ type derived from this DIE. */
+ unsigned char building_fullname : 1;

/* Abbrev number */
unsigned int abbrev;
@@ -979,9 +992,13 @@ static struct symbol *new_symbol_full (s
static void dwarf2_const_value (struct attribute *, struct symbol *,
struct dwarf2_cu *);

-static void dwarf2_const_value_data (struct attribute *attr,
- struct symbol *sym,
- int bits);
+static void dwarf2_const_value_attr (struct attribute *attr,
+ struct type *type,
+ const char *name,
+ struct obstack *obstack,
+ struct dwarf2_cu *cu, long *value,
+ gdb_byte **bytes,
+ struct dwarf2_locexpr_baton **baton);

static struct type *die_type (struct die_info *, struct dwarf2_cu *);

@@ -1091,6 +1108,10 @@ static char *dwarf2_canonicalize_name (c

static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);

+static const char *dwarf2_full_name (char *name,
+ struct die_info *die,
+ struct dwarf2_cu *cu);
+
static struct die_info *dwarf2_extension (struct die_info *die,
struct dwarf2_cu **);

@@ -3161,6 +3182,8 @@ dwarf2_build_psymtabs_hard (struct objfi
struct cleanup *back_to, *addrmap_cleanup;
struct obstack temp_obstack;

+ reading_partial_symbols = 1;
+
dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
info_ptr = dwarf2_per_objfile->info.buffer;

@@ -3224,10 +3247,11 @@ load_partial_comp_unit (struct dwarf2_pe
gdb_byte *info_ptr, *beg_of_comp_unit;
struct die_info *comp_unit_die;
struct dwarf2_cu *cu;
- struct cleanup *back_to;
+ struct cleanup *free_abbrevs_cleanup, *free_cu_cleanup;
struct attribute *attr;
int has_children;
struct die_reader_specs reader_specs;
+ int read_cu = 0;

gdb_assert (! this_cu->from_debug_types);

@@ -3235,27 +3259,43 @@ load_partial_comp_unit (struct dwarf2_pe
info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
beg_of_comp_unit = info_ptr;

- cu = alloc_one_comp_unit (objfile);
+ if (this_cu->cu == NULL)
+ {
+ cu = alloc_one_comp_unit (objfile);

- /* ??? Missing cleanup for CU? */
+ read_cu = 1;

- /* Link this compilation unit into the compilation unit tree. */
- this_cu->cu = cu;
- cu->per_cu = this_cu;
- cu->type_hash = this_cu->type_hash;
-
- info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr,
- dwarf2_per_objfile->info.buffer,
- dwarf2_per_objfile->info.size,
- abfd);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);

- /* Complete the cu_header. */
- cu->header.offset = this_cu->offset;
- cu->header.first_die_offset = info_ptr - beg_of_comp_unit;
+ info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr,
+ dwarf2_per_objfile->info.buffer,
+ dwarf2_per_objfile->info.size,
+ abfd);
+
+ /* Complete the cu_header. */
+ cu->header.offset = this_cu->offset;
+ cu->header.first_die_offset = info_ptr - beg_of_comp_unit;
+
+ /* Link this compilation unit into the compilation unit tree. */
+ this_cu->cu = cu;
+ cu->per_cu = this_cu;
+ cu->type_hash = this_cu->type_hash;
+
+ /* Link this CU into read_in_chain. */
+ this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = this_cu;
+ }
+ else
+ {
+ cu = this_cu->cu;
+ info_ptr += cu->header.first_die_offset;
+ }

/* Read the abbrevs for this compilation unit into a table. */
+ gdb_assert (cu->dwarf2_abbrevs == NULL);
dwarf2_read_abbrevs (abfd, cu);
- back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+ free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu);

/* Read the compilation unit die. */
init_cu_die_reader (&reader_specs, cu);
@@ -3275,7 +3315,14 @@ load_partial_comp_unit (struct dwarf2_pe
if (has_children)
load_partial_dies (abfd, dwarf2_per_objfile->info.buffer, info_ptr, 0, cu);

- do_cleanups (back_to);
+ do_cleanups (free_abbrevs_cleanup);
+
+ if (read_cu)
+ {
+ /* We've successfully allocated this compilation unit. Let our
+ caller clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
+ }
}

/* Create a list of all compilation units in OBJFILE. We do this only
@@ -3521,6 +3568,29 @@ partial_die_full_name (struct partial_di
{
char *parent_scope;

+ /* If this is a template instantiation, we can not work out the
+ template arguments from partial DIEs. So, unfortunately, we have
+ to go through the full DIEs. At least any work we do building
+ types here will be reused if full symbols are loaded later. */
+ if (pdi->has_template_arguments)
+ {
+ fixup_partial_die (pdi, cu);
+
+ if (pdi->name != NULL && strchr (pdi->name, '<') == NULL)
+ {
+ struct die_info *die;
+ struct attribute attr;
+ struct dwarf2_cu *ref_cu = cu;
+
+ attr.name = 0;
+ attr.form = DW_FORM_ref_addr;
+ attr.u.addr = pdi->offset;
+ die = follow_die_ref (NULL, &attr, &ref_cu);
+
+ return xstrdup (dwarf2_full_name (NULL, die, ref_cu));
+ }
+ }
+
parent_scope = partial_die_parent_scope (pdi, cu);
if (parent_scope == NULL)
return NULL;
@@ -4063,6 +4133,8 @@ dwarf2_psymtab_to_symtab (struct partial
= dpo_backlink->has_section_at_zero;
}

+ reading_partial_symbols = 0;
+
psymtab_to_symtab_1 (pst);

/* Finish up the debug error message. */
@@ -4194,8 +4266,9 @@ load_full_comp_unit (struct dwarf2_per_c
struct dwarf2_cu *cu;
unsigned int offset;
gdb_byte *info_ptr, *beg_of_comp_unit;
- struct cleanup *back_to, *free_cu_cleanup;
+ struct cleanup *free_abbrevs_cleanup, *free_cu_cleanup;
struct attribute *attr;
+ int read_cu = 0;

gdb_assert (! per_cu->from_debug_types);

@@ -4206,26 +4279,40 @@ load_full_comp_unit (struct dwarf2_per_c
info_ptr = dwarf2_per_objfile->info.buffer + offset;
beg_of_comp_unit = info_ptr;

- cu = alloc_one_comp_unit (objfile);
+ if (per_cu->cu == NULL)
+ {
+ cu = alloc_one_comp_unit (objfile);

- /* If an error occurs while loading, release our storage. */
- free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+ read_cu = 1;

- /* Read in the comp_unit header. */
- info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);

- /* Complete the cu_header. */
- cu->header.offset = offset;
- cu->header.first_die_offset = info_ptr - beg_of_comp_unit;
+ /* Read in the comp_unit header. */
+ info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd);

- /* Read the abbrevs for this compilation unit. */
- dwarf2_read_abbrevs (abfd, cu);
- back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+ /* Complete the cu_header. */
+ cu->header.offset = offset;
+ cu->header.first_die_offset = info_ptr - beg_of_comp_unit;

- /* Link this compilation unit into the compilation unit tree. */
- per_cu->cu = cu;
- cu->per_cu = per_cu;
- cu->type_hash = per_cu->type_hash;
+ /* Read the abbrevs for this compilation unit. */
+ dwarf2_read_abbrevs (abfd, cu);
+ free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu);
+
+ /* Link this compilation unit into the compilation unit tree. */
+ per_cu->cu = cu;
+ cu->per_cu = per_cu;
+ cu->type_hash = per_cu->type_hash;
+
+ /* Link this CU into read_in_chain. */
+ per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = per_cu;
+ }
+ else
+ {
+ cu = per_cu->cu;
+ info_ptr += cu->header.first_die_offset;
+ }

cu->dies = read_comp_unit (info_ptr, cu);

@@ -4245,15 +4332,14 @@ load_full_comp_unit (struct dwarf2_per_c
if (attr)
cu->producer = DW_STRING (attr);

- /* Link this CU into read_in_chain. */
- per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
- dwarf2_per_objfile->read_in_chain = per_cu;
-
- do_cleanups (back_to);
+ if (read_cu)
+ {
+ do_cleanups (free_abbrevs_cleanup);

- /* We've successfully allocated this compilation unit. Let our caller
- clean it up when finished with it. */
- discard_cleanups (free_cu_cleanup);
+ /* We've successfully allocated this compilation unit. Let our
+ caller clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
+ }
}

/* Generate full symbol information for PST and CU, whose DIEs have
@@ -4446,6 +4532,17 @@ die_needs_namespace (struct die_info *di
}
}

+/* Retrieve the last character from a mem_file. */
+
+static void
+do_ui_file_peek_last (void *object, const char *buffer, long length)
+{
+ char *last_char_p = (char *) object;
+
+ if (length > 0)
+ *last_char_p = buffer[length - 1];
+}
+
/* Compute the fully qualified name of DIE in CU. If PHYSNAME is nonzero,
compute the physname for the object, which include a method's
formal parameters (C++/Java) and return type (Java).
@@ -4505,6 +4602,129 @@ dwarf2_compute_name (char *name, struct
else
fputs_unfiltered (name ? name : "", buf);

+ /* Template parameters may be specified in the DIE's DW_AT_name, or
+ as children with DW_TAG_template_type_param or
+ DW_TAG_value_type_param. If the latter, add them to the name
+ here. If the name already has template parameters, then
+ skip this step; some versions of GCC emit both, and
+ it is more efficient to use the pre-computed name.
+
+ Something to keep in mind about this process: it is very
+ unlikely, or in some cases downright impossible, to produce
+ something that will match the mangled name of a function.
+ If the definition of the function has the same debug info,
+ we should be able to match up with it anyway. But fallbacks
+ using the minimal symbol, for instance to find a method
+ implemented in a stripped copy of libstdc++, will not work.
+ If we do not have debug info for the definition, we will have to
+ match them up some other way.
+
+ When we do name matching there is a related problem with function
+ templates; two instantiated function templates are allowed to
+ differ only by their return types, which we do not add here. */
+
+ if (cu->language == language_cplus && strchr (name, '<') == NULL)
+ {
+ struct attribute *attr;
+ struct die_info *child;
+ int first = 1;
+
+ die->building_fullname = 1;
+
+ for (child = die->child; child != NULL; child = child->sibling)
+ {
+ struct type *type;
+ long value;
+ gdb_byte *bytes;
+ struct dwarf2_locexpr_baton *baton;
+ struct value *v;
+
+ if (child->tag != DW_TAG_template_type_param
+ && child->tag != DW_TAG_template_value_param)
+ continue;
+
+ if (first)
+ {
+ fputs_unfiltered ("<", buf);
+ first = 0;
+ }
+ else
+ fputs_unfiltered (", ", buf);
+
+ attr = dwarf2_attr (child, DW_AT_type, cu);
+ if (attr == NULL)
+ {
+ complaint (&symfile_complaints,
+ _("template parameter missing DW_AT_type"));
+ fputs_unfiltered ("UNKNOWN_TYPE", buf);
+ continue;
+ }
+ type = die_type (child, cu);
+
+ if (child->tag == DW_TAG_template_type_param)
+ {
+ c_print_type (type, "", buf, -1, 0);
+ continue;
+ }
+
+ attr = dwarf2_attr (child, DW_AT_const_value, cu);
+ if (attr == NULL)
+ {
+ complaint (&symfile_complaints,
+ _("template parameter missing DW_AT_const_value"));
+ fputs_unfiltered ("UNKNOWN_VALUE", buf);
+ continue;
+ }
+
+ dwarf2_const_value_attr (attr, type, name,
+ &cu->comp_unit_obstack, cu,
+ &value, &bytes, &baton);
+
+ if (TYPE_NOSIGN (type))
+ /* GDB prints characters as NUMBER 'CHAR'. If that's
+ changed, this can use value_print instead. */
+ c_printchar (value, type, buf);
+ else
+ {
+ struct value_print_options opts;
+
+ if (baton != NULL)
+ v = dwarf2_evaluate_loc_desc (type, NULL,
+ baton->data,
+ baton->size,
+ baton->per_cu);
+ else if (bytes != NULL)
+ {
+ v = allocate_value (type);
+ memcpy (value_contents_writeable (v), bytes,
+ TYPE_LENGTH (type));
+ }
+ else
+ v = value_from_longest (type, value);
+
+ /* Specify decimal so that we do not depend on the radix. */
+ get_formatted_print_options (&opts, 'd');
+ value_print (v, buf, &opts);
+ release_value (v);
+ value_free (v);
+ }
+ }
+
+ die->building_fullname = 0;
+
+ if (!first)
+ {
+ /* Close the argument list, with a space if necessary
+ (nested templates). */
+ char last_char = '\0';
+ ui_file_put (buf, do_ui_file_peek_last, &last_char);
+ if (last_char == '>')
+ fputs_unfiltered (" >", buf);
+ else
+ fputs_unfiltered (">", buf);
+ }
+ }
+
/* For Java and C++ methods, append formal parameter type
information, if PHYSNAME. */

@@ -7752,6 +7972,16 @@ static struct die_info *
read_comp_unit (gdb_byte *info_ptr, struct dwarf2_cu *cu)
{
struct die_reader_specs reader_specs;
+ int read_abbrevs = 0;
+ struct cleanup *back_to;
+ struct die_info *die;
+
+ if (cu->dwarf2_abbrevs == NULL)
+ {
+ dwarf2_read_abbrevs (cu->objfile->obfd, cu);
+ back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+ read_abbrevs = 1;
+ }

gdb_assert (cu->die_hash == NULL);
cu->die_hash
@@ -7765,7 +7995,12 @@ read_comp_unit (gdb_byte *info_ptr, stru

init_cu_die_reader (&reader_specs, cu);

- return read_die_and_children (&reader_specs, info_ptr, &info_ptr, NULL);
+ die = read_die_and_children (&reader_specs, info_ptr, &info_ptr, NULL);
+
+ if (read_abbrevs)
+ do_cleanups (back_to);
+
+ return die;
}

/* Main entry point for reading a DIE and all children.
@@ -8147,6 +8382,35 @@ load_partial_dies (bfd *abfd, gdb_byte *
continue;
}

+ /* Check for template arguments. We never save these; if
+ they're seen, we just mark the parent, and go on our way. */
+ if (parent_die != NULL
+ && cu->language == language_cplus
+ && (abbrev->tag == DW_TAG_template_type_param
+ || abbrev->tag == DW_TAG_template_value_param))
+ {
+ parent_die->has_template_arguments = 1;
+
+ if (!load_all)
+ {
+ /* We don't need a partial DIE for the template argument. */
+ info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev,
+ cu);
+ continue;
+ }
+ }
+
+ /* We only recurse into subprograms looking for template arguments.
+ Skip their other children. */
+ if (!load_all
+ && cu->language == language_cplus
+ && parent_die != NULL
+ && parent_die->tag == DW_TAG_subprogram)
+ {
+ info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu);
+ continue;
+ }
+
/* Check whether this DIE is interesting enough to save. Normally
we would not be interested in members here, but there may be
later variables referencing them via DW_AT_specification (for
@@ -8280,8 +8544,11 @@ load_partial_dies (bfd *abfd, gdb_byte *

/* For some DIEs we want to follow their children (if any). For C
we have no reason to follow the children of structures; for other
- languages we have to, both so that we can get at method physnames
- to infer fully qualified class names, and for DW_AT_specification.
+ languages we have to, so that we can get at method physnames
+ to infer fully qualified class names, for DW_AT_specification,
+ and for C++ template arguments. For C++, we also look one level
+ inside functions to find template arguments (if the name of the
+ function does not already contain the template arguments).

For Ada, we need to scan the children of subprograms and lexical
blocks as well because Ada allows the definition of nested
@@ -8292,6 +8559,10 @@ load_partial_dies (bfd *abfd, gdb_byte *
|| last_die->tag == DW_TAG_namespace
|| last_die->tag == DW_TAG_module
|| last_die->tag == DW_TAG_enumeration_type
+ || (cu->language == language_cplus
+ && last_die->tag == DW_TAG_subprogram
+ && (last_die->name == NULL
+ || strchr (last_die->name, '<') == NULL))
|| (cu->language != language_c
&& (last_die->tag == DW_TAG_class_type
|| last_die->tag == DW_TAG_interface_type
@@ -8508,12 +8779,8 @@ find_partial_die (unsigned int offset, s

per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);

- if (per_cu->cu == NULL)
- {
- load_partial_comp_unit (per_cu, cu->objfile);
- per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
- dwarf2_per_objfile->read_in_chain = per_cu;
- }
+ if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
+ load_partial_comp_unit (per_cu, cu->objfile);

per_cu->cu->last_used = 0;
pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
@@ -10376,58 +10643,97 @@ new_symbol (struct die_info *die, struct
return new_symbol_full (die, type, cu, NULL);
}

-/* Copy constant value from an attribute to a symbol. */
+/* Given an attr with a DW_FORM_dataN value in host byte order,
+ zero-extend it as appropriate for the symbol's type. The DWARF
+ standard (v4) is not entirely clear about the meaning of using
+ DW_FORM_dataN for a constant with a signed type, where the type is
+ wider than the data. The conclusion of a discussion on the DWARF
+ list was that this is unspecified. We choose to always zero-extend
+ because that is the interpretation long in use by GCC. */

-static void
-dwarf2_const_value (struct attribute *attr, struct symbol *sym,
- struct dwarf2_cu *cu)
+static gdb_byte *
+dwarf2_const_value_data (struct attribute *attr, struct type *type,
+ const char *name, struct obstack *obstack,
+ struct dwarf2_cu *cu, long *value, int bits)
{
struct objfile *objfile = cu->objfile;
- struct comp_unit_head *cu_header = &cu->header;
enum bfd_endian byte_order = bfd_big_endian (objfile->obfd) ?
BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+ LONGEST l = DW_UNSND (attr);
+
+ if (bits < sizeof (*value) * 8)
+ {
+ l &= ((LONGEST) 1 << bits) - 1;
+ *value = l;
+ }
+ else if (bits == sizeof (*value) * 8)
+ *value = l;
+ else
+ {
+ gdb_byte *bytes = obstack_alloc (obstack, bits / 8);
+ store_unsigned_integer (bytes, bits / 8, byte_order, l);
+ return bytes;
+ }
+
+ return NULL;
+}
+
+/* Read a constant value from an attribute. Either set *VALUE, or if
+ the value does not fit in *VALUE, set *BYTES - either already
+ allocated on the objfile obstack, or newly allocated on OBSTACK,
+ or, set *BATON, if we translated the constant to a location
+ expression. */
+
+static void
+dwarf2_const_value_attr (struct attribute *attr, struct type *type,
+ const char *name, struct obstack *obstack,
+ struct dwarf2_cu *cu,
+ long *value, gdb_byte **bytes,
+ struct dwarf2_locexpr_baton **baton)
+{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
struct dwarf_block *blk;
+ enum bfd_endian byte_order = (bfd_big_endian (objfile->obfd) ?
+ BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE);
+
+ *value = 0;
+ *bytes = NULL;
+ *baton = NULL;

switch (attr->form)
{
case DW_FORM_addr:
{
- struct dwarf2_locexpr_baton *baton;
gdb_byte *data;

- if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
- dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym),
+ if (TYPE_LENGTH (type) != cu_header->addr_size)
+ dwarf2_const_value_length_mismatch_complaint (name,
cu_header->addr_size,
- TYPE_LENGTH (SYMBOL_TYPE
- (sym)));
+ TYPE_LENGTH (type));
/* Symbols of this form are reasonably rare, so we just
piggyback on the existing location code rather than writing
a new implementation of symbol_computed_ops. */
- baton = obstack_alloc (&objfile->objfile_obstack,
- sizeof (struct dwarf2_locexpr_baton));
- baton->per_cu = cu->per_cu;
- gdb_assert (baton->per_cu);
-
- baton->size = 2 + cu_header->addr_size;
- data = obstack_alloc (&objfile->objfile_obstack, baton->size);
- baton->data = data;
+ *baton = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct dwarf2_locexpr_baton));
+ (*baton)->per_cu = cu->per_cu;
+ gdb_assert ((*baton)->per_cu);
+
+ (*baton)->size = 2 + cu_header->addr_size;
+ data = obstack_alloc (&objfile->objfile_obstack, (*baton)->size);
+ (*baton)->data = data;

data[0] = DW_OP_addr;
store_unsigned_integer (&data[1], cu_header->addr_size,
byte_order, DW_ADDR (attr));
data[cu_header->addr_size + 1] = DW_OP_stack_value;
-
- SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
- SYMBOL_LOCATION_BATON (sym) = baton;
- SYMBOL_CLASS (sym) = LOC_COMPUTED;
}
break;
case DW_FORM_string:
case DW_FORM_strp:
- /* DW_STRING is already allocated on the obstack, point directly
- to it. */
- SYMBOL_VALUE_BYTES (sym) = (gdb_byte *) DW_STRING (attr);
- SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ /* DW_STRING is already allocated on the objfile obstack, point
+ directly to it. */
+ *bytes = (gdb_byte *) DW_STRING (attr);
break;
case DW_FORM_block1:
case DW_FORM_block2:
@@ -10435,15 +10741,10 @@ dwarf2_const_value (struct attribute *at
case DW_FORM_block:
case DW_FORM_exprloc:
blk = DW_BLOCK (attr);
- if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
- dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym),
- blk->size,
- TYPE_LENGTH (SYMBOL_TYPE
- (sym)));
- SYMBOL_VALUE_BYTES (sym) =
- obstack_alloc (&objfile->objfile_obstack, blk->size);
- memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
- SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ if (TYPE_LENGTH (type) != blk->size)
+ dwarf2_const_value_length_mismatch_complaint (name, blk->size,
+ TYPE_LENGTH (type));
+ *bytes = blk->data;
break;

/* The DW_AT_const_value attributes are supposed to carry the
@@ -10452,58 +10753,69 @@ dwarf2_const_value (struct attribute *at
converted to host endianness, so we just need to sign- or
zero-extend it as appropriate. */
case DW_FORM_data1:
- dwarf2_const_value_data (attr, sym, 8);
+ *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 8);
break;
case DW_FORM_data2:
- dwarf2_const_value_data (attr, sym, 16);
+ *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 16);
break;
case DW_FORM_data4:
- dwarf2_const_value_data (attr, sym, 32);
+ *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 32);
break;
case DW_FORM_data8:
- dwarf2_const_value_data (attr, sym, 64);
+ *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 64);
break;

case DW_FORM_sdata:
- SYMBOL_VALUE (sym) = DW_SND (attr);
- SYMBOL_CLASS (sym) = LOC_CONST;
+ *value = DW_SND (attr);
break;

case DW_FORM_udata:
- SYMBOL_VALUE (sym) = DW_UNSND (attr);
- SYMBOL_CLASS (sym) = LOC_CONST;
+ *value = DW_UNSND (attr);
break;

default:
complaint (&symfile_complaints,
_("unsupported const value attribute form: '%s'"),
dwarf_form_name (attr->form));
- SYMBOL_VALUE (sym) = 0;
- SYMBOL_CLASS (sym) = LOC_CONST;
+ *value = 0;
break;
}
}

-/* Given an attr with a DW_FORM_dataN value in host byte order,
- zero-extend it as appropriate for the symbol's type. The DWARF
- standard (v4) is not entirely clear about the meaning of using
- DW_FORM_dataN for a constant with a signed type, where the type is
- wider than the data. The conclusion of a discussion on the DWARF
- list was that this is unspecified. We choose to always zero-extend
- because that is the interpretation long in use by GCC. */
+/* Copy constant value from an attribute to a symbol. */
+
static void
-dwarf2_const_value_data (struct attribute *attr,
- struct symbol *sym,
- int bits)
+dwarf2_const_value (struct attribute *attr, struct symbol *sym,
+ struct dwarf2_cu *cu)
{
- LONGEST l = DW_UNSND (attr);
-
- if (bits < sizeof (l) * 8)
- l &= ((LONGEST) 1 << bits) - 1;
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
+ long value;
+ gdb_byte *bytes;
+ struct dwarf2_locexpr_baton *baton;
+
+ dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym),
+ SYMBOL_PRINT_NAME (sym),
+ &objfile->objfile_obstack, cu,
+ &value, &bytes, &baton);

- SYMBOL_VALUE (sym) = l;
- SYMBOL_CLASS (sym) = LOC_CONST;
+ if (baton != NULL)
+ {
+ SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
+ SYMBOL_LOCATION_BATON (sym) = baton;
+ SYMBOL_CLASS (sym) = LOC_COMPUTED;
+ }
+ else if (bytes != NULL)
+ {
+ SYMBOL_VALUE_BYTES (sym) = bytes;
+ SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ }
+ else
+ {
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ }
}

@@ -10756,6 +11068,48 @@ determine_prefix (struct die_info *die,

if (parent == NULL)
return "";
+ else if (parent->building_fullname)
+ {
+ const char *name;
+ const char *parent_name;
+
+ /* It has been seen on RealView 2.2 built binaries,
+ DW_TAG_template_type_param types actually _defined_ as
+ children of the parent class:
+
+ enum E {};
+ template class <class Enum> Class{};
+ Class<enum E> class_e;
+
+ 1: DW_TAG_class_type (Class)
+ 2: DW_TAG_enumeration_type (E)
+ 3: DW_TAG_enumerator (enum1:0)
+ 3: DW_TAG_enumerator (enum2:1)
+ ...
+ 2: DW_TAG_template_type_param
+ DW_AT_type DW_FORM_ref_udata (E)
+
+ Besides being broken debug info, it can put GDB into an
+ infinite loop. Consider:
+
+ When we're building the full name for Class<E>, we'll start
+ at Class, and go look over its template type parameters,
+ finding E. We'll then try to build the full name of E, and
+ reach here. We're now trying to build the full name of E,
+ and look over the parent DIE for containing scope. In the
+ broken case, if we followed the parent DIE of E, we'd again
+ find Class, and once again go look at its template type
+ arguments, etc., etc. Simply don't consider such parent die
+ as source-level parent of this die (it can't be, the language
+ doesn't allow it), and break the loop here. */
+ name = dwarf2_name (die, cu);
+ parent_name = dwarf2_name (parent, cu);
+ complaint (&symfile_complaints,
+ _("template param type '%s' defined within parent '%s'"),
+ name ? name : "<unknown>",
+ parent_name ? parent_name : "<unknown>");
+ return "";
+ }
else
switch (parent->tag)
{
@@ -12156,6 +12510,16 @@ static int
maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
struct dwarf2_per_cu_data *per_cu)
{
+ /* 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. */
+ if (reading_partial_symbols)
+ {
+ if (per_cu->cu == NULL || per_cu->cu->dies == NULL)
+ return 1;
+ return 0;
+ }
+
/* Mark the dependence relation so that we don't flush PER_CU
too early. */
dwarf2_add_dependence (this_cu, per_cu);
@@ -12214,6 +12578,8 @@ follow_die_offset (unsigned int offset,

gdb_assert (cu->per_cu != NULL);

+ target_cu = cu;
+
if (cu->per_cu->from_debug_types)
{
/* .debug_types CUs cannot reference anything outside their CU.
@@ -12221,7 +12587,6 @@ follow_die_offset (unsigned int offset,
DW_FORM_sig8. */
if (! offset_in_cu_p (&cu->header, offset))
return NULL;
- target_cu = cu;
}
else if (! offset_in_cu_p (&cu->header, offset))
{
@@ -12235,8 +12600,12 @@ follow_die_offset (unsigned int offset,

target_cu = per_cu->cu;
}
- else
- target_cu = cu;
+ else if (cu->dies == NULL)
+ {
+ /* We're loading full DIEs during partial symbol reading. */
+ gdb_assert (reading_partial_symbols);
+ load_full_comp_unit (cu->per_cu, cu->objfile);
+ }

*ref_cu = target_cu;
temp_die.offset = offset;
Index: src/gdb/dwarf2loc.c
===================================================================
--- src.orig/gdb/dwarf2loc.c 2010-07-30 00:39:47.000000000 +0100
+++ src/gdb/dwarf2loc.c 2010-07-30 12:20:09.000000000 +0100
@@ -881,7 +881,7 @@ static struct lval_funcs pieced_value_fu
SIZE, to find the current location of variable of TYPE in the context
of FRAME. */

-static struct value *
+struct value *
dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
const gdb_byte *data, unsigned short size,
struct dwarf2_per_cu_data *per_cu)
Index: src/gdb/dwarf2loc.h
===================================================================
--- src.orig/gdb/dwarf2loc.h 2010-07-30 00:39:47.000000000 +0100
+++ src/gdb/dwarf2loc.h 2010-07-30 12:20:09.000000000 +0100
@@ -48,6 +48,16 @@ CORE_ADDR dwarf2_per_cu_text_offset (str
struct dwarf2_locexpr_baton dwarf2_fetch_die_location_block
(unsigned int offset, struct dwarf2_per_cu_data *per_cu);

+/* Evaluate a location description, starting at DATA and with length
+ SIZE, to find the current location of variable of TYPE in the context
+ of FRAME. */
+
+struct value *dwarf2_evaluate_loc_desc (struct type *type,
+ struct frame_info *frame,
+ const gdb_byte *data,
+ unsigned short size,
+ struct dwarf2_per_cu_data *per_cu);
+
/* The symbol location baton types used by the DWARF-2 reader (i.e.
SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct
dwarf2_locexpr_baton" is for a symbol with a single location