From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21251 invoked by alias); 10 May 2012 20:14:40 -0000 Received: (qmail 21232 invoked by uid 22791); 10 May 2012 20:14:38 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_BJ,TW_TM,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 10 May 2012 20:14:14 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4AKEEEA024856 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 10 May 2012 16:14:14 -0400 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4AKEBjs019307 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Thu, 10 May 2012 16:14:12 -0400 From: Tom Tromey To: gdb-patches@sourceware.org Subject: Re: [7/10] keep track of dependencies References: <87zk9zabho.fsf@fleche.redhat.com> Date: Thu, 10 May 2012 20:14:00 -0000 In-Reply-To: <87zk9zabho.fsf@fleche.redhat.com> (Tom Tromey's message of "Wed, 25 Apr 2012 12:54:11 -0600") Message-ID: <873977aj58.fsf@fleche.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.95 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-05/txt/msg00387.txt.bz2 >>>>> "Tom" == Tom Tromey writes: Tom> This patch introduces the dependency-tracking code for psymtabs and Tom> symtabs. Oops, I attached the wrong patch in my last mail. Sigh -- renumbering was not a great idea :) Here it is again. I also neglected to mention that this version takes Jan's comments into account. Tom >From 57377dc9e08b5a163bf4841f431e0cf393e9f3e4 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 23 Apr 2012 12:19:58 -0600 Subject: [PATCH 08/10] keep track of dependencies when reading psymtabs and symtabs this almost works but sometimes gives crashes * dwarf2read.c: (dwarf2_per_cu_ptr): New typedef. (struct dwarf2_per_objfile) : New field. (struct dwarf2_per_cu_data) : New field. (dw2_do_instantiate_symtab): Check whether symtab was read in before queueing. (dw2_instantiate_symtab): Add assertion. Call process_cu_includes. (process_psymtab_comp_unit): Compute 'dependencies' for psymtab. (partial_symtab_p): New typedef. (set_partial_user): New function. (dwarf2_build_psymtabs_hard): Use set_partial_user. (scan_partial_symbols): Add imported CU to imported_symtabs. (dwarf2_psymtab_to_symtab): Call process_cu_includes. (psymtab_to_symtab_1): Do nothing if psymtab is readin. (get_symtab, recursively_compute_inclusions) (compute_symtab_includes, process_cu_includes) (process_imported_unit_die): New functions. (process_die) : New case. (dwarf2_per_objfile_free): Free 'imported_symtabs'. --- gdb/dwarf2read.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 221 insertions(+), 3 deletions(-) diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index d34c048..ff1babd 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -148,6 +148,9 @@ struct mapped_index const char *constant_pool; }; +typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr; +DEF_VEC_P (dwarf2_per_cu_ptr); + /* Collection of data recorded per objfile. This hangs off of dwarf2_objfile_data_key. */ @@ -221,6 +224,9 @@ struct dwarf2_per_objfile This is NULL if not allocated yet. The mapping is done via (CU/TU signature + DIE offset) -> type. */ htab_t die_type_hash; + + /* The CUs we recently read. */ + VEC (dwarf2_per_cu_ptr) *just_read_cus; }; static struct dwarf2_per_objfile *dwarf2_per_objfile; @@ -489,6 +495,12 @@ struct dwarf2_per_cu_data /* Data needed by the "quick" functions. */ struct dwarf2_per_cu_quick_data *quick; } v; + + /* The CUs we import using DW_TAG_imported_unit. This is filled in + while reading psymtabs, used to compute the psymtab dependencies, + and then cleared. Then it is filled in again while reading full + symbols, and only deleted when the objfile is destroyed. */ + VEC (dwarf2_per_cu_ptr) *imported_symtabs; }; /* Entry in the signatured_types hash table. */ @@ -1389,6 +1401,9 @@ static void dwarf2_release_queue (void *dummy); static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu); +static int maybe_queue_comp_unit (struct dwarf2_cu *this_cu, + struct dwarf2_per_cu_data *per_cu); + static void process_queue (void); static void find_file_and_directory (struct die_info *die, @@ -1427,6 +1442,8 @@ static void free_dwo_file_cleanup (void *); static void munmap_section_buffer (struct dwarf2_section_info *); +static void process_cu_includes (void); + #if WORDS_BIGENDIAN /* Convert VALUE between big- and little-endian. */ @@ -1948,9 +1965,13 @@ dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu) back_to = make_cleanup (dwarf2_release_queue, NULL); - queue_comp_unit (per_cu); - - load_cu (per_cu); + if (dwarf2_per_objfile->using_index + ? per_cu->v.quick->symtab == NULL + : (per_cu->v.psymtab == NULL || !per_cu->v.psymtab->readin)) + { + queue_comp_unit (per_cu); + load_cu (per_cu); + } process_queue (); @@ -1968,11 +1989,13 @@ dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu) static struct symtab * dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu) { + gdb_assert (dwarf2_per_objfile->using_index); if (!per_cu->v.quick->symtab) { struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL); increment_reading_symtab (); dw2_do_instantiate_symtab (per_cu); + process_cu_includes (); do_cleanups (back_to); } return per_cu->v.quick->symtab; @@ -4109,6 +4132,26 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, (objfile->static_psymbols.list + pst->statics_offset); sort_pst_symbols (pst); + if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs)) + { + int i; + int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs); + struct dwarf2_per_cu_data *iter; + + /* Fill in 'dependencies' here; we fill in 'users' in a + post-pass. */ + pst->number_of_dependencies = len; + pst->dependencies = obstack_alloc (&objfile->objfile_obstack, + len * sizeof (struct symtab *)); + for (i = 0; + VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs, + i, iter); + ++i) + pst->dependencies[i] = iter->v.psymtab; + + VEC_free (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs); + } + if (per_cu->is_debug_types) { /* It's not clear we want to do anything with stmt lists here. @@ -4197,6 +4240,28 @@ psymtabs_addrmap_cleanup (void *o) objfile->psymtabs_addrmap = NULL; } +/* Compute the 'user' field for each psymtab in OBJFILE. */ + +static void +set_partial_user (struct objfile *objfile) +{ + int i; + + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + { + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + struct partial_symtab *pst = per_cu->v.psymtab; + int j; + + for (j = 0; j < pst->number_of_dependencies; ++j) + { + /* Set the 'user' field only if it is not already set. */ + if (pst->dependencies[j]->user == NULL) + pst->dependencies[j]->user = pst; + } + } +} + /* Build the partial symbol table by doing a quick pass through the .debug_info and .debug_abbrev sections. */ @@ -4233,6 +4298,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile) process_psymtab_comp_unit (per_cu, 0); } + set_partial_user (objfile); + objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap, &objfile->objfile_obstack); discard_cleanups (addrmap_cleanup); @@ -4411,6 +4478,9 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, /* Go read the partial unit, if needed. */ if (per_cu->v.psymtab == NULL) process_psymtab_comp_unit (per_cu, 1); + + VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs, + per_cu); } break; default: @@ -5102,6 +5172,8 @@ dwarf2_psymtab_to_symtab (struct partial_symtab *pst) printf_filtered (_("done.\n")); } } + + process_cu_includes (); } /* Reading in full CUs. */ @@ -5188,6 +5260,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) struct cleanup *back_to; int i; + if (pst->readin) + return; + for (i = 0; i < pst->number_of_dependencies; i++) if (!pst->dependencies[i]->readin) { @@ -5413,6 +5488,111 @@ fixup_go_packaging (struct dwarf2_cu *cu) } } +static void compute_symtab_includes (struct dwarf2_per_cu_data *per_cu); + +/* Return the symtab for PER_CU. This works properly regardless of + whether we're using the index or psymtabs. */ + +static struct symtab * +get_symtab (struct dwarf2_per_cu_data *per_cu) +{ + return (dwarf2_per_objfile->using_index + ? per_cu->v.quick->symtab + : per_cu->v.psymtab->symtab); +} + +/* A helper function for computing the list of all symbol tables + included by PER_CU. */ + +static void +recursively_compute_inclusions (VEC (dwarf2_per_cu_ptr) **result, + htab_t all_children, + struct dwarf2_per_cu_data *per_cu) +{ + void **slot; + int ix; + struct dwarf2_per_cu_data *iter; + + slot = htab_find_slot (all_children, per_cu, INSERT); + if (*slot != NULL) + { + /* This inclusion and its children have been processed. */ + return; + } + + *slot = per_cu; + /* Only add a CU if it has a symbol table. */ + if (get_symtab (per_cu) != NULL) + VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu); + + for (ix = 0; + VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter); + ++ix) + recursively_compute_inclusions (result, all_children, iter); +} + +/* Compute the symtab 'includes' fields for the symtab related to + PER_CU. */ + +static void +compute_symtab_includes (struct dwarf2_per_cu_data *per_cu) +{ + if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->imported_symtabs)) + { + int ix, len; + struct dwarf2_per_cu_data *iter; + VEC (dwarf2_per_cu_ptr) *result_children = NULL; + htab_t all_children; + struct symtab *symtab = get_symtab (per_cu); + + /* If we don't have a symtab, we can just skip this case. */ + if (symtab == NULL) + return; + + all_children = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer, + NULL, xcalloc, xfree); + + for (ix = 0; + VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, + ix, iter); + ++ix) + recursively_compute_inclusions (&result_children, all_children, iter); + + /* Now we have a transitive closure of all the included CUs, so + we can convert it to a list of symtabs. */ + len = VEC_length (dwarf2_per_cu_ptr, result_children); + symtab->includes + = obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack, + (len + 1) * sizeof (struct symtab *)); + for (ix = 0; + VEC_iterate (dwarf2_per_cu_ptr, result_children, ix, iter); + ++ix) + symtab->includes[ix] = get_symtab (iter); + symtab->includes[len] = NULL; + + VEC_free (dwarf2_per_cu_ptr, result_children); + htab_delete (all_children); + } +} + +/* Compute the 'includes' field for the symtabs of all the CUs we just + read. */ + +static void +process_cu_includes (void) +{ + int ix; + struct dwarf2_per_cu_data *iter; + + for (ix = 0; + VEC_iterate (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus, + ix, iter); + ++ix) + compute_symtab_includes (iter); + + VEC_free (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus); +} + /* Generate full symbol information for PER_CU, whose DIEs have already been loaded into memory. */ @@ -5494,9 +5674,38 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) pst->readin = 1; } + /* Push it for inclusion processing later. */ + VEC_safe_push (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus, per_cu); + do_cleanups (back_to); } +/* Process an imported unit DIE. */ + +static void +process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_import, cu); + if (attr != NULL) + { + struct dwarf2_per_cu_data *per_cu; + struct symtab *imported_symtab; + sect_offset offset; + + offset = dwarf2_get_ref_die_offset (attr); + per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile); + + /* Queue the unit, if needed. */ + if (maybe_queue_comp_unit (cu, per_cu)) + load_full_comp_unit (per_cu); + + VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs, + per_cu); + } +} + /* Process a die and its children. */ static void @@ -5576,6 +5785,11 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) dwarf_tag_name (die->tag)); read_import_statement (die, cu); break; + + case DW_TAG_imported_unit: + process_imported_unit_die (die, cu); + break; + default: new_symbol (die, NULL, cu); break; @@ -16868,6 +17082,10 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d) ++ix) munmap_section_buffer (section); + for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix) + VEC_free (dwarf2_per_cu_ptr, + dwarf2_per_objfile->all_comp_units[ix]->imported_symtabs); + VEC_free (dwarf2_section_info_def, data->types); if (data->dwo_files) -- 1.7.7.6