* [RFA] comdat types
@ 2009-06-20 0:04 Doug Evans
2009-06-25 19:47 ` Tom Tromey
0 siblings, 1 reply; 11+ messages in thread
From: Doug Evans @ 2009-06-20 0:04 UTC (permalink / raw)
To: gdb-patches; +Cc: ccoutant
Hi.
This patch adds support for "comdat types" from dwarf4.
http://wiki.dwarfstd.org/index.php?title=COMDAT_Type_Sections
It requires http://sourceware.org/ml/gdb-patches/2009-06/msg00521.html.
There are no regressions on amd64 or i386 when not using -gdwarf-4.
There are a couple of failures with -gdwarf-4,
I need to revisit them with the latest gcc (the dwarf4 branch)
as they seem like gcc issues.
[specifically gdb.cp/classes.exp, and "info type foo" doesn't print the
source location though it should]
Storing each TU (type unit, a la CU for comp unit) in its own psymtab
may or may not be the right thing to do. Psymtabs are eventually going
away, and doing it this way falls out naturally from the code so I
went with this for now.
Ok to check in?
[It's been painful continually updating this patch.
I'm kinda hoping for a relatively quick review,
though I understand this patch is not small.]
2009-06-19 Doug Evans <dje@google.com>
* dwarf2.h (enum dwarf_tag): Add DW_TAG_type_unit.
(enum dwarf_form): Add DW_FORM_sec_offset, DW_FORM_exprloc,
DW_FORM_flag_present, DW_FORM_sig8.
(enum dwarf_attribute): Add DW_AT_signature, DW_AT_GNU_odr_signature.
Add support for "comdat types" from DWARF4.
* dwarf2read.c (dwarf2_per_objfile): New member types,
signatured_types.
(TYPES_SECTION): New macro.
(dwarf2_per_cu_data): Change size of length field from 30 bits
to 29 bits. New member from_debug_types.
(signatured_type): New struct.
(struct attribute): New union member signatured_type.
(DW_SIGNATURED_TYPE): New macro.
(dwarf2_attr_no_follow): New function.
(read_type_unit_scope): New function.
(follow_die_ref_or_sig, follow_die_sig): New functions.
(dwarf2_locate_sectoins): Handle .debug_types.
(dwarf2_build_psymtabs): Read .debug_types.
(read_type_comp_unit_head): New function.
(hash_type_signature, eq_type_signature): New functions.
(create_debug_types_hash_table): New function.
(lookup_signatured_type): New function.
(process_psymtab_comp_unit): Handle type units too.
(process_type_comp_unit, build_type_psymtabs): New functions.
(dwarf2_build_psymtabs_hard): Call build_type_psymtabs.
(load_partial_comp_unit): Assert not called for a type unit.
(skip_one_die): Handle DW_FORM_sig8.
(queue_comp_unit): Don't call load_full_comp_unit here, or
update read_in_chain.
(psymtab_to_symtab_1): Call read_signatured_type_at_offset for
type units, or load_full_comp_unit for comp units after
queue_comp_unit returns.
(load_full_comp_unit): Assert not called for type units.
(load_full_comp_unit): Update read_in_chain here.
(process_die): Handle DW_TAG_type_unit.
(read_structure_type): Look for signatured types.
(read_enumeration_type): Ditto.
(init_cu_die_reader): Handle .debug_types.
(read_comp_unit): Assert hash not computed yet.
(read_die_and_children): Expand debugging printf to handle .debug_types.
(read_partial_die): Handle DW_TAG_type_unit:
(find_patial_die): Handle .debug_types.
(read_attribute_value): Handle DW_FORM_sig8.
(die_type): Call follow_die_ref_or_sig instead of follow_die_ref.
(die_containing_type): Ditto.
(dwarf_tag_name): Handle DW_TAG_type_unit.
(dwarf_attr_name): Handle DW_AT_signature, DW_GNU_odr_signature.
(dwarf_form_name): Handle DW_FORM_sec_offset, DW_FORM_exprloc,
DW_FORM_flag_present, DW_FORM_sig8.
(dump_die_shallow): Handlel DW_FORM_sig8.
(maybe_queue_comp_unit): Change return type to int from void.
All callers updated.
(follow_die_ref): Handle .debug_types.
(lookup_signatured_type_at_offset): New function.
(read_signatured_type_at_offset): New function.
(read_signatured_type): New function.
Index: ./include/elf/dwarf2.h
===================================================================
RCS file: /cvs/src/src/include/elf/dwarf2.h,v
retrieving revision 1.25
diff -u -p -r1.25 dwarf2.h
--- ./include/elf/dwarf2.h 24 Apr 2009 18:28:58 -0000 1.25
+++ ./include/elf/dwarf2.h 19 Jun 2009 23:48:31 -0000
@@ -190,6 +190,8 @@ enum dwarf_tag
DW_TAG_imported_unit = 0x3d,
DW_TAG_condition = 0x3f,
DW_TAG_shared_type = 0x40,
+ /* DWARF 4. */
+ DW_TAG_type_unit = 0x41,
/* SGI/MIPS Extensions. */
DW_TAG_MIPS_loop = 0x4081,
/* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */
@@ -239,7 +241,12 @@ enum dwarf_form
DW_FORM_ref4 = 0x13,
DW_FORM_ref8 = 0x14,
DW_FORM_ref_udata = 0x15,
- DW_FORM_indirect = 0x16
+ DW_FORM_indirect = 0x16,
+ /* DWARF 4. */
+ DW_FORM_sec_offset = 0x17,
+ DW_FORM_exprloc = 0x18,
+ DW_FORM_flag_present = 0x19,
+ DW_FORM_sig8 = 0x20
};
/* Attribute names and codes. */
@@ -337,6 +344,8 @@ enum dwarf_attribute
DW_AT_elemental = 0x66,
DW_AT_pure = 0x67,
DW_AT_recursive = 0x68,
+ /* DWARF 4 values. */
+ DW_AT_signature = 0x69,
/* SGI/MIPS extensions. */
DW_AT_MIPS_fde = 0x2001,
DW_AT_MIPS_loop_begin = 0x2002,
@@ -372,6 +381,7 @@ enum dwarf_attribute
DW_AT_body_begin = 0x2105,
DW_AT_body_end = 0x2106,
DW_AT_GNU_vector = 0x2107,
+ DW_AT_GNU_odr_signature = 0x210f,
/* VMS extensions. */
DW_AT_VMS_rtnbeg_pd_address = 0x2201,
/* UPC extension. */
diff -u -p ../../dwarf-cleanup/src/gdb/dwarf2read.c ./gdb/dwarf2read.c
--- ../../dwarf-cleanup/src/gdb/dwarf2read.c 2009-06-18 19:07:07.000000000 -0700
+++ ./gdb/dwarf2read.c 2009-06-19 15:38:07.000000000 -0700
@@ -163,6 +163,7 @@ struct dwarf2_per_objfile
struct dwarf2_section_info macinfo;
struct dwarf2_section_info str;
struct dwarf2_section_info ranges;
+ struct dwarf2_section_info types;
struct dwarf2_section_info frame;
struct dwarf2_section_info eh_frame;
@@ -177,6 +178,10 @@ struct dwarf2_per_objfile
they can be freed later. */
struct dwarf2_per_cu_data *read_in_chain;
+ /* A table mapping .debug_types signatures to its signatured_type entry.
+ This is NULL if the .debug_types section hasn't been read in yet. */
+ htab_t signatured_types;
+
/* A flag indicating wether this objfile has a section loaded at a
VMA of 0. */
int has_section_at_zero;
@@ -198,6 +203,7 @@ static struct dwarf2_per_objfile *dwarf2
#define MACINFO_SECTION "debug_macinfo"
#define STR_SECTION "debug_str"
#define RANGES_SECTION "debug_ranges"
+#define TYPES_SECTION "debug_types"
#define FRAME_SECTION "debug_frame"
#define EH_FRAME_SECTION "eh_frame"
@@ -339,13 +345,13 @@ struct dwarf2_cu
struct dwarf2_per_cu_data
{
- /* The start offset and length of this compilation unit. 2**30-1
+ /* The start offset and length of this compilation unit. 2**29-1
bytes should suffice to store the length of any compilation unit
- if it doesn't, GDB will fall over anyway.
NOTE: Unlike comp_unit_head.length, this length includes
initial_length_size. */
unsigned int offset;
- unsigned int length : 30;
+ unsigned int length : 29;
/* Flag indicating this compilation unit will be read in before
any of the current compilation units are processed. */
@@ -357,6 +363,10 @@ struct dwarf2_per_cu_data
hash table and don't find it. */
unsigned int load_all_dies : 1;
+ /* Non-zero if this CU is from .debug_types.
+ Otherwise it's from .debug_info. */
+ unsigned int from_debug_types : 1;
+
/* Set iff currently read in. */
struct dwarf2_cu *cu;
@@ -372,6 +382,22 @@ struct dwarf2_per_cu_data
struct partial_symtab *psymtab;
};
+/* Entry in the signatured_types hash table. */
+
+struct signatured_type
+{
+ ULONGEST signature;
+
+ /* Offset in .debug_types of the TU (type_unit) for this type. */
+ unsigned int offset;
+
+ /* Offset in .debug_types of the type defined by this TU. */
+ unsigned int type_offset;
+
+ /* The CU(/TU) of this type. */
+ struct dwarf2_per_cu_data per_cu;
+};
+
/* Struct used to pass misc. parameters to read_die_and_children, et. al.
which are used for both .debug_info and .debug_types dies.
All parameters here are unchanging for the life of the call.
@@ -540,6 +566,7 @@ struct attribute
unsigned long unsnd;
long int snd;
CORE_ADDR addr;
+ struct signatured_type *signatured_type;
}
u;
};
@@ -589,6 +616,7 @@ struct function_range
#define DW_BLOCK(attr) ((attr)->u.blk)
#define DW_SND(attr) ((attr)->u.snd)
#define DW_ADDR(attr) ((attr)->u.addr)
+#define DW_SIGNATURED_TYPE(attr) ((attr)->u.signatured_type)
/* Blocks are a bunch of untyped bytes. */
struct dwarf_block
@@ -873,6 +901,10 @@ static void set_cu_language (unsigned in
static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
struct dwarf2_cu *);
+static struct attribute *dwarf2_attr_no_follow (struct die_info *,
+ unsigned int,
+ struct dwarf2_cu *);
+
static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
struct dwarf2_cu *cu);
@@ -923,6 +955,8 @@ static char *typename_concat (struct obs
static void read_file_scope (struct die_info *, struct dwarf2_cu *);
+static void read_type_unit_scope (struct die_info *, struct dwarf2_cu *);
+
static void read_func_scope (struct die_info *, struct dwarf2_cu *);
static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
@@ -1043,10 +1077,24 @@ static unsigned int dwarf2_get_ref_die_o
static int dwarf2_get_attr_constant_value (struct attribute *, int);
+static struct die_info *follow_die_ref_or_sig (struct die_info *,
+ struct attribute *,
+ struct dwarf2_cu **);
+
static struct die_info *follow_die_ref (struct die_info *,
struct attribute *,
struct dwarf2_cu **);
+static struct die_info *follow_die_sig (struct die_info *,
+ struct attribute *,
+ struct dwarf2_cu **);
+
+static void read_signatured_type_at_offset (struct objfile *objfile,
+ unsigned int offset);
+
+static void read_signatured_type (struct objfile *,
+ struct signatured_type *type_sig);
+
/* memory allocation interface */
static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
@@ -1214,6 +1262,11 @@ dwarf2_locate_sections (bfd *abfd, asect
dwarf2_per_objfile->ranges.asection = sectp;
dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
}
+ else if (section_is_p (sectp->name, TYPES_SECTION))
+ {
+ dwarf2_per_objfile->types.asection = sectp;
+ dwarf2_per_objfile->types.size = bfd_get_section_size (sectp);
+ }
if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD)
&& bfd_section_vma (abfd, sectp) == 0)
@@ -1413,6 +1466,7 @@ dwarf2_build_psymtabs (struct objfile *o
dwarf2_read_section (objfile, &dwarf2_per_objfile->str);
dwarf2_read_section (objfile, &dwarf2_per_objfile->macinfo);
dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
dwarf2_read_section (objfile, &dwarf2_per_objfile->loc);
dwarf2_read_section (objfile, &dwarf2_per_objfile->eh_frame);
dwarf2_read_section (objfile, &dwarf2_per_objfile->frame);
@@ -1551,6 +1605,29 @@ partial_read_comp_unit_head (struct comp
return info_ptr;
}
+/* Read in the types comp unit header information from .debug_types entry at
+ types_ptr. The result is a pointer to one past the end of the header. */
+
+static gdb_byte *
+read_type_comp_unit_head (struct comp_unit_head *cu_header,
+ ULONGEST *signature,
+ gdb_byte *types_ptr, bfd *abfd)
+{
+ unsigned int bytes_read;
+ gdb_byte *initial_types_ptr = types_ptr;
+
+ cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer;
+
+ types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd);
+
+ *signature = read_8_bytes (abfd, types_ptr);
+ types_ptr += 8;
+ types_ptr += cu_header->offset_size;
+ cu_header->first_die_offset = types_ptr - initial_types_ptr;
+
+ return types_ptr;
+}
+
/* Allocate a new partial symtab for file named NAME and mark this new
partial symtab as being an include of PST. */
@@ -1610,9 +1687,137 @@ dwarf2_build_include_psymtabs (struct dw
free_line_header (lh);
}
-/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
+static hashval_t
+hash_type_signature (const void *item)
+{
+ const struct signatured_type *type_sig = item;
+ /* This drops the top 32 bits of the signature, but is ok for a hash. */
+ return type_sig->signature;
+}
+
+static int
+eq_type_signature (const void *item_lhs, const void *item_rhs)
+{
+ const struct signatured_type *lhs = item_lhs;
+ const struct signatured_type *rhs = item_rhs;
+ return lhs->signature == rhs->signature;
+}
+
+/* Create the hash table of all entries in the .debug_types section.
+ The result is zero if there is an error (e.g. missing .debug_types section),
+ otherwise non-zero. */
+
+static int
+create_debug_types_hash_table (struct objfile *objfile)
+{
+ gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer;
+ htab_t types_htab;
+
+ if (info_ptr == NULL)
+ {
+ dwarf2_per_objfile->signatured_types = NULL;
+ return 0;
+ }
+
+ types_htab = htab_create_alloc_ex (41,
+ hash_type_signature,
+ eq_type_signature,
+ NULL,
+ &objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+
+ if (dwarf2_die_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
+ }
+
+ while (info_ptr < dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
+ {
+ unsigned int offset;
+ unsigned int offset_size;
+ unsigned int type_offset;
+ unsigned int length, initial_length_size;
+ unsigned short version;
+ ULONGEST signature;
+ struct signatured_type *type_sig;
+ void **slot;
+ gdb_byte *ptr = info_ptr;
+
+ offset = ptr - dwarf2_per_objfile->types.buffer;
+
+ /* We need to read the type's signature in order to build the hash
+ table, but we don't need to read anything else just yet. */
+
+ /* Sanity check to ensure entire cu is present. */
+ length = read_initial_length (objfile->obfd, ptr, &initial_length_size);
+ if (ptr + length + initial_length_size
+ > dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
+ {
+ complaint (&symfile_complaints,
+ _("debug type entry runs off end of `.debug_types' section, ignored"));
+ break;
+ }
+
+ offset_size = initial_length_size == 4 ? 4 : 8;
+ ptr += initial_length_size;
+ version = bfd_get_16 (objfile->obfd, ptr);
+ ptr += 2;
+ ptr += offset_size; /* abbrev offset */
+ ptr += 1; /* address size */
+ signature = bfd_get_64 (objfile->obfd, ptr);
+ ptr += 8;
+ type_offset = read_offset_1 (objfile->obfd, ptr, offset_size);
+
+ type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig));
+ memset (type_sig, 0, sizeof (*type_sig));
+ type_sig->signature = signature;
+ type_sig->offset = offset;
+ type_sig->type_offset = type_offset;
+
+ slot = htab_find_slot (types_htab, type_sig, INSERT);
+ gdb_assert (slot != NULL);
+ *slot = type_sig;
+
+ if (dwarf2_die_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n",
+ offset, phex (signature, sizeof (signature)));
+ }
+
+ info_ptr = info_ptr + initial_length_size + length;
+ }
+
+ dwarf2_per_objfile->signatured_types = types_htab;
+
+ return 1;
+}
+
+/* Lookup a signature based type.
+ Returns NULL if SIG is not present in the table. */
+
+static struct signatured_type *
+lookup_signatured_type (struct objfile *objfile, ULONGEST sig)
+{
+ struct signatured_type find_entry, *entry;
+
+ if (dwarf2_per_objfile->signatured_types == NULL)
+ {
+ complaint (&symfile_complaints,
+ _("missing `.debug_types' section for DW_FORM_sig8 die"));
+ return 0;
+ }
+
+ find_entry.signature = sig;
+ entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
+ return entry;
+}
+
+/* Subroutine of process_type_comp_unit and dwarf2_build_psymtabs_hard
+ to combine the common parts.
Process a compilation unit for a psymtab.
- BUFFER is a pointer to the beginning of the dwarf section buffer.
+ BUFFER is a pointer to the beginning of the dwarf section buffer,
+ either .debug_info or debug_types.
INFO_PTR is a pointer to the start of the CU.
Returns a pointer to the next CU. */
@@ -1653,11 +1858,19 @@ process_psymtab_comp_unit (struct objfil
make_cleanup (dwarf2_free_abbrev_table, &cu);
/* Read the compilation unit die. */
+ if (this_cu->from_debug_types)
+ info_ptr += 8 /*signature*/ + cu.header.offset_size;
abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, abfd,
buffer, info_ptr, &cu);
- if (comp_unit_die.tag == DW_TAG_partial_unit)
+ if (this_cu->from_debug_types)
+ {
+ /* ??? How come this is for .debug_types only? */
+ this_cu->offset = cu.header.offset;
+ this_cu->length = cu.header.length + cu.header.initial_length_size;
+ }
+ else if (comp_unit_die.tag == DW_TAG_partial_unit)
{
info_ptr = (beg_of_comp_unit + cu.header.length
+ cu.header.initial_length_size);
@@ -1708,7 +1921,8 @@ process_psymtab_comp_unit (struct objfil
this_cu->psymtab = pst;
/* Possibly set the default values of LOWPC and HIGHPC from
- `DW_AT_ranges'. */
+ `DW_AT_ranges'.
+ ??? Is this valid for .debug_types? */
if (cu.has_ranges_offset)
{
if (dwarf2_ranges_read (cu.ranges_offset, &comp_unit_die.lowpc,
@@ -1764,12 +1978,18 @@ process_psymtab_comp_unit (struct objfil
/* If there is already a psymtab or symtab for a file of this
name, remove it. (If there is a symtab, more drastic things
also happen.) This happens in VxWorks. */
- free_named_symtabs (pst->filename);
+ if (! this_cu->from_debug_types)
+ free_named_symtabs (pst->filename);
info_ptr = (beg_of_comp_unit + cu.header.length
+ cu.header.initial_length_size);
- if (comp_unit_die.has_stmt_list)
+ if (this_cu->from_debug_types)
+ {
+ /* ??? It's not clear we want to do anything with stmt lists here.
+ Waiting to see what gcc ultimately does. */
+ }
+ else if (comp_unit_die.has_stmt_list)
{
/* Get the list of files included in the current compilation unit,
and build a psymtab for each of them. */
@@ -1781,6 +2001,40 @@ process_psymtab_comp_unit (struct objfil
return info_ptr;
}
+/* Traversal function for htab_traverse_noresize.
+ Process one .debug_types comp-unit. */
+
+static int
+process_type_comp_unit (void **slot, void *info)
+{
+ struct signatured_type *entry = (struct signatured_type *) *slot;
+ struct objfile *objfile = (struct objfile *) info;
+ struct dwarf2_per_cu_data *this_cu;
+
+ this_cu = &entry->per_cu;
+ this_cu->from_debug_types = 1;
+
+ process_psymtab_comp_unit (objfile, this_cu,
+ dwarf2_per_objfile->types.buffer,
+ dwarf2_per_objfile->types.buffer + entry->offset,
+ dwarf2_per_objfile->types.size);
+
+ return 1;
+}
+
+/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
+ Build partial symbol tables for the .debug_types comp-units. */
+
+static void
+build_type_psymtabs (struct objfile *objfile)
+{
+ if (! create_debug_types_hash_table (objfile))
+ return;
+
+ htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
+ process_type_comp_unit, objfile);
+}
+
/* Build the partial symbol table by doing a quick pass through the
.debug_info and .debug_abbrev sections. */
@@ -1799,6 +2053,8 @@ dwarf2_build_psymtabs_hard (struct objfi
read_in_chain. Make sure to free them when we're done. */
back_to = make_cleanup (free_cached_comp_units, NULL);
+ build_type_psymtabs (objfile);
+
create_all_comp_units (objfile);
objfile->psymtabs_addrmap =
@@ -1852,6 +2108,8 @@ load_partial_comp_unit (struct dwarf2_pe
unsigned int bytes_read;
struct cleanup *back_to;
+ gdb_assert (! this_cu->from_debug_types);
+
info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
beg_of_comp_unit = info_ptr;
@@ -2592,6 +2850,7 @@ skip_one_die (gdb_byte *buffer, gdb_byte
break;
case DW_FORM_data8:
case DW_FORM_ref8:
+ case DW_FORM_sig8:
info_ptr += 8;
break;
case DW_FORM_string:
@@ -2727,12 +2986,6 @@ queue_comp_unit (struct dwarf2_per_cu_da
dwarf2_queue_tail->next = item;
dwarf2_queue_tail = item;
-
- /* Either PER_CU is the CU we want to process, or we're following a reference
- pointing into PER_CU. Either way, we need its DIEs now. */
- load_full_comp_unit (item->per_cu, objfile);
- item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
- dwarf2_per_objfile->read_in_chain = item->per_cu;
}
/* Process the queue. */
@@ -2827,6 +3080,11 @@ psymtab_to_symtab_1 (struct partial_symt
queue_comp_unit (per_cu, pst->objfile);
+ if (per_cu->from_debug_types)
+ read_signatured_type_at_offset (pst->objfile, per_cu->offset);
+ else
+ load_full_comp_unit (per_cu, pst->objfile);
+
process_queue (pst->objfile);
/* Age the cache, releasing compilation units that have not
@@ -2849,6 +3107,8 @@ load_full_comp_unit (struct dwarf2_per_c
struct attribute *attr;
CORE_ADDR baseaddr;
+ gdb_assert (! per_cu->from_debug_types);
+
/* Set local variables from the partial symbol table info. */
offset = per_cu->offset;
@@ -2888,6 +3148,10 @@ load_full_comp_unit (struct dwarf2_per_c
else
set_cu_language (language_minimal, cu);
+ /* 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);
/* We've successfully allocated this compilation unit. Let our caller
@@ -2979,6 +3243,9 @@ process_die (struct die_info *die, struc
case DW_TAG_compile_unit:
read_file_scope (die, cu);
break;
+ case DW_TAG_type_unit:
+ read_type_unit_scope (die, cu);
+ break;
case DW_TAG_subprogram:
read_func_scope (die, cu);
break;
@@ -3222,6 +3489,91 @@ read_file_scope (struct die_info *die, s
do_cleanups (back_to);
}
+/* For TUs we want to skip the first top level sibling if it's not the
+ actual type being defined by this TU. In this case the first top
+ level sibling is there to provide context only. */
+
+static void
+read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+ CORE_ADDR lowpc;
+ struct attribute *attr;
+ char *name = NULL;
+ char *comp_dir = NULL;
+ struct die_info *child_die;
+ bfd *abfd = objfile->obfd;
+ struct line_header *line_header = 0;
+
+ /* start_symtab needs a low pc, but we don't really have one.
+ Do what read_file_scope would do in the absence of such info. */
+ lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ /* Find the filename. Do not use dwarf2_name here, since the filename
+ is not a source language identifier. */
+ attr = dwarf2_attr (die, DW_AT_name, cu);
+ if (attr)
+ {
+ name = DW_STRING (attr);
+ }
+
+ attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
+ if (attr)
+ {
+ comp_dir = DW_STRING (attr);
+ }
+ else if (name != NULL && IS_ABSOLUTE_PATH (name))
+ {
+ comp_dir = ldirname (name);
+ if (comp_dir != NULL)
+ make_cleanup (xfree, comp_dir);
+ }
+
+ if (name == NULL)
+ name = "<unknown>";
+
+ attr = dwarf2_attr (die, DW_AT_language, cu);
+ if (attr)
+ {
+ set_cu_language (DW_UNSND (attr), cu);
+ }
+
+ /* This isn't technically needed today. It is done for symmetry
+ with read_file_scope. */
+ attr = dwarf2_attr (die, DW_AT_producer, cu);
+ if (attr)
+ cu->producer = DW_STRING (attr);
+
+ /* We assume that we're processing GCC output. */
+ processing_gcc_compilation = 2;
+
+ processing_has_namespace_info = 0;
+
+ start_symtab (name, comp_dir, lowpc);
+ record_debugformat ("DWARF 2");
+ record_producer (cu->producer);
+
+ /* Process the dies in the type unit. */
+ if (die->child == NULL)
+ {
+ dump_die_for_error (die);
+ error (_("Dwarf Error: Missing children for type unit [in module %s]"),
+ bfd_get_filename (abfd));
+ }
+
+ child_die = die->child;
+
+ while (child_die && child_die->tag)
+ {
+ process_die (child_die, cu);
+
+ child_die = sibling_die (child_die);
+ }
+
+ do_cleanups (back_to);
+}
+
static void
add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
struct dwarf2_cu *cu)
@@ -4414,6 +4766,22 @@ read_structure_type (struct die_info *di
if (type)
return type;
+ /* If the definition of this type lives in .debug_types, read that type.
+ Don't follow DW_AT_specification though, that will take us back up
+ the chain and we want to go down. */
+ attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
+ if (attr)
+ {
+ struct dwarf2_cu *type_cu = cu;
+ struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
+ /* We could just recurse on read_structure_type, but we need to call
+ get_die_type to ensure only one type for this DIE is created.
+ This is important, for example, because for c++ classes we need
+ TYPE_NAME set which is only done by new_symbol. Blech. */
+ type = read_type_die (type_die, type_cu);
+ return set_die_type (die, type, cu);
+ }
+
type = alloc_type (objfile);
INIT_CPLUS_SPECIFIC (type);
@@ -4628,6 +4996,18 @@ read_enumeration_type (struct die_info *
struct attribute *attr;
const char *name;
+ /* If the definition of this type lives in .debug_types, read that type.
+ Don't follow DW_AT_specification though, that will take us back up
+ the chain and we want to go down. */
+ attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
+ if (attr)
+ {
+ struct dwarf2_cu *type_cu = cu;
+ struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
+ type = read_type_die (type_die, type_cu);
+ return set_die_type (die, type, cu);
+ }
+
type = alloc_type (objfile);
TYPE_CODE (type) = TYPE_CODE_ENUM;
@@ -5549,7 +5929,10 @@ init_cu_die_reader (struct die_reader_sp
{
reader->abfd = cu->objfile->obfd;
reader->cu = cu;
- reader->buffer = dwarf2_per_objfile->info.buffer;
+ if (cu->per_cu->from_debug_types)
+ reader->buffer = dwarf2_per_objfile->types.buffer;
+ else
+ reader->buffer = dwarf2_per_objfile->info.buffer;
}
/* Read a whole compilation unit into a linked list of dies. */
@@ -5559,6 +5942,7 @@ read_comp_unit (gdb_byte *info_ptr, stru
{
struct die_reader_specs reader_specs;
+ gdb_assert (cu->die_hash == NULL);
cu->die_hash
= htab_create_alloc_ex (cu->header.length / 12,
die_hash,
@@ -5587,7 +5971,14 @@ read_die_and_children (const struct die_
if (dwarf2_die_debug)
{
- fprintf_unfiltered (gdb_stdlog, "Read die from .debug_info:\n");
+ fprintf_unfiltered (gdb_stdlog,
+ "\nRead die from %s of %s:\n",
+ reader->buffer == dwarf2_per_objfile->info.buffer
+ ? ".debug_info"
+ : reader->buffer == dwarf2_per_objfile->types.buffer
+ ? ".debug_types"
+ : "unknown section",
+ reader->abfd->filename);
dump_die (result, dwarf2_die_debug);
}
@@ -6157,6 +6548,7 @@ read_partial_die (struct partial_die_inf
switch (part_die->tag)
{
case DW_TAG_compile_unit:
+ case DW_TAG_type_unit:
/* Compilation units have a DW_AT_name that is a filename, not
a source language identifier. */
case DW_TAG_enumeration_type:
@@ -6319,7 +6711,10 @@ find_partial_die_in_comp_unit (unsigned
return lookup_die;
}
-/* Find a partial DIE at OFFSET, which may or may not be in CU. */
+/* Find a partial DIE at OFFSET, which may or may not be in CU,
+ except in the case of .debug_types DIEs which do not reference
+ outside their CU (they do however referencing other types via
+ DW_FORM_sig8). */
static struct partial_die_info *
find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
@@ -6327,6 +6722,14 @@ find_partial_die (unsigned int offset, s
struct dwarf2_per_cu_data *per_cu = NULL;
struct partial_die_info *pd = NULL;
+ if (cu->per_cu->from_debug_types)
+ {
+ pd = find_partial_die_in_comp_unit (offset, cu);
+ if (pd != NULL)
+ return pd;
+ goto NotFound;
+ }
+
if (offset_in_cu_p (&cu->header, offset))
{
pd = find_partial_die_in_comp_unit (offset, cu);
@@ -6380,6 +6783,8 @@ find_partial_die (unsigned int offset, s
pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
}
+ NotFound:
+
if (pd == NULL)
internal_error (__FILE__, __LINE__,
_("could not find partial DIE 0x%x in cache [from module %s]\n"),
@@ -6533,6 +6938,14 @@ read_attribute_value (struct attribute *
DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
+ case DW_FORM_sig8:
+ /* Convert the signature to something we can record in DW_UNSND
+ for later lookup.
+ NOTE: This is NULL if the type wasn't found. */
+ DW_SIGNATURED_TYPE (attr) =
+ lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr));
+ info_ptr += 8;
+ break;
case DW_FORM_ref_udata:
DW_ADDR (attr) = (cu->header.offset
+ read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
@@ -6995,6 +7408,27 @@ dwarf2_attr (struct die_info *die, unsig
return NULL;
}
+/* Return the named attribute or NULL if not there,
+ but do not follow DW_AT_specification, etc.
+ This is for use in contexts where we're reading .debug_types dies.
+ Following DW_AT_specification, DW_AT_abstract_origin will take us
+ back up the chain, and we want to go down. */
+
+static struct attribute *
+dwarf2_attr_no_follow (struct die_info *die, unsigned int name,
+ struct dwarf2_cu *cu)
+{
+ unsigned int i;
+
+ for (i = 0; i < die->num_attrs; ++i)
+ {
+ if (die->attrs[i].name == name)
+ return &die->attrs[i];
+ }
+
+ return NULL;
+}
+
/* Return non-zero iff the attribute NAME is defined for the given DIE,
and holds a non-zero value. This function should only be used for
DW_FORM_flag attributes. */
@@ -8125,8 +8559,8 @@ die_type (struct die_info *die, struct d
/* A missing DW_AT_type represents a void type. */
return builtin_type (gdbarch)->builtin_void;
}
- else
- type_die = follow_die_ref (die, type_attr, &cu);
+
+ type_die = follow_die_ref_or_sig (die, type_attr, &cu);
type = tag_type_to_type (type_die, cu);
if (!type)
@@ -8151,7 +8585,7 @@ die_containing_type (struct die_info *di
type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
if (type_attr)
{
- type_die = follow_die_ref (die, type_attr, &cu);
+ type_die = follow_die_ref_or_sig (die, type_attr, &cu);
type = tag_type_to_type (type_die, cu);
}
if (!type)
@@ -8589,6 +9023,8 @@ dwarf_tag_name (unsigned tag)
return "DW_TAG_condition";
case DW_TAG_shared_type:
return "DW_TAG_shared_type";
+ case DW_TAG_type_unit:
+ return "DW_TAG_type_unit";
case DW_TAG_MIPS_loop:
return "DW_TAG_MIPS_loop";
case DW_TAG_HP_array_descriptor:
@@ -8804,6 +9240,9 @@ dwarf_attr_name (unsigned attr)
return "DW_AT_pure";
case DW_AT_recursive:
return "DW_AT_recursive";
+ /* DWARF 4 values. */
+ case DW_AT_signature:
+ return "DW_AT_signature";
/* SGI/MIPS extensions. */
#ifdef MIPS /* collides with DW_AT_HP_block_index */
case DW_AT_MIPS_fde:
@@ -8875,6 +9314,8 @@ dwarf_attr_name (unsigned attr)
return "DW_AT_body_end";
case DW_AT_GNU_vector:
return "DW_AT_GNU_vector";
+ case DW_AT_GNU_odr_signature:
+ return "DW_AT_GNU_odr_signature";
/* VMS extensions. */
case DW_AT_VMS_rtnbeg_pd_address:
return "DW_AT_VMS_rtnbeg_pd_address";
@@ -8942,6 +9383,14 @@ dwarf_form_name (unsigned form)
return "DW_FORM_ref_udata";
case DW_FORM_indirect:
return "DW_FORM_indirect";
+ case DW_FORM_sec_offset:
+ return "DW_FORM_sec_offset";
+ case DW_FORM_exprloc:
+ return "DW_FORM_exprloc";
+ case DW_FORM_flag_present:
+ return "DW_FORM_flag_present";
+ case DW_FORM_sig8:
+ return "DW_FORM_sig8";
case GDB_FORM_cached_string:
return "GDB_FORM_cached_string";
default:
@@ -9487,6 +9936,13 @@ dump_die_shallow (struct ui_file *f, int
case DW_FORM_sdata:
fprintf_unfiltered (f, "constant: %ld", DW_UNSND (&die->attrs[i]));
break;
+ case DW_FORM_sig8:
+ if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL)
+ fprintf_unfiltered (f, "signatured type, offset: 0x%x",
+ DW_SIGNATURED_TYPE (&die->attrs[i])->offset);
+ else
+ fprintf_unfiltered (f, "signatured type, offset: unknown");
+ break;
case DW_FORM_string:
case DW_FORM_strp:
case GDB_FORM_cached_string:
@@ -9624,9 +10080,11 @@ dwarf2_get_attr_constant_value (struct a
}
/* THIS_CU has a reference to PER_CU. If necessary, load the new compilation
- unit and add it to our queue. */
+ unit and add it to our queue.
+ The result is non-zero if PER_CU was queued, otherwise the result is zero
+ meaning either PER_CU is already queued or it is already loaded. */
-static void
+static int
maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
struct dwarf2_per_cu_data *per_cu)
{
@@ -9636,18 +10094,48 @@ maybe_queue_comp_unit (struct dwarf2_cu
/* If it's already on the queue, we have nothing to do. */
if (per_cu->queued)
- return;
+ return 0;
/* If the compilation unit is already loaded, just mark it as
used. */
if (per_cu->cu != NULL)
{
per_cu->cu->last_used = 0;
- return;
+ return 0;
}
/* Add it to the queue. */
queue_comp_unit (per_cu, this_cu->objfile);
+
+ return 1;
+}
+
+/* Follow reference or signature attribute ATTR of SRC_DIE.
+ On entry *REF_CU is the CU of SRC_DIE.
+ On exit *REF_CU is the CU of the result. */
+
+static struct die_info *
+follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
+ struct dwarf2_cu **ref_cu)
+{
+ struct die_info *die;
+
+ if (is_ref_attr (attr))
+ {
+ die = follow_die_ref (src_die, attr, ref_cu);
+ }
+ else if (attr->form == DW_FORM_sig8)
+ {
+ die = follow_die_sig (src_die, attr, ref_cu);
+ }
+ else
+ {
+ dump_die_for_error (src_die);
+ error (_("Dwarf Error: Expected reference attribute [in module %s]"),
+ (*ref_cu)->objfile->name);
+ }
+
+ return die;
}
/* Follow reference attribute ATTR of SRC_DIE.
@@ -9663,15 +10151,27 @@ follow_die_ref (struct die_info *src_die
struct die_info temp_die;
struct dwarf2_cu *target_cu, *cu = *ref_cu;
+ gdb_assert (cu->per_cu != NULL);
+
offset = dwarf2_get_ref_die_offset (attr);
- if (! offset_in_cu_p (&cu->header, offset))
+ if (cu->per_cu->from_debug_types)
+ {
+ /* .debug_types CUs cannot reference anything outside their CU.
+ If they need to, they have to reference a signatured type via
+ DW_FORM_sig8. */
+ if (! offset_in_cu_p (&cu->header, offset))
+ goto NotFound;
+ target_cu = cu;
+ }
+ else if (! offset_in_cu_p (&cu->header, offset))
{
struct dwarf2_per_cu_data *per_cu;
per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
/* If necessary, add it to the queue and load its DIEs. */
- maybe_queue_comp_unit (cu, per_cu);
+ if (maybe_queue_comp_unit (cu, per_cu))
+ load_full_comp_unit (per_cu, cu->objfile);
target_cu = per_cu->cu;
}
@@ -9684,9 +10184,164 @@ follow_die_ref (struct die_info *src_die
if (die)
return die;
- error (_("Dwarf Error: Cannot find DIE at 0x%lx referenced from DIE "
- "at 0x%lx [in module %s]"),
- (long) offset, (long) src_die->offset, cu->objfile->name);
+ NotFound:
+
+ error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
+ "at 0x%x [in module %s]"),
+ offset, src_die->offset, cu->objfile->name);
+}
+
+/* Follow the signature attribute ATTR in SRC_DIE.
+ On entry *REF_CU is the CU of SRC_DIE.
+ On exit *REF_CU is the CU of the result. */
+
+static struct die_info *
+follow_die_sig (struct die_info *src_die, struct attribute *attr,
+ struct dwarf2_cu **ref_cu)
+{
+ struct objfile *objfile = (*ref_cu)->objfile;
+ struct die_info temp_die;
+ struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
+ struct dwarf2_cu *sig_cu;
+ struct die_info *die;
+
+ /* sig_type will be NULL if the signatured type is missing from
+ the debug info. */
+ if (sig_type == NULL)
+ error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE "
+ "at 0x%x [in module %s]"),
+ src_die->offset, objfile->name);
+
+ /* If necessary, add it to the queue and load its DIEs. */
+
+ if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu))
+ read_signatured_type (objfile, sig_type);
+
+ gdb_assert (sig_type->per_cu.cu != NULL);
+
+ sig_cu = sig_type->per_cu.cu;
+ temp_die.offset = sig_cu->header.offset + sig_type->type_offset;
+ die = htab_find_with_hash (sig_cu->die_hash, &temp_die, temp_die.offset);
+ if (die)
+ {
+ *ref_cu = sig_cu;
+ return die;
+ }
+
+ error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced from DIE "
+ "at 0x%x [in module %s]"),
+ sig_type->type_offset, src_die->offset, objfile->name);
+}
+
+/* Given an offset of a signatured type, return its signatured_type. */
+
+static struct signatured_type *
+lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset)
+{
+ gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer + offset;
+ unsigned int length, initial_length_size;
+ unsigned int sig_offset;
+ struct signatured_type find_entry, *type_sig;
+
+ length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size);
+ sig_offset = (initial_length_size
+ + 2 /*version*/
+ + (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/
+ + 1 /*address_size*/);
+ find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset);
+ type_sig = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
+
+ /* This is only used to lookup previously recorded types.
+ If we didn't find it, it's our bug. */
+ gdb_assert (type_sig != NULL);
+ gdb_assert (offset == type_sig->offset);
+
+ return type_sig;
+}
+
+/* Read in signatured type at OFFSET and build its CU and die(s). */
+
+static void
+read_signatured_type_at_offset (struct objfile *objfile,
+ unsigned int offset)
+{
+ struct signatured_type *type_sig;
+
+ /* We have the section offset, but we need the signature to do the
+ hash table lookup. */
+ type_sig = lookup_signatured_type_at_offset (objfile, offset);
+
+ gdb_assert (type_sig->per_cu.cu == NULL);
+
+ read_signatured_type (objfile, type_sig);
+
+ gdb_assert (type_sig->per_cu.cu != NULL);
+}
+
+/* Read in a signatured type and build its CU and DIEs. */
+
+static void
+read_signatured_type (struct objfile *objfile,
+ struct signatured_type *type_sig)
+{
+ gdb_byte *types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset;
+ struct die_reader_specs reader_specs;
+ struct dwarf2_cu *cu;
+ ULONGEST signature;
+ struct cleanup *back_to, *free_cu_cleanup;
+ struct attribute *attr;
+
+ gdb_assert (type_sig->per_cu.cu == NULL);
+
+ cu = xmalloc (sizeof (struct dwarf2_cu));
+ memset (cu, 0, sizeof (struct dwarf2_cu));
+ obstack_init (&cu->comp_unit_obstack);
+ cu->objfile = objfile;
+ type_sig->per_cu.cu = cu;
+ cu->per_cu = &type_sig->per_cu;
+
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+
+ types_ptr = read_type_comp_unit_head (&cu->header, &signature,
+ types_ptr, objfile->obfd);
+ gdb_assert (signature == type_sig->signature);
+
+ cu->die_hash
+ = htab_create_alloc_ex (cu->header.length / 12,
+ die_hash,
+ die_eq,
+ NULL,
+ &cu->comp_unit_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+
+ dwarf2_read_abbrevs (cu->objfile->obfd, cu);
+ back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+
+ init_cu_die_reader (&reader_specs, cu);
+
+ cu->dies = read_die_and_children (&reader_specs, types_ptr, &types_ptr,
+ NULL /*parent*/);
+
+ /* We try not to read any attributes in this function, because not
+ all objfiles needed for references have been loaded yet, and symbol
+ table processing isn't initialized. But we have to set the CU language,
+ or we won't be able to build types correctly. */
+ attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
+ if (attr)
+ set_cu_language (DW_UNSND (attr), cu);
+ else
+ set_cu_language (language_minimal, cu);
+
+ do_cleanups (back_to);
+
+ /* We've successfully allocated this compilation unit. Let our caller
+ clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
+
+ type_sig->per_cu.cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = &type_sig->per_cu;
}
/* Decode simple location descriptions.
@@ -10622,8 +11277,8 @@ dwarf2_per_cu_addr_size (struct dwarf2_p
}
}
-/* Locate the compilation unit from CU's objfile which contains the
- DIE at OFFSET. Raises an error on failure. */
+/* Locate the .debug_info compilation unit from CU's objfile which contains
+ the DIE at OFFSET. Raises an error on failure. */
static struct dwarf2_per_cu_data *
dwarf2_find_containing_comp_unit (unsigned int offset,
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [RFA] comdat types 2009-06-20 0:04 [RFA] comdat types Doug Evans @ 2009-06-25 19:47 ` Tom Tromey 2009-06-25 20:28 ` Doug Evans 2009-06-26 0:01 ` Cary Coutant 0 siblings, 2 replies; 11+ messages in thread From: Tom Tromey @ 2009-06-25 19:47 UTC (permalink / raw) To: Doug Evans; +Cc: gdb-patches, ccoutant >>>>> "Doug" == Doug Evans <dje@google.com> writes: Doug> This patch adds support for "comdat types" from dwarf4. Doug> http://wiki.dwarfstd.org/index.php?title=COMDAT_Type_Sections I am a fan of this. I'm curious about one thing on this page, and I thought I'd take the opportunity to ask. DW_TAG_type_unit may have a DW_AT_language child. But, the language is not mentioned in the suggested method for computing a type's signature. This seems strange to me: either the language matters (in which case, it seems like it ought to be in the signature); or the language does not matter, in which case, why mention it? Doug> I need to revisit them with the latest gcc (the dwarf4 branch) Doug> as they seem like gcc issues. Doug> [specifically gdb.cp/classes.exp, and "info type foo" doesn't print the Doug> source location though it should] Yeah; my view is that since this patch can't hurt anything, if the gcc changes require gdb changes in turn, it won't matter. Doug> Ok to check in? I read through it. Unfortunately, I don't think I am enough of a dwarf2read.c expert to approve this. So, I would appreciate it if someone more expert could claim it. Alternatively, if nobody has time to do this, and they say so, I will learn more and take it on. One concern I have is whether there is any chance that the specification will change between now and when DWARF-4 is published. I do have a few nits. Doug> + types_htab = htab_create_alloc_ex (41, Doug> + hash_type_signature, Doug> + eq_type_signature, Doug> + NULL, Doug> + &objfile->objfile_obstack, Doug> + hashtab_obstack_allocate, Doug> + dummy_obstack_deallocate); This is just a side note -- I've seen a few hash tables allocated on obstacks. Doesn't resizing the table waste memory? Too bad we don't have allocation pools instead of obstacks. I suppose in this specific case we could use the objfile data machinery to deallocate hash tables. Doug> + if (dwarf2_die_debug) Doug> + { Doug> + fprintf_unfiltered (gdb_stdlog, "Signatured types:\n"); Doug> + } Over-bracing. There's a fair amount of this in the patch. Doug> + if (this_cu->from_debug_types) Doug> + { Doug> + /* ??? How come this is for .debug_types only? */ Doug> + this_cu->offset = cu.header.offset; Doug> + this_cu->length = cu.header.length + cu.header.initial_length_size; Daniel has asked before for "no new FIXMEs". You can't escape this by spelling it "???" :-) Seriously, I think this is a valid concern and I would like some definitive resolution to the various "???" comments. Doug> + NotFound: Should be "not_found". There's a couple of these. Tom ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-06-25 19:47 ` Tom Tromey @ 2009-06-25 20:28 ` Doug Evans 2009-06-25 20:49 ` Tom Tromey 2009-06-26 1:33 ` Daniel Jacobowitz 2009-06-26 0:01 ` Cary Coutant 1 sibling, 2 replies; 11+ messages in thread From: Doug Evans @ 2009-06-25 20:28 UTC (permalink / raw) To: tromey; +Cc: gdb-patches, ccoutant On Thu, Jun 25, 2009 at 12:46 PM, Tom Tromey<tromey@redhat.com> wrote: > I'm curious about one thing on this page, and I thought I'd take the > opportunity to ask. DW_TAG_type_unit may have a DW_AT_language child. > But, the language is not mentioned in the suggested method for > computing a type's signature. This seems strange to me: either the > language matters (in which case, it seems like it ought to be in the > signature); or the language does not matter, in which case, why > mention it? I'll leave this for Cary. > One concern I have is whether there is any chance that the > specification will change between now and when DWARF-4 is published. Cary? > I do have a few nits. > > Doug> + types_htab = htab_create_alloc_ex (41, > Doug> + hash_type_signature, > Doug> + eq_type_signature, > Doug> + NULL, > Doug> + &objfile->objfile_obstack, > Doug> + hashtab_obstack_allocate, > Doug> + dummy_obstack_deallocate); > > This is just a side note -- I've seen a few hash tables allocated on > obstacks. Doesn't resizing the table waste memory? IIRC I use the noresize traversal routine. It's not ideal, no. > Too bad we don't have allocation pools instead of obstacks. I suppose > in this specific case we could use the objfile data machinery to > deallocate hash tables. If that's ok, I'll do that. > Doug> + if (dwarf2_die_debug) > Doug> + { > Doug> + fprintf_unfiltered (gdb_stdlog, "Signatured types:\n"); > Doug> + } > > Over-bracing. There's a fair amount of this in the patch. One of the style rules I'm less fond of (and see others are too from scans of gdb, is this a rule or a guideline?). [I'm reminded of Pirates of the Caribbean, "They're more like guidelines anyway." :-)] But ok. > Doug> + if (this_cu->from_debug_types) > Doug> + { > Doug> + /* ??? How come this is for .debug_types only? */ > Doug> + this_cu->offset = cu.header.offset; > Doug> + this_cu->length = cu.header.length + cu.header.initial_length_size; > > Daniel has asked before for "no new FIXMEs". You can't escape this by > spelling it "???" :-) Well, that one was an oversight (these patches drag on and my eyes tend to glaze over ...). While as a general rule I don't disagree, it's kinda odd to see others add new functionality with open issues. > Seriously, I think this is a valid concern and I would like some > definitive resolution to the various "???" comments. > > Doug> + NotFound: > > Should be "not_found". There's a couple of these. fwiw I like StudlyCaps for labels: How many labels should there be in one's code? --> As absolutely few as possible. Same with StudlyCaps. :-) There are existing uses of StudlyCaps for labels (albeit isolated to one file) so I went with that. But ok. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-06-25 20:28 ` Doug Evans @ 2009-06-25 20:49 ` Tom Tromey 2009-07-15 1:13 ` Doug Evans 2009-06-26 1:33 ` Daniel Jacobowitz 1 sibling, 1 reply; 11+ messages in thread From: Tom Tromey @ 2009-06-25 20:49 UTC (permalink / raw) To: Doug Evans; +Cc: gdb-patches, ccoutant >>>>> "Doug" == Doug Evans <dje@google.com> writes: Tom> Too bad we don't have allocation pools instead of obstacks. I suppose Tom> in this specific case we could use the objfile data machinery to Tom> deallocate hash tables. Doug> If that's ok, I'll do that. Sorry, I wasn't clear. This particular thing was just a drive-by complaint on my part. I don't think you need to make any change to your patch. Tom> Over-bracing. There's a fair amount of this in the patch. Doug> One of the style rules I'm less fond of (and see others are too from Doug> scans of gdb, is this a rule or a guideline?). Doug> [I'm reminded of Pirates of the Caribbean, "They're more like Doug> guidelines anyway." :-)] Doug> But ok. Yeah, I tend to treat this one as a rule. Doug> Well, that one was an oversight (these patches drag on and my eyes Doug> tend to glaze over ...). Doug> While as a general rule I don't disagree, it's kinda odd to see others Doug> add new functionality with open issues. I'm sorry. I try to be reasonably consistent when reviewing, but I'm probably not. It is fair to call me on that when it happens. Perhaps it was wrong of me to drag in the general rule (which, as we were discussing on irc, has various corner cases and ambiguities) when something specific would serve better. The comments in question: + if (this_cu->from_debug_types) + { + /* ??? How come this is for .debug_types only? */ + this_cu->offset = cu.header.offset; + this_cu->length = cu.header.length + cu.header.initial_length_size; + } /* Possibly set the default values of LOWPC and HIGHPC from - `DW_AT_ranges'. */ + `DW_AT_ranges'. + ??? Is this valid for .debug_types? */ if (cu.has_ranges_offset) { + if (this_cu->from_debug_types) + { + /* ??? It's not clear we want to do anything with stmt lists here. + Waiting to see what gcc ultimately does. */ + } It seems to me that the first one is (IIUC) a question about the implementation of dwarf2read.c itself. So, can it answered and rephrased as a note? The second seems like a question about the spec. The third one, I'm less sure. Perhaps just removing the "???" part is appropriate. Doug> fwiw I like StudlyCaps for labels: How many labels should there be in Doug> one's code? Doug> --> As absolutely few as possible. Doug> Same with StudlyCaps. :-) :-) StudlyCaps just look weird to me in GNU code. And the many gotos in gdb largely follow the GNUish naming convention, though I see some counterexamples in Ada: ada-typeprint.c: goto Huh; ada-exp.y: goto BadEncoding; ada-exp.y: goto TryAfterRenaming; Tom ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-06-25 20:49 ` Tom Tromey @ 2009-07-15 1:13 ` Doug Evans 2009-07-15 19:28 ` Tom Tromey 0 siblings, 1 reply; 11+ messages in thread From: Doug Evans @ 2009-07-15 1:13 UTC (permalink / raw) To: tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 337 bytes --] How about this? It addresses the issues raised here: http://sourceware.org/ml/gdb-patches/2009-06/msg00689.html This patch requires: http://sourceware.org/ml/gdb-patches/2009-06/msg00521.html which is unchanged (modulo the requested formatting change), and was approved here: http://sourceware.org/ml/gdb-patches/2009-06/msg00657.html [-- Attachment #2: gdb-090714-dwarf2read-sig8-2.patch.txt --] [-- Type: text/plain, Size: 41153 bytes --] 2009-06-19 Doug Evans <dje@google.com> * dwarf2.h (enum dwarf_tag): Add DW_TAG_type_unit. (enum dwarf_form): Add DW_FORM_sec_offset, DW_FORM_exprloc, DW_FORM_flag_present, DW_FORM_sig8. (enum dwarf_attribute): Add DW_AT_signature, DW_AT_GNU_odr_signature. Add support for "comdat types" from DWARF4. * dwarf2read.c (dwarf2_per_objfile): New member types, signatured_types. (TYPES_SECTION): New macro. (dwarf2_per_cu_data): Change size of length field from 30 bits to 29 bits. New member from_debug_types. (signatured_type): New struct. (struct attribute): New union member signatured_type. (DW_SIGNATURED_TYPE): New macro. (dwarf2_attr_no_follow): New function. (read_type_unit_scope): New function. (follow_die_ref_or_sig, follow_die_sig): New functions. (dwarf2_locate_sectoins): Handle .debug_types. (dwarf2_build_psymtabs): Read .debug_types. (read_type_comp_unit_head): New function. (hash_type_signature, eq_type_signature): New functions. (create_debug_types_hash_table): New function. (lookup_signatured_type): New function. (process_psymtab_comp_unit): Handle type units too. (process_type_comp_unit, build_type_psymtabs): New functions. (dwarf2_build_psymtabs_hard): Call build_type_psymtabs. (load_partial_comp_unit): Assert not called for a type unit. (skip_one_die): Handle DW_FORM_sig8. (queue_comp_unit): Don't call load_full_comp_unit here, or update read_in_chain. (psymtab_to_symtab_1): Call read_signatured_type_at_offset for type units, or load_full_comp_unit for comp units after queue_comp_unit returns. (load_full_comp_unit): Assert not called for type units. (load_full_comp_unit): Update read_in_chain here. (process_die): Handle DW_TAG_type_unit. (read_structure_type): Look for signatured types. (read_enumeration_type): Ditto. (init_cu_die_reader): Handle .debug_types. (read_comp_unit): Assert hash not computed yet. (read_die_and_children): Expand debugging printf to handle .debug_types. (read_partial_die): Handle DW_TAG_type_unit: (find_patial_die): Handle .debug_types. (read_attribute_value): Handle DW_FORM_sig8. (die_type): Call follow_die_ref_or_sig instead of follow_die_ref. (die_containing_type): Ditto. (dwarf_tag_name): Handle DW_TAG_type_unit. (dwarf_attr_name): Handle DW_AT_signature, DW_GNU_odr_signature. (dwarf_form_name): Handle DW_FORM_sec_offset, DW_FORM_exprloc, DW_FORM_flag_present, DW_FORM_sig8. (dump_die_shallow): Handlel DW_FORM_sig8. (maybe_queue_comp_unit): Change return type to int from void. All callers updated. (follow_die_ref): Handle .debug_types. (lookup_signatured_type_at_offset): New function. (read_signatured_type_at_offset): New function. (read_signatured_type): New function. diff -u -p -r1.2 dwarf2.h --- dwarf2.h 9 Jul 2009 21:01:15 -0000 1.2 +++ dwarf2.h 14 Jul 2009 23:22:35 -0000 @@ -194,6 +194,8 @@ enum dwarf_tag DW_TAG_imported_unit = 0x3d, DW_TAG_condition = 0x3f, DW_TAG_shared_type = 0x40, + /* DWARF 4. */ + DW_TAG_type_unit = 0x41, DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff, @@ -244,7 +246,12 @@ enum dwarf_form DW_FORM_ref4 = 0x13, DW_FORM_ref8 = 0x14, DW_FORM_ref_udata = 0x15, - DW_FORM_indirect = 0x16 + DW_FORM_indirect = 0x16, + /* DWARF 4. */ + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_sig8 = 0x20 }; /* Attribute names and codes. */ @@ -342,6 +349,8 @@ enum dwarf_attribute DW_AT_elemental = 0x66, DW_AT_pure = 0x67, DW_AT_recursive = 0x68, + /* DWARF 4 values. */ + DW_AT_signature = 0x69, DW_AT_lo_user = 0x2000, /* Implementation-defined range start. */ DW_AT_hi_user = 0x3ff0, /* Implementation-defined range end. */ @@ -381,6 +390,7 @@ enum dwarf_attribute DW_AT_body_begin = 0x2105, DW_AT_body_end = 0x2106, DW_AT_GNU_vector = 0x2107, + DW_AT_GNU_odr_signature = 0x210f, /* VMS extensions. */ DW_AT_VMS_rtnbeg_pd_address = 0x2201, /* UPC extension. */ diff -u -p ../../dwarf-cleanup/src/gdb/dwarf2read.c ./gdb/dwarf2read.c --- ../../../dwarf-cleanup/src/gdb/dwarf2read.c 2009-07-14 14:36:55.000000000 -0700 +++ ./dwarf2read.c 2009-07-14 16:19:30.000000000 -0700 @@ -164,6 +164,7 @@ struct dwarf2_per_objfile struct dwarf2_section_info macinfo; struct dwarf2_section_info str; struct dwarf2_section_info ranges; + struct dwarf2_section_info types; struct dwarf2_section_info frame; struct dwarf2_section_info eh_frame; @@ -178,6 +179,10 @@ struct dwarf2_per_objfile they can be freed later. */ struct dwarf2_per_cu_data *read_in_chain; + /* A table mapping .debug_types signatures to its signatured_type entry. + This is NULL if the .debug_types section hasn't been read in yet. */ + htab_t signatured_types; + /* A flag indicating wether this objfile has a section loaded at a VMA of 0. */ int has_section_at_zero; @@ -199,6 +204,7 @@ static struct dwarf2_per_objfile *dwarf2 #define MACINFO_SECTION "debug_macinfo" #define STR_SECTION "debug_str" #define RANGES_SECTION "debug_ranges" +#define TYPES_SECTION "debug_types" #define FRAME_SECTION "debug_frame" #define EH_FRAME_SECTION "eh_frame" @@ -340,13 +346,13 @@ struct dwarf2_cu struct dwarf2_per_cu_data { - /* The start offset and length of this compilation unit. 2**30-1 + /* The start offset and length of this compilation unit. 2**29-1 bytes should suffice to store the length of any compilation unit - if it doesn't, GDB will fall over anyway. NOTE: Unlike comp_unit_head.length, this length includes initial_length_size. */ unsigned int offset; - unsigned int length : 30; + unsigned int length : 29; /* Flag indicating this compilation unit will be read in before any of the current compilation units are processed. */ @@ -358,6 +364,10 @@ struct dwarf2_per_cu_data hash table and don't find it. */ unsigned int load_all_dies : 1; + /* Non-zero if this CU is from .debug_types. + Otherwise it's from .debug_info. */ + unsigned int from_debug_types : 1; + /* Set iff currently read in. */ struct dwarf2_cu *cu; @@ -373,6 +383,22 @@ struct dwarf2_per_cu_data struct partial_symtab *psymtab; }; +/* Entry in the signatured_types hash table. */ + +struct signatured_type +{ + ULONGEST signature; + + /* Offset in .debug_types of the TU (type_unit) for this type. */ + unsigned int offset; + + /* Offset in .debug_types of the type defined by this TU. */ + unsigned int type_offset; + + /* The CU(/TU) of this type. */ + struct dwarf2_per_cu_data per_cu; +}; + /* Struct used to pass misc. parameters to read_die_and_children, et. al. which are used for both .debug_info and .debug_types dies. All parameters here are unchanging for the life of the call. @@ -541,6 +567,7 @@ struct attribute unsigned long unsnd; long int snd; CORE_ADDR addr; + struct signatured_type *signatured_type; } u; }; @@ -590,6 +617,7 @@ struct function_range #define DW_BLOCK(attr) ((attr)->u.blk) #define DW_SND(attr) ((attr)->u.snd) #define DW_ADDR(attr) ((attr)->u.addr) +#define DW_SIGNATURED_TYPE(attr) ((attr)->u.signatured_type) /* Blocks are a bunch of untyped bytes. */ struct dwarf_block @@ -874,6 +902,10 @@ static void set_cu_language (unsigned in static struct attribute *dwarf2_attr (struct die_info *, unsigned int, struct dwarf2_cu *); +static struct attribute *dwarf2_attr_no_follow (struct die_info *, + unsigned int, + struct dwarf2_cu *); + static int dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu); @@ -924,6 +956,8 @@ static char *typename_concat (struct obs static void read_file_scope (struct die_info *, struct dwarf2_cu *); +static void read_type_unit_scope (struct die_info *, struct dwarf2_cu *); + static void read_func_scope (struct die_info *, struct dwarf2_cu *); static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *); @@ -1046,10 +1080,24 @@ static unsigned int dwarf2_get_ref_die_o static int dwarf2_get_attr_constant_value (struct attribute *, int); +static struct die_info *follow_die_ref_or_sig (struct die_info *, + struct attribute *, + struct dwarf2_cu **); + static struct die_info *follow_die_ref (struct die_info *, struct attribute *, struct dwarf2_cu **); +static struct die_info *follow_die_sig (struct die_info *, + struct attribute *, + struct dwarf2_cu **); + +static void read_signatured_type_at_offset (struct objfile *objfile, + unsigned int offset); + +static void read_signatured_type (struct objfile *, + struct signatured_type *type_sig); + /* memory allocation interface */ static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *); @@ -1217,6 +1265,11 @@ dwarf2_locate_sections (bfd *abfd, asect dwarf2_per_objfile->ranges.asection = sectp; dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp); } + else if (section_is_p (sectp->name, TYPES_SECTION)) + { + dwarf2_per_objfile->types.asection = sectp; + dwarf2_per_objfile->types.size = bfd_get_section_size (sectp); + } if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD) && bfd_section_vma (abfd, sectp) == 0) @@ -1416,6 +1469,7 @@ dwarf2_build_psymtabs (struct objfile *o dwarf2_read_section (objfile, &dwarf2_per_objfile->str); dwarf2_read_section (objfile, &dwarf2_per_objfile->macinfo); dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges); + dwarf2_read_section (objfile, &dwarf2_per_objfile->types); dwarf2_read_section (objfile, &dwarf2_per_objfile->loc); dwarf2_read_section (objfile, &dwarf2_per_objfile->eh_frame); dwarf2_read_section (objfile, &dwarf2_per_objfile->frame); @@ -1554,6 +1608,29 @@ partial_read_comp_unit_head (struct comp return info_ptr; } +/* Read in the types comp unit header information from .debug_types entry at + types_ptr. The result is a pointer to one past the end of the header. */ + +static gdb_byte * +read_type_comp_unit_head (struct comp_unit_head *cu_header, + ULONGEST *signature, + gdb_byte *types_ptr, bfd *abfd) +{ + unsigned int bytes_read; + gdb_byte *initial_types_ptr = types_ptr; + + cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer; + + types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd); + + *signature = read_8_bytes (abfd, types_ptr); + types_ptr += 8; + types_ptr += cu_header->offset_size; + cu_header->first_die_offset = types_ptr - initial_types_ptr; + + return types_ptr; +} + /* Allocate a new partial symtab for file named NAME and mark this new partial symtab as being an include of PST. */ @@ -1613,9 +1690,133 @@ dwarf2_build_include_psymtabs (struct dw free_line_header (lh); } -/* Subroutine of dwarf2_build_psymtabs_hard to simplify it. +static hashval_t +hash_type_signature (const void *item) +{ + const struct signatured_type *type_sig = item; + /* This drops the top 32 bits of the signature, but is ok for a hash. */ + return type_sig->signature; +} + +static int +eq_type_signature (const void *item_lhs, const void *item_rhs) +{ + const struct signatured_type *lhs = item_lhs; + const struct signatured_type *rhs = item_rhs; + return lhs->signature == rhs->signature; +} + +/* Create the hash table of all entries in the .debug_types section. + The result is zero if there is an error (e.g. missing .debug_types section), + otherwise non-zero. */ + +static int +create_debug_types_hash_table (struct objfile *objfile) +{ + gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer; + htab_t types_htab; + + if (info_ptr == NULL) + { + dwarf2_per_objfile->signatured_types = NULL; + return 0; + } + + types_htab = htab_create_alloc_ex (41, + hash_type_signature, + eq_type_signature, + NULL, + &objfile->objfile_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + + if (dwarf2_die_debug) + fprintf_unfiltered (gdb_stdlog, "Signatured types:\n"); + + while (info_ptr < dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size) + { + unsigned int offset; + unsigned int offset_size; + unsigned int type_offset; + unsigned int length, initial_length_size; + unsigned short version; + ULONGEST signature; + struct signatured_type *type_sig; + void **slot; + gdb_byte *ptr = info_ptr; + + offset = ptr - dwarf2_per_objfile->types.buffer; + + /* We need to read the type's signature in order to build the hash + table, but we don't need to read anything else just yet. */ + + /* Sanity check to ensure entire cu is present. */ + length = read_initial_length (objfile->obfd, ptr, &initial_length_size); + if (ptr + length + initial_length_size + > dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size) + { + complaint (&symfile_complaints, + _("debug type entry runs off end of `.debug_types' section, ignored")); + break; + } + + offset_size = initial_length_size == 4 ? 4 : 8; + ptr += initial_length_size; + version = bfd_get_16 (objfile->obfd, ptr); + ptr += 2; + ptr += offset_size; /* abbrev offset */ + ptr += 1; /* address size */ + signature = bfd_get_64 (objfile->obfd, ptr); + ptr += 8; + type_offset = read_offset_1 (objfile->obfd, ptr, offset_size); + + type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig)); + memset (type_sig, 0, sizeof (*type_sig)); + type_sig->signature = signature; + type_sig->offset = offset; + type_sig->type_offset = type_offset; + + slot = htab_find_slot (types_htab, type_sig, INSERT); + gdb_assert (slot != NULL); + *slot = type_sig; + + if (dwarf2_die_debug) + fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n", + offset, phex (signature, sizeof (signature))); + + info_ptr = info_ptr + initial_length_size + length; + } + + dwarf2_per_objfile->signatured_types = types_htab; + + return 1; +} + +/* Lookup a signature based type. + Returns NULL if SIG is not present in the table. */ + +static struct signatured_type * +lookup_signatured_type (struct objfile *objfile, ULONGEST sig) +{ + struct signatured_type find_entry, *entry; + + if (dwarf2_per_objfile->signatured_types == NULL) + { + complaint (&symfile_complaints, + _("missing `.debug_types' section for DW_FORM_sig8 die")); + return 0; + } + + find_entry.signature = sig; + entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry); + return entry; +} + +/* Subroutine of process_type_comp_unit and dwarf2_build_psymtabs_hard + to combine the common parts. Process a compilation unit for a psymtab. - BUFFER is a pointer to the beginning of the dwarf section buffer. + BUFFER is a pointer to the beginning of the dwarf section buffer, + either .debug_info or debug_types. INFO_PTR is a pointer to the start of the CU. Returns a pointer to the next CU. */ @@ -1656,11 +1857,19 @@ process_psymtab_comp_unit (struct objfil make_cleanup (dwarf2_free_abbrev_table, &cu); /* Read the compilation unit die. */ + if (this_cu->from_debug_types) + info_ptr += 8 /*signature*/ + cu.header.offset_size; abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu); info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, abfd, buffer, info_ptr, &cu); - if (comp_unit_die.tag == DW_TAG_partial_unit) + if (this_cu->from_debug_types) + { + /* offset,length haven't been set yet for type units. */ + this_cu->offset = cu.header.offset; + this_cu->length = cu.header.length + cu.header.initial_length_size; + } + else if (comp_unit_die.tag == DW_TAG_partial_unit) { info_ptr = (beg_of_comp_unit + cu.header.length + cu.header.initial_length_size); @@ -1767,12 +1976,18 @@ process_psymtab_comp_unit (struct objfil /* If there is already a psymtab or symtab for a file of this name, remove it. (If there is a symtab, more drastic things also happen.) This happens in VxWorks. */ - free_named_symtabs (pst->filename); + if (! this_cu->from_debug_types) + free_named_symtabs (pst->filename); info_ptr = (beg_of_comp_unit + cu.header.length + cu.header.initial_length_size); - if (comp_unit_die.has_stmt_list) + if (this_cu->from_debug_types) + { + /* It's not clear we want to do anything with stmt lists here. + Waiting to see what gcc ultimately does. */ + } + else if (comp_unit_die.has_stmt_list) { /* Get the list of files included in the current compilation unit, and build a psymtab for each of them. */ @@ -1784,6 +1999,40 @@ process_psymtab_comp_unit (struct objfil return info_ptr; } +/* Traversal function for htab_traverse_noresize. + Process one .debug_types comp-unit. */ + +static int +process_type_comp_unit (void **slot, void *info) +{ + struct signatured_type *entry = (struct signatured_type *) *slot; + struct objfile *objfile = (struct objfile *) info; + struct dwarf2_per_cu_data *this_cu; + + this_cu = &entry->per_cu; + this_cu->from_debug_types = 1; + + process_psymtab_comp_unit (objfile, this_cu, + dwarf2_per_objfile->types.buffer, + dwarf2_per_objfile->types.buffer + entry->offset, + dwarf2_per_objfile->types.size); + + return 1; +} + +/* Subroutine of dwarf2_build_psymtabs_hard to simplify it. + Build partial symbol tables for the .debug_types comp-units. */ + +static void +build_type_psymtabs (struct objfile *objfile) +{ + if (! create_debug_types_hash_table (objfile)) + return; + + htab_traverse_noresize (dwarf2_per_objfile->signatured_types, + process_type_comp_unit, objfile); +} + /* Build the partial symbol table by doing a quick pass through the .debug_info and .debug_abbrev sections. */ @@ -1802,6 +2051,8 @@ dwarf2_build_psymtabs_hard (struct objfi read_in_chain. Make sure to free them when we're done. */ back_to = make_cleanup (free_cached_comp_units, NULL); + build_type_psymtabs (objfile); + create_all_comp_units (objfile); objfile->psymtabs_addrmap = @@ -1855,6 +2106,8 @@ load_partial_comp_unit (struct dwarf2_pe unsigned int bytes_read; struct cleanup *back_to; + gdb_assert (! this_cu->from_debug_types); + info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset; beg_of_comp_unit = info_ptr; @@ -2595,6 +2848,7 @@ skip_one_die (gdb_byte *buffer, gdb_byte break; case DW_FORM_data8: case DW_FORM_ref8: + case DW_FORM_sig8: info_ptr += 8; break; case DW_FORM_string: @@ -2730,12 +2984,6 @@ queue_comp_unit (struct dwarf2_per_cu_da dwarf2_queue_tail->next = item; dwarf2_queue_tail = item; - - /* Either PER_CU is the CU we want to process, or we're following a reference - pointing into PER_CU. Either way, we need its DIEs now. */ - load_full_comp_unit (item->per_cu, objfile); - item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain; - dwarf2_per_objfile->read_in_chain = item->per_cu; } /* Process the queue. */ @@ -2830,6 +3078,11 @@ psymtab_to_symtab_1 (struct partial_symt queue_comp_unit (per_cu, pst->objfile); + if (per_cu->from_debug_types) + read_signatured_type_at_offset (pst->objfile, per_cu->offset); + else + load_full_comp_unit (per_cu, pst->objfile); + process_queue (pst->objfile); /* Age the cache, releasing compilation units that have not @@ -2852,6 +3105,8 @@ load_full_comp_unit (struct dwarf2_per_c struct attribute *attr; CORE_ADDR baseaddr; + gdb_assert (! per_cu->from_debug_types); + /* Set local variables from the partial symbol table info. */ offset = per_cu->offset; @@ -2891,6 +3146,10 @@ load_full_comp_unit (struct dwarf2_per_c else set_cu_language (language_minimal, cu); + /* 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); /* We've successfully allocated this compilation unit. Let our caller @@ -2982,6 +3241,9 @@ process_die (struct die_info *die, struc case DW_TAG_compile_unit: read_file_scope (die, cu); break; + case DW_TAG_type_unit: + read_type_unit_scope (die, cu); + break; case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: read_func_scope (die, cu); @@ -3303,6 +3565,85 @@ read_file_scope (struct die_info *die, s do_cleanups (back_to); } +/* For TUs we want to skip the first top level sibling if it's not the + actual type being defined by this TU. In this case the first top + level sibling is there to provide context only. */ + +static void +read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); + CORE_ADDR lowpc; + struct attribute *attr; + char *name = NULL; + char *comp_dir = NULL; + struct die_info *child_die; + bfd *abfd = objfile->obfd; + struct line_header *line_header = 0; + + /* start_symtab needs a low pc, but we don't really have one. + Do what read_file_scope would do in the absence of such info. */ + lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + /* Find the filename. Do not use dwarf2_name here, since the filename + is not a source language identifier. */ + attr = dwarf2_attr (die, DW_AT_name, cu); + if (attr) + name = DW_STRING (attr); + + attr = dwarf2_attr (die, DW_AT_comp_dir, cu); + if (attr) + comp_dir = DW_STRING (attr); + else if (name != NULL && IS_ABSOLUTE_PATH (name)) + { + comp_dir = ldirname (name); + if (comp_dir != NULL) + make_cleanup (xfree, comp_dir); + } + + if (name == NULL) + name = "<unknown>"; + + attr = dwarf2_attr (die, DW_AT_language, cu); + if (attr) + set_cu_language (DW_UNSND (attr), cu); + + /* This isn't technically needed today. It is done for symmetry + with read_file_scope. */ + attr = dwarf2_attr (die, DW_AT_producer, cu); + if (attr) + cu->producer = DW_STRING (attr); + + /* We assume that we're processing GCC output. */ + processing_gcc_compilation = 2; + + processing_has_namespace_info = 0; + + start_symtab (name, comp_dir, lowpc); + record_debugformat ("DWARF 2"); + record_producer (cu->producer); + + /* Process the dies in the type unit. */ + if (die->child == NULL) + { + dump_die_for_error (die); + error (_("Dwarf Error: Missing children for type unit [in module %s]"), + bfd_get_filename (abfd)); + } + + child_die = die->child; + + while (child_die && child_die->tag) + { + process_die (child_die, cu); + + child_die = sibling_die (child_die); + } + + do_cleanups (back_to); +} + static void add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc, struct dwarf2_cu *cu) @@ -4532,6 +4873,22 @@ read_structure_type (struct die_info *di if (type) return type; + /* If the definition of this type lives in .debug_types, read that type. + Don't follow DW_AT_specification though, that will take us back up + the chain and we want to go down. */ + attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu); + if (attr) + { + struct dwarf2_cu *type_cu = cu; + struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu); + /* We could just recurse on read_structure_type, but we need to call + get_die_type to ensure only one type for this DIE is created. + This is important, for example, because for c++ classes we need + TYPE_NAME set which is only done by new_symbol. Blech. */ + type = read_type_die (type_die, type_cu); + return set_die_type (die, type, cu); + } + type = alloc_type (objfile); INIT_CPLUS_SPECIFIC (type); @@ -4746,6 +5103,18 @@ read_enumeration_type (struct die_info * struct attribute *attr; const char *name; + /* If the definition of this type lives in .debug_types, read that type. + Don't follow DW_AT_specification though, that will take us back up + the chain and we want to go down. */ + attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu); + if (attr) + { + struct dwarf2_cu *type_cu = cu; + struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu); + type = read_type_die (type_die, type_cu); + return set_die_type (die, type, cu); + } + type = alloc_type (objfile); TYPE_CODE (type) = TYPE_CODE_ENUM; @@ -5665,7 +6034,10 @@ init_cu_die_reader (struct die_reader_sp { reader->abfd = cu->objfile->obfd; reader->cu = cu; - reader->buffer = dwarf2_per_objfile->info.buffer; + if (cu->per_cu->from_debug_types) + reader->buffer = dwarf2_per_objfile->types.buffer; + else + reader->buffer = dwarf2_per_objfile->info.buffer; } /* Read a whole compilation unit into a linked list of dies. */ @@ -5675,6 +6047,7 @@ read_comp_unit (gdb_byte *info_ptr, stru { struct die_reader_specs reader_specs; + gdb_assert (cu->die_hash == NULL); cu->die_hash = htab_create_alloc_ex (cu->header.length / 12, die_hash, @@ -5703,7 +6076,14 @@ read_die_and_children (const struct die_ if (dwarf2_die_debug) { - fprintf_unfiltered (gdb_stdlog, "Read die from .debug_info:\n"); + fprintf_unfiltered (gdb_stdlog, + "\nRead die from %s of %s:\n", + reader->buffer == dwarf2_per_objfile->info.buffer + ? ".debug_info" + : reader->buffer == dwarf2_per_objfile->types.buffer + ? ".debug_types" + : "unknown section", + reader->abfd->filename); dump_die (result, dwarf2_die_debug); } @@ -5735,9 +6115,7 @@ read_die_and_children_1 (const struct di store_in_ref_table (die, reader->cu); if (has_children) - { - die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die); - } + die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die); else { die->child = NULL; @@ -5813,11 +6191,10 @@ read_full_die (const struct die_reader_s abbrev = dwarf2_lookup_abbrev (abbrev_number, cu); if (!abbrev) - { - error (_("Dwarf Error: could not find abbrev number %d [in module %s]"), - abbrev_number, - bfd_get_filename (abfd)); - } + error (_("Dwarf Error: could not find abbrev number %d [in module %s]"), + abbrev_number, + bfd_get_filename (abfd)); + die = dwarf_alloc_die (cu, abbrev->num_attrs); die->offset = offset; die->tag = abbrev->tag; @@ -6273,6 +6650,7 @@ read_partial_die (struct partial_die_inf switch (part_die->tag) { case DW_TAG_compile_unit: + case DW_TAG_type_unit: /* Compilation units have a DW_AT_name that is a filename, not a source language identifier. */ case DW_TAG_enumeration_type: @@ -6435,7 +6813,10 @@ find_partial_die_in_comp_unit (unsigned return lookup_die; } -/* Find a partial DIE at OFFSET, which may or may not be in CU. */ +/* Find a partial DIE at OFFSET, which may or may not be in CU, + except in the case of .debug_types DIEs which do not reference + outside their CU (they do however referencing other types via + DW_FORM_sig8). */ static struct partial_die_info * find_partial_die (unsigned int offset, struct dwarf2_cu *cu) @@ -6443,6 +6824,14 @@ find_partial_die (unsigned int offset, s struct dwarf2_per_cu_data *per_cu = NULL; struct partial_die_info *pd = NULL; + if (cu->per_cu->from_debug_types) + { + pd = find_partial_die_in_comp_unit (offset, cu); + if (pd != NULL) + return pd; + goto not_found; + } + if (offset_in_cu_p (&cu->header, offset)) { pd = find_partial_die_in_comp_unit (offset, cu); @@ -6496,6 +6885,8 @@ find_partial_die (unsigned int offset, s pd = find_partial_die_in_comp_unit (offset, per_cu->cu); } + not_found: + if (pd == NULL) internal_error (__FILE__, __LINE__, _("could not find partial DIE 0x%x in cache [from module %s]\n"), @@ -6649,6 +7040,14 @@ read_attribute_value (struct attribute * DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr); info_ptr += 8; break; + case DW_FORM_sig8: + /* Convert the signature to something we can record in DW_UNSND + for later lookup. + NOTE: This is NULL if the type wasn't found. */ + DW_SIGNATURED_TYPE (attr) = + lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr)); + info_ptr += 8; + break; case DW_FORM_ref_udata: DW_ADDR (attr) = (cu->header.offset + read_unsigned_leb128 (abfd, info_ptr, &bytes_read)); @@ -7111,6 +7510,25 @@ dwarf2_attr (struct die_info *die, unsig return NULL; } +/* Return the named attribute or NULL if not there, + but do not follow DW_AT_specification, etc. + This is for use in contexts where we're reading .debug_types dies. + Following DW_AT_specification, DW_AT_abstract_origin will take us + back up the chain, and we want to go down. */ + +static struct attribute * +dwarf2_attr_no_follow (struct die_info *die, unsigned int name, + struct dwarf2_cu *cu) +{ + unsigned int i; + + for (i = 0; i < die->num_attrs; ++i) + if (die->attrs[i].name == name) + return &die->attrs[i]; + + return NULL; +} + /* Return non-zero iff the attribute NAME is defined for the given DIE, and holds a non-zero value. This function should only be used for DW_FORM_flag attributes. */ @@ -8266,8 +8684,8 @@ die_type (struct die_info *die, struct d /* A missing DW_AT_type represents a void type. */ return objfile_type (cu->objfile)->builtin_void; } - else - type_die = follow_die_ref (die, type_attr, &cu); + + type_die = follow_die_ref_or_sig (die, type_attr, &cu); type = tag_type_to_type (type_die, cu); if (!type) @@ -8292,7 +8710,7 @@ die_containing_type (struct die_info *di type_attr = dwarf2_attr (die, DW_AT_containing_type, cu); if (type_attr) { - type_die = follow_die_ref (die, type_attr, &cu); + type_die = follow_die_ref_or_sig (die, type_attr, &cu); type = tag_type_to_type (type_die, cu); } if (!type) @@ -8731,6 +9149,8 @@ dwarf_tag_name (unsigned tag) return "DW_TAG_condition"; case DW_TAG_shared_type: return "DW_TAG_shared_type"; + case DW_TAG_type_unit: + return "DW_TAG_type_unit"; case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; case DW_TAG_HP_array_descriptor: @@ -8946,6 +9366,9 @@ dwarf_attr_name (unsigned attr) return "DW_AT_pure"; case DW_AT_recursive: return "DW_AT_recursive"; + /* DWARF 4 values. */ + case DW_AT_signature: + return "DW_AT_signature"; /* SGI/MIPS extensions. */ #ifdef MIPS /* collides with DW_AT_HP_block_index */ case DW_AT_MIPS_fde: @@ -9017,6 +9440,8 @@ dwarf_attr_name (unsigned attr) return "DW_AT_body_end"; case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + case DW_AT_GNU_odr_signature: + return "DW_AT_GNU_odr_signature"; /* VMS extensions. */ case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address"; @@ -9084,6 +9509,14 @@ dwarf_form_name (unsigned form) return "DW_FORM_ref_udata"; case DW_FORM_indirect: return "DW_FORM_indirect"; + case DW_FORM_sec_offset: + return "DW_FORM_sec_offset"; + case DW_FORM_exprloc: + return "DW_FORM_exprloc"; + case DW_FORM_flag_present: + return "DW_FORM_flag_present"; + case DW_FORM_sig8: + return "DW_FORM_sig8"; case GDB_FORM_cached_string: return "GDB_FORM_cached_string"; default: @@ -9629,6 +10062,13 @@ dump_die_shallow (struct ui_file *f, int case DW_FORM_sdata: fprintf_unfiltered (f, "constant: %ld", DW_UNSND (&die->attrs[i])); break; + case DW_FORM_sig8: + if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL) + fprintf_unfiltered (f, "signatured type, offset: 0x%x", + DW_SIGNATURED_TYPE (&die->attrs[i])->offset); + else + fprintf_unfiltered (f, "signatured type, offset: unknown"); + break; case DW_FORM_string: case DW_FORM_strp: case GDB_FORM_cached_string: @@ -9766,9 +10206,11 @@ dwarf2_get_attr_constant_value (struct a } /* THIS_CU has a reference to PER_CU. If necessary, load the new compilation - unit and add it to our queue. */ + unit and add it to our queue. + The result is non-zero if PER_CU was queued, otherwise the result is zero + meaning either PER_CU is already queued or it is already loaded. */ -static void +static int maybe_queue_comp_unit (struct dwarf2_cu *this_cu, struct dwarf2_per_cu_data *per_cu) { @@ -9778,18 +10220,44 @@ maybe_queue_comp_unit (struct dwarf2_cu /* If it's already on the queue, we have nothing to do. */ if (per_cu->queued) - return; + return 0; /* If the compilation unit is already loaded, just mark it as used. */ if (per_cu->cu != NULL) { per_cu->cu->last_used = 0; - return; + return 0; } /* Add it to the queue. */ queue_comp_unit (per_cu, this_cu->objfile); + + return 1; +} + +/* Follow reference or signature attribute ATTR of SRC_DIE. + On entry *REF_CU is the CU of SRC_DIE. + On exit *REF_CU is the CU of the result. */ + +static struct die_info * +follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr, + struct dwarf2_cu **ref_cu) +{ + struct die_info *die; + + if (is_ref_attr (attr)) + die = follow_die_ref (src_die, attr, ref_cu); + else if (attr->form == DW_FORM_sig8) + die = follow_die_sig (src_die, attr, ref_cu); + else + { + dump_die_for_error (src_die); + error (_("Dwarf Error: Expected reference attribute [in module %s]"), + (*ref_cu)->objfile->name); + } + + return die; } /* Follow reference attribute ATTR of SRC_DIE. @@ -9805,15 +10273,27 @@ follow_die_ref (struct die_info *src_die struct die_info temp_die; struct dwarf2_cu *target_cu, *cu = *ref_cu; + gdb_assert (cu->per_cu != NULL); + offset = dwarf2_get_ref_die_offset (attr); - if (! offset_in_cu_p (&cu->header, offset)) + if (cu->per_cu->from_debug_types) + { + /* .debug_types CUs cannot reference anything outside their CU. + If they need to, they have to reference a signatured type via + DW_FORM_sig8. */ + if (! offset_in_cu_p (&cu->header, offset)) + goto not_found; + target_cu = cu; + } + else if (! offset_in_cu_p (&cu->header, offset)) { struct dwarf2_per_cu_data *per_cu; per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile); /* If necessary, add it to the queue and load its DIEs. */ - maybe_queue_comp_unit (cu, per_cu); + if (maybe_queue_comp_unit (cu, per_cu)) + load_full_comp_unit (per_cu, cu->objfile); target_cu = per_cu->cu; } @@ -9826,9 +10306,164 @@ follow_die_ref (struct die_info *src_die if (die) return die; - error (_("Dwarf Error: Cannot find DIE at 0x%lx referenced from DIE " - "at 0x%lx [in module %s]"), - (long) offset, (long) src_die->offset, cu->objfile->name); + not_found: + + error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE " + "at 0x%x [in module %s]"), + offset, src_die->offset, cu->objfile->name); +} + +/* Follow the signature attribute ATTR in SRC_DIE. + On entry *REF_CU is the CU of SRC_DIE. + On exit *REF_CU is the CU of the result. */ + +static struct die_info * +follow_die_sig (struct die_info *src_die, struct attribute *attr, + struct dwarf2_cu **ref_cu) +{ + struct objfile *objfile = (*ref_cu)->objfile; + struct die_info temp_die; + struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr); + struct dwarf2_cu *sig_cu; + struct die_info *die; + + /* sig_type will be NULL if the signatured type is missing from + the debug info. */ + if (sig_type == NULL) + error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE " + "at 0x%x [in module %s]"), + src_die->offset, objfile->name); + + /* If necessary, add it to the queue and load its DIEs. */ + + if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu)) + read_signatured_type (objfile, sig_type); + + gdb_assert (sig_type->per_cu.cu != NULL); + + sig_cu = sig_type->per_cu.cu; + temp_die.offset = sig_cu->header.offset + sig_type->type_offset; + die = htab_find_with_hash (sig_cu->die_hash, &temp_die, temp_die.offset); + if (die) + { + *ref_cu = sig_cu; + return die; + } + + error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced from DIE " + "at 0x%x [in module %s]"), + sig_type->type_offset, src_die->offset, objfile->name); +} + +/* Given an offset of a signatured type, return its signatured_type. */ + +static struct signatured_type * +lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset) +{ + gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer + offset; + unsigned int length, initial_length_size; + unsigned int sig_offset; + struct signatured_type find_entry, *type_sig; + + length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size); + sig_offset = (initial_length_size + + 2 /*version*/ + + (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/ + + 1 /*address_size*/); + find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset); + type_sig = htab_find (dwarf2_per_objfile->signatured_types, &find_entry); + + /* This is only used to lookup previously recorded types. + If we didn't find it, it's our bug. */ + gdb_assert (type_sig != NULL); + gdb_assert (offset == type_sig->offset); + + return type_sig; +} + +/* Read in signatured type at OFFSET and build its CU and die(s). */ + +static void +read_signatured_type_at_offset (struct objfile *objfile, + unsigned int offset) +{ + struct signatured_type *type_sig; + + /* We have the section offset, but we need the signature to do the + hash table lookup. */ + type_sig = lookup_signatured_type_at_offset (objfile, offset); + + gdb_assert (type_sig->per_cu.cu == NULL); + + read_signatured_type (objfile, type_sig); + + gdb_assert (type_sig->per_cu.cu != NULL); +} + +/* Read in a signatured type and build its CU and DIEs. */ + +static void +read_signatured_type (struct objfile *objfile, + struct signatured_type *type_sig) +{ + gdb_byte *types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset; + struct die_reader_specs reader_specs; + struct dwarf2_cu *cu; + ULONGEST signature; + struct cleanup *back_to, *free_cu_cleanup; + struct attribute *attr; + + gdb_assert (type_sig->per_cu.cu == NULL); + + cu = xmalloc (sizeof (struct dwarf2_cu)); + memset (cu, 0, sizeof (struct dwarf2_cu)); + obstack_init (&cu->comp_unit_obstack); + cu->objfile = objfile; + type_sig->per_cu.cu = cu; + cu->per_cu = &type_sig->per_cu; + + /* If an error occurs while loading, release our storage. */ + free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); + + types_ptr = read_type_comp_unit_head (&cu->header, &signature, + types_ptr, objfile->obfd); + gdb_assert (signature == type_sig->signature); + + cu->die_hash + = htab_create_alloc_ex (cu->header.length / 12, + die_hash, + die_eq, + NULL, + &cu->comp_unit_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + + dwarf2_read_abbrevs (cu->objfile->obfd, cu); + back_to = make_cleanup (dwarf2_free_abbrev_table, cu); + + init_cu_die_reader (&reader_specs, cu); + + cu->dies = read_die_and_children (&reader_specs, types_ptr, &types_ptr, + NULL /*parent*/); + + /* We try not to read any attributes in this function, because not + all objfiles needed for references have been loaded yet, and symbol + table processing isn't initialized. But we have to set the CU language, + or we won't be able to build types correctly. */ + attr = dwarf2_attr (cu->dies, DW_AT_language, cu); + if (attr) + set_cu_language (DW_UNSND (attr), cu); + else + set_cu_language (language_minimal, cu); + + do_cleanups (back_to); + + /* We've successfully allocated this compilation unit. Let our caller + clean it up when finished with it. */ + discard_cleanups (free_cu_cleanup); + + type_sig->per_cu.cu->read_in_chain = dwarf2_per_objfile->read_in_chain; + dwarf2_per_objfile->read_in_chain = &type_sig->per_cu; } /* Decode simple location descriptions. @@ -10764,8 +11399,8 @@ dwarf2_per_cu_addr_size (struct dwarf2_p } } -/* Locate the compilation unit from CU's objfile which contains the - DIE at OFFSET. Raises an error on failure. */ +/* Locate the .debug_info compilation unit from CU's objfile which contains + the DIE at OFFSET. Raises an error on failure. */ static struct dwarf2_per_cu_data * dwarf2_find_containing_comp_unit (unsigned int offset, ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-07-15 1:13 ` Doug Evans @ 2009-07-15 19:28 ` Tom Tromey 2009-07-16 1:25 ` Doug Evans 2009-07-21 0:10 ` Cary Coutant 0 siblings, 2 replies; 11+ messages in thread From: Tom Tromey @ 2009-07-15 19:28 UTC (permalink / raw) To: Doug Evans; +Cc: gdb-patches >>>>> "Doug" == Doug Evans <dje@google.com> writes: Doug> How about this? Doug> It addresses the issues raised here: Doug> http://sourceware.org/ml/gdb-patches/2009-06/msg00689.html Now that you are a global maintainer (congratulations!) I think you ought to self-approve it. There has been plenty of time for comments. BTW, what is the status of the GCC patch? Tom ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-07-15 19:28 ` Tom Tromey @ 2009-07-16 1:25 ` Doug Evans 2009-07-21 0:10 ` Cary Coutant 1 sibling, 0 replies; 11+ messages in thread From: Doug Evans @ 2009-07-16 1:25 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On Wed, Jul 15, 2009 at 11:57 AM, Tom Tromey<tromey@redhat.com> wrote: >>>>>> "Doug" == Doug Evans <dje@google.com> writes: > > Doug> How about this? > Doug> It addresses the issues raised here: > Doug> http://sourceware.org/ml/gdb-patches/2009-06/msg00689.html > > Now that you are a global maintainer (congratulations!) I think you > ought to self-approve it. There has been plenty of time for comments. Cool. :-) > BTW, what is the status of the GCC patch? I don't know if it's changed, but I'll get an update from Cary. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-07-15 19:28 ` Tom Tromey 2009-07-16 1:25 ` Doug Evans @ 2009-07-21 0:10 ` Cary Coutant 1 sibling, 0 replies; 11+ messages in thread From: Cary Coutant @ 2009-07-21 0:10 UTC (permalink / raw) To: Tom Tromey; +Cc: Doug Evans, gdb-patches > BTW, what is the status of the GCC patch? I have one bug that I need to fix on the dwarf4 branch in gcc, then I need to do another merge from trunk and fix any breakage that causes. After that, the branch should be ready to merge into the trunk. I hope to have that bug fixed this week. -cary ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-06-25 20:28 ` Doug Evans 2009-06-25 20:49 ` Tom Tromey @ 2009-06-26 1:33 ` Daniel Jacobowitz 1 sibling, 0 replies; 11+ messages in thread From: Daniel Jacobowitz @ 2009-06-26 1:33 UTC (permalink / raw) To: Doug Evans; +Cc: tromey, gdb-patches, ccoutant On Thu, Jun 25, 2009 at 01:28:02PM -0700, Doug Evans wrote: > > Doug> + Â types_htab = htab_create_alloc_ex (41, > > Doug> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â hash_type_signature, > > Doug> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â eq_type_signature, > > Doug> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NULL, > > Doug> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &objfile->objfile_obstack, > > Doug> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â hashtab_obstack_allocate, > > Doug> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â dummy_obstack_deallocate); > > > > This is just a side note -- I've seen a few hash tables allocated on > > obstacks. Â Doesn't resizing the table waste memory? > > IIRC I use the noresize traversal routine. > It's not ideal, no. FWIW, 3 of the other 4 hash tables are on the compilation unit obstack, which is temporary. The exception is type_hash which I found to be performance-sensitive (both time and space) and have a pretty good initial size estimate. Obstacks are a big win for that sort of thing. This one probably fills the same niche, but doesn't have an initial estimate. So I'm not sure what I think about keeping it on the obstack. If the contents can go on the obstack instead, that's probably enough. > > Doug> + Â if (this_cu->from_debug_types) > > Doug> + Â Â { > > Doug> + Â Â Â /* ??? How come this is for .debug_types only? Â */ > > Doug> + Â Â Â this_cu->offset = cu.header.offset; > > Doug> + Â Â Â this_cu->length = cu.header.length + cu.header.initial_length_size; > > > > Daniel has asked before for "no new FIXMEs". Â You can't escape this by > > spelling it "???" :-) > > Well, that one was an oversight (these patches drag on and my eyes > tend to glaze over ...). > While as a general rule I don't disagree, it's kinda odd to see others > add new functionality with open issues. Yes, we're (me included) not totally consistent on this - but it's a sure way to get reviewers to chew on you, as you know :-) As a general extension to the general rule, "FIXME: Foo doesn't work" makes me happier than "FIXME: What about foo?". I particularly don't like FIXMEs with questions in them; we should know what works and what doesn't. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-06-25 19:47 ` Tom Tromey 2009-06-25 20:28 ` Doug Evans @ 2009-06-26 0:01 ` Cary Coutant 2009-06-26 0:54 ` Doug Evans 1 sibling, 1 reply; 11+ messages in thread From: Cary Coutant @ 2009-06-26 0:01 UTC (permalink / raw) To: tromey; +Cc: Doug Evans, gdb-patches > I'm curious about one thing on this page, and I thought I'd take the > opportunity to ask. DW_TAG_type_unit may have a DW_AT_language child. > But, the language is not mentioned in the suggested method for > computing a type's signature. This seems strange to me: either the > language matters (in which case, it seems like it ought to be in the > signature); or the language does not matter, in which case, why > mention it? DW_AT_language was a late addition, and if I recall correctly, it was at Doug's request because there were still some places in gdb where the language mattered. It's an attribute of the type_unit (just like it is of the compile_unit), not of the type itself, so it's not involved in computing the type signature. Theoretically, if two type definitions from different languages generate the same signature, they're still the same type, and should be merged together. On the other hand, if the language really does matter to gdb, maybe they shouldn't be merged. I'm not sure it's likely enough to matter much, although I think it would be desirable for a C type and the same type in C++ to have the same signature. I had the impression that the dependence on language was a wart, and that ideally, it really shouldn't be necessary, so the language attribute is there only as helpful extra information. > One concern I have is whether there is any chance that the > specification will change between now and when DWARF-4 is published. The DWARF proposal (after a long drawn-out process to finalize the details of the signature computation) is final, and is being incorporated into the next draft specification. The editor has promised me that the new DW_TAG and DW_AT codes are cast in stone. DWARF-4 is closed to new issues now, and I think the chances of any changes are virtually nil. -cary ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA] comdat types 2009-06-26 0:01 ` Cary Coutant @ 2009-06-26 0:54 ` Doug Evans 0 siblings, 0 replies; 11+ messages in thread From: Doug Evans @ 2009-06-26 0:54 UTC (permalink / raw) To: Cary Coutant; +Cc: tromey, gdb-patches On Thu, Jun 25, 2009 at 5:01 PM, Cary Coutant<ccoutant@google.com> wrote: >> I'm curious about one thing on this page, and I thought I'd take the >> opportunity to ask. DW_TAG_type_unit may have a DW_AT_language child. >> But, the language is not mentioned in the suggested method for >> computing a type's signature. This seems strange to me: either the >> language matters (in which case, it seems like it ought to be in the >> signature); or the language does not matter, in which case, why >> mention it? > > DW_AT_language was a late addition, and if I recall correctly, it was > at Doug's request because there were still some places in gdb where > the language mattered. It's an attribute of the type_unit (just like > it is of the compile_unit), not of the type itself, so it's not > involved in computing the type signature. Theoretically, if two type > definitions from different languages generate the same signature, > they're still the same type, and should be merged together. On the > other hand, if the language really does matter to gdb, maybe they > shouldn't be merged. I'm not sure it's likely enough to matter much, > although I think it would be desirable for a C type and the same type > in C++ to have the same signature. I had the impression that the > dependence on language was a wart, and that ideally, it really > shouldn't be necessary, so the language attribute is there only as > helpful extra information. I looked back, and apparently it there's by request of the dwarf committee. Since it's there I made use of it, but that can change of course. ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2009-07-20 21:36 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-06-20 0:04 [RFA] comdat types Doug Evans 2009-06-25 19:47 ` Tom Tromey 2009-06-25 20:28 ` Doug Evans 2009-06-25 20:49 ` Tom Tromey 2009-07-15 1:13 ` Doug Evans 2009-07-15 19:28 ` Tom Tromey 2009-07-16 1:25 ` Doug Evans 2009-07-21 0:10 ` Cary Coutant 2009-06-26 1:33 ` Daniel Jacobowitz 2009-06-26 0:01 ` Cary Coutant 2009-06-26 0:54 ` Doug Evans
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox