From: Doug Evans Date: Mon, 20 Jul 2009 21:21:17 +0000 (+0000) Subject: Add support for "comdat types" from DWARF4. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=348e048f0cbdfbd035ca7b7820b7a6bf02dce1e0;p=binutils-gdb.git 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. (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 --git a/gdb/ChangeLog b/gdb/ChangeLog index b3f386c387d..58a295d65c8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,58 @@ +2009-07-20 Doug Evans + + 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. + (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. + 2009-07-20 Ulrich Weigand * arch-utils.c (gdbarch_info_fill): Only reference GDB_OSABI_DEFAULT diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index d294aea9364..445bab8c562 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -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_per_objfile; #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 int, struct dwarf2_cu *); 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 obstack *, 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_offset (struct attribute *); 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, asection *sectp, void *ignore_ptr) 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 *objfile, int mainline) 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_unit_head *header, gdb_byte *info_ptr, 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 dwarf2_cu *cu, 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 objfile *objfile, 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 objfile *objfile, /* 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 objfile *objfile, 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 objfile *objfile, int mainline) 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_per_cu_data *this_cu, 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 *info_ptr, 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_data *per_cu, struct objfile *objfile) 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_symtab *pst) 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_cu_data *per_cu, struct objfile *objfile) 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_cu_data *per_cu, struct objfile *objfile) 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, struct dwarf2_cu *cu) 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, struct dwarf2_cu *cu) 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 = ""; + + 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 *die, struct dwarf2_cu *cu) 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 *die, struct dwarf2_cu *cu) 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_specs *reader, { 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, struct dwarf2_cu *cu) { 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_reader_specs *reader, 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 die_reader_specs *reader, 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_specs *reader, 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_info *part_die, 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 int offset, struct dwarf2_cu *cu) 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, struct dwarf2_cu *cu) 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, struct dwarf2_cu *cu) 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 *attr, unsigned form, 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, unsigned int name, struct dwarf2_cu *cu) 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 dwarf2_cu *cu) /* 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 *die, struct dwarf2_cu *cu) 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: @@ -9084,6 +9507,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 +10060,13 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) 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 +10204,11 @@ dwarf2_get_attr_constant_value (struct attribute *attr, int default_value) } /* 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 +10218,44 @@ maybe_queue_comp_unit (struct dwarf2_cu *this_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 +10271,27 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr, 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 +10304,164 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr, 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 +11397,8 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) } } -/* 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,