diff options
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 419 |
1 files changed, 252 insertions, 167 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index e8d696923d8..00ebaeeb024 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -368,11 +368,18 @@ struct dwarf2_per_cu_data any of the current compilation units are processed. */ unsigned long queued : 1; + /* Set iff currently read in. */ + struct dwarf2_cu *cu; + /* Only set during full symbol reading. */ struct partial_symtab *psymtab; - /* Set iff currently read in. */ - struct dwarf2_cu *cu; + /* If full symbols for this CU have been read in, then this field + holds a map of DIE offsets to types. It isn't always possible + to reconstruct this information later, so we have to preserve + it. */ + + htab_t type_hash; }; /* The line number information for a compilation unit (found in the @@ -657,7 +664,7 @@ struct field_info compilation units. Set this to zero to disable caching. Cache sizes of up to at least twenty will improve startup time for typical inter-CU-reference binaries, at an obvious memory cost. */ -static unsigned int dwarf2_max_cache_age = 5; +static int dwarf2_max_cache_age = 5; /* Various complaints about symbol reading that don't abort the process */ @@ -871,7 +878,8 @@ static void read_type_die (struct die_info *, struct dwarf2_cu *); static char *determine_prefix (struct die_info *die, struct dwarf2_cu *); -static char *typename_concat (const char *prefix, const char *suffix); +static char *typename_concat (struct obstack *, const char *prefix, const char *suffix, + struct dwarf2_cu *); static void read_typedef (struct die_info *, struct dwarf2_cu *); @@ -1059,7 +1067,7 @@ static void free_one_comp_unit (void *); static void free_cached_comp_units (void *); -static void age_cached_comp_units (void *); +static void age_cached_comp_units (void); static void free_one_cached_comp_unit (void *); @@ -1466,10 +1474,6 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) cu.list_in_scope = &file_symbols; - cu.partial_dies = NULL; - - cu.read_in_chain = NULL; - /* Read the abbrevs for this compilation unit into a table */ dwarf2_read_abbrevs (abfd, &cu); make_cleanup (dwarf2_free_abbrev_table, &cu); @@ -1492,13 +1496,12 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) objfile->global_psymbols.next, objfile->static_psymbols.next); - if (comp_unit_die.dirname) - pst->dirname = xstrdup (comp_unit_die.dirname); + if (comp_unit_die.dirname) + pst->dirname = xstrdup (comp_unit_die.dirname); pst->read_symtab_private = (char *) obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo)); DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf2_per_objfile->info_buffer; - PST_PRIVATE (pst)->type_hash = NULL; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); /* Store the function that reads in the rest of the symbol table */ @@ -1510,18 +1513,21 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) per_cu = dwarf2_find_comp_unit (cu.header.offset, objfile); - /* If we were already read in, free ourselves to read in again. - Yes, this is pointless duplication. Fixing this will provide - a nice speed boost but require a lot of editing in this - function. */ + /* If this compilation unit was already read in, free the + cached copy in order to read it in again. This is + necessary because we skipped some symbols when we first + read in the compilation unit (see load_partial_dies). + This problem could be avoided, but the benefit is + unclear. */ if (per_cu->cu != NULL) free_one_cached_comp_unit (per_cu->cu); cu.per_cu = per_cu; - /* Note that this is a pointer to our stack frame. It will - be cleaned up in free_stack_comp_unit when we finish with - this compilation unit. */ + /* Note that this is a pointer to our stack frame, being + added to a global data structure. It will be cleaned up + in free_stack_comp_unit when we finish with this + compilation unit. */ per_cu->cu = &cu; per_cu->psymtab = pst; @@ -1609,25 +1615,24 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) cu->objfile = objfile; info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, abfd); - /* Complete the cu_header */ + /* Complete the cu_header. */ cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer; cu->header.first_die_ptr = info_ptr; cu->header.cu_head_ptr = beg_of_comp_unit; - cu->partial_dies = NULL; - - /* Read the abbrevs for this compilation unit into a table */ + /* Read the abbrevs for this compilation unit into a table. */ dwarf2_read_abbrevs (abfd, cu); back_to = make_cleanup (dwarf2_free_abbrev_table, cu); - /* Read the compilation unit die */ + /* Read the compilation unit die. */ abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu); info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, abfd, info_ptr, cu); - /* Set the language we're debugging */ + /* Set the language we're debugging. */ set_cu_language (comp_unit_die.language, cu); + /* Link this compilation unit into the compilation unit tree. */ this_cu->cu = cu; cu->per_cu = this_cu; @@ -1791,7 +1796,8 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, /* Functions used to compute the fully scoped name of a partial DIE. Normally, this is simple. For C++, the parent DIE's fully scoped - name is concatenated with "::" and the partial DIE's name. + name is concatenated with "::" and the partial DIE's name. For + Java, the same thing occurs except that "." is used instead of "::". Enumerators are an exception; they use the scope of their parent enumeration type, i.e. the name of the enumeration type is not prepended to the enumerator. @@ -1846,8 +1852,8 @@ partial_die_parent_scope (struct partial_die_info *pdi, if (grandparent_scope == NULL) parent->scope = parent->name; else - parent->scope = obconcat (&cu->comp_unit_obstack, grandparent_scope, - "::", parent->name); + parent->scope = typename_concat (&cu->comp_unit_obstack, grandparent_scope, + parent->name, cu); } else if (parent->tag == DW_TAG_enumeration_type) /* Enumerators should not get the name of the enumeration as a prefix. */ @@ -1879,7 +1885,7 @@ partial_die_full_name (struct partial_die_info *pdi, if (parent_scope == NULL) return NULL; else - return concat (parent_scope, "::", pdi->name, NULL); + return typename_concat (NULL, parent_scope, pdi->name, cu); } static void @@ -1997,14 +2003,16 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) return; add_psymbol_to_list (actual_name, strlen (actual_name), STRUCT_DOMAIN, LOC_TYPEDEF, - cu->language == language_cplus + (cu->language == language_cplus + || cu->language == language_java) ? &objfile->global_psymbols : &objfile->static_psymbols, 0, (CORE_ADDR) 0, cu->language, objfile); - if (cu->language == language_cplus) + if (cu->language == language_cplus + || cu->language == language_java) { - /* For C++, these implicitly act as typedefs as well. */ + /* For C++ and Java, these implicitly act as typedefs as well. */ add_psymbol_to_list (actual_name, strlen (actual_name), VAR_DOMAIN, LOC_TYPEDEF, &objfile->global_psymbols, @@ -2014,7 +2022,8 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) case DW_TAG_enumerator: add_psymbol_to_list (actual_name, strlen (actual_name), VAR_DOMAIN, LOC_CONST, - cu->language == language_cplus + (cu->language == language_cplus + || cu->language == language_java) ? &objfile->global_psymbols : &objfile->static_psymbols, 0, (CORE_ADDR) 0, cu->language, objfile); @@ -2094,7 +2103,8 @@ static void guess_structure_name (struct partial_die_info *struct_pdi, struct dwarf2_cu *cu) { - if (cu->language == language_cplus + if ((cu->language == language_cplus + || cu->language == language_java) && cu->has_namespace_info == 0 && struct_pdi->has_children) { @@ -2524,7 +2534,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) /* Aging is a very important performance improvement. My testing shows a factor of six loss from disabling the caching. */ - age_cached_comp_units (NULL); + age_cached_comp_units (); } do_cleanups (back_to); @@ -2928,7 +2938,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu)) return; - if (cu->language == language_cplus) + if (cu->language == language_cplus + || cu->language == language_java) { struct dwarf2_cu *spec_cu; struct die_info *spec_die = die_specification (die, cu, &spec_cu); @@ -3728,10 +3739,13 @@ static int is_vtable_name (const char *name, struct dwarf2_cu *cu) { static const char vptr[] = "_vptr"; + static const char vtable[] = "vtable"; - /* C++ and some implementations of Java use this name. */ - if (strncmp (name, vptr, sizeof (vptr) - 1) == 0 - && is_cplus_marker (name[sizeof (vptr) - 1])) + /* Look for the C++ and Java forms of the vtable. */ + if ((cu->language == language_java + && strncmp (name, vtable, sizeof (vtable) - 1) == 0) + || (strncmp (name, vptr, sizeof (vptr) - 1) == 0 + && is_cplus_marker (name[sizeof (vptr) - 1]))) return 1; return 0; @@ -3775,7 +3789,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_name, cu); if (attr && DW_STRING (attr)) { - if (cu->language == language_cplus) + if (cu->language == language_cplus + || cu->language == language_java) { char *new_prefix = determine_class_name (die, cu); TYPE_TAG_NAME (type) = obsavestring (new_prefix, @@ -3980,11 +3995,9 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) if (processing_has_namespace_info) { - TYPE_TAG_NAME (type) = obconcat (&objfile->objfile_obstack, - processing_current_prefix, - processing_current_prefix[0] == '\0' - ? "" : "::", - name); + TYPE_TAG_NAME (type) = typename_concat (&objfile->objfile_obstack, + processing_current_prefix, + name, cu); } else { @@ -4008,7 +4021,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) } /* Determine the name of the type represented by DIE, which should be - a named C++ compound type. Return the name in question; the caller + a named C++ or Java compound type. Return the name in question; the caller is responsible for xfree()'ing it. */ static char * @@ -4056,8 +4069,9 @@ determine_class_name (struct die_info *die, struct dwarf2_cu *cu) if (new_prefix == NULL) { const char *name = dwarf2_name (die, cu); - new_prefix = typename_concat (processing_current_prefix, - name ? name : "<<anonymous>>"); + new_prefix = typename_concat (NULL, processing_current_prefix, + name ? name : "<<anonymous>>", + cu); } if (back_to != NULL) @@ -4325,6 +4339,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) const char *name; int is_anonymous; struct die_info *current_die; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); struct dwarf2_cu *spec_cu; name = namespace_name (die, &is_anonymous, cu); @@ -4337,14 +4352,8 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) } else { - /* We need temp_name around because processing_current_prefix - is a const char *. */ - char *temp_name = alloca (strlen (previous_prefix) - + 2 + strlen(name) + 1); - strcpy (temp_name, previous_prefix); - strcat (temp_name, "::"); - strcat (temp_name, name); - + char *temp_name = typename_concat (NULL, previous_prefix, name, cu); + make_cleanup (xfree, temp_name); processing_current_prefix = temp_name; } @@ -4384,6 +4393,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) } processing_current_prefix = previous_prefix; + do_cleanups (back_to); } /* Return the name of the namespace represented by DIE. Set @@ -4634,10 +4644,11 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) type = die_type (die, cu); ftype = lookup_function_type (type); - /* All functions in C++ have prototypes. */ + /* All functions in C++ and Java have prototypes. */ attr = dwarf2_attr (die, DW_AT_prototyped, cu); if ((attr && (DW_UNSND (attr) != 0)) - || cu->language == language_cplus) + || cu->language == language_cplus + || cu->language == language_java) TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED; if (die->child != NULL) @@ -4704,7 +4715,8 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu) name = DW_STRING (attr); } set_die_type (die, init_type (TYPE_CODE_TYPEDEF, 0, - TYPE_FLAG_TARGET_STUB, name, objfile), cu); + TYPE_FLAG_TARGET_STUB, name, objfile), + cu); TYPE_TARGET_TYPE (die->type) = die_type (die, cu); } } @@ -5291,7 +5303,8 @@ load_partial_dies (bfd *abfd, char *info_ptr, int building_psymtab, else if (building_psymtab) add_psymbol_to_list (part_die->name, strlen (part_die->name), VAR_DOMAIN, LOC_CONST, - cu->language == language_cplus + (cu->language == language_cplus + || cu->language == language_java) ? &cu->objfile->global_psymbols : &cu->objfile->static_psymbols, 0, (CORE_ADDR) 0, cu->language, cu->objfile); @@ -5530,7 +5543,13 @@ find_partial_die (unsigned long offset, struct dwarf2_cu *cu, } per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile); - gdb_assert (per_cu != NULL); + + /* If this offset isn't pointing into a known compilation unit, + the debug information is probably corrupted. */ + if (per_cu == NULL) + error ("Dwarf Error: could not find partial DIE containing " + "offset 0x%lx [in module %s]", + (long) offset, bfd_get_filename (cu->objfile->obfd)); if (per_cu->cu == NULL) { @@ -6972,7 +6991,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) read_structure_type, and the correct name is saved in the type. */ - if (cu->language == language_cplus) + if (cu->language == language_cplus + || cu->language == language_java) { struct type *type = SYMBOL_TYPE (sym); @@ -6989,7 +7009,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) } { - /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't + /* NOTE: carlton/2003-11-10: C++ and Java class symbols shouldn't really ever be static objects: otherwise, if you try to, say, break of a class's method and you're in a file which doesn't mention that class, it won't work unless @@ -7000,15 +7020,18 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) struct pending **list_to_add; list_to_add = (cu->list_in_scope == &file_symbols - && cu->language == language_cplus + && (cu->language == language_cplus + || cu->language == language_java) ? &global_symbols : cu->list_in_scope); add_symbol_to_list (sym, list_to_add); /* The semantics of C++ state that "struct foo { ... }" also - defines a typedef for "foo". Synthesize a typedef symbol so - that "ptype foo" works as expected. */ - if (cu->language == language_cplus) + defines a typedef for "foo". A Java class declaration also + defines a typedef for the class. Synthesize a typedef symbol + so that "ptype foo" works as expected. */ + if (cu->language == language_cplus + || cu->language == language_java) { struct symbol *typedef_sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack, @@ -7028,10 +7051,9 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) if (processing_has_namespace_info && processing_current_prefix[0] != '\0') { - SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack, - processing_current_prefix, - "::", - name); + SYMBOL_LINKAGE_NAME (sym) = typename_concat (&objfile->objfile_obstack, + processing_current_prefix, + name, cu); } SYMBOL_CLASS (sym) = LOC_TYPEDEF; SYMBOL_DOMAIN (sym) = VAR_DOMAIN; @@ -7047,10 +7069,9 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) if (processing_has_namespace_info && processing_current_prefix[0] != '\0') { - SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack, - processing_current_prefix, - "::", - name); + SYMBOL_LINKAGE_NAME (sym) = typename_concat (&objfile->objfile_obstack, + processing_current_prefix, + name, cu); } attr = dwarf2_attr (die, DW_AT_const_value, cu); if (attr) @@ -7064,7 +7085,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) struct pending **list_to_add; list_to_add = (cu->list_in_scope == &file_symbols - && cu->language == language_cplus + && (cu->language == language_cplus + || cu->language == language_java) ? &global_symbols : cu->list_in_scope); add_symbol_to_list (sym, list_to_add); @@ -7372,7 +7394,8 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) { struct die_info *parent; - if (cu->language != language_cplus) + if (cu->language != language_cplus + && cu->language != language_java) return NULL; parent = die->parent; @@ -7396,9 +7419,10 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) { int dummy; char *parent_prefix = determine_prefix (parent, cu); - char *retval = typename_concat (parent_prefix, + char *retval = typename_concat (NULL, parent_prefix, namespace_name (parent, &dummy, - cu)); + cu), + cu); xfree (parent_prefix); return retval; } @@ -7431,25 +7455,47 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) } } -/* Return a newly-allocated string formed by concatenating PREFIX, - "::", and SUFFIX, except that if PREFIX is NULL or the empty - string, just return a copy of SUFFIX. */ +/* Return a newly-allocated string formed by concatenating PREFIX and + SUFFIX with appropriate separator. If PREFIX or SUFFIX is NULL or empty, then + simply copy the SUFFIX or PREFIX, respectively. If OBS is non-null, + perform an obconcat, otherwise allocate storage for the result. The CU argument + is used to determine the language and hence, the appropriate separator. */ + +#define MAX_SEP_LEN 2 /* sizeof ("::") */ static char * -typename_concat (const char *prefix, const char *suffix) +typename_concat (struct obstack *obs, const char *prefix, const char *suffix, + struct dwarf2_cu *cu) { - if (prefix == NULL || prefix[0] == '\0') - return xstrdup (suffix); - else - { - char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1); + char *sep; - strcpy (retval, prefix); - strcat (retval, "::"); - strcat (retval, suffix); + if (suffix == NULL || suffix[0] == '\0' || prefix == NULL || prefix[0] == '\0') + sep = ""; + else if (cu->language == language_java) + sep = "."; + else + sep = "::"; + if (obs == NULL) + { + char *retval = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1); + retval[0] = '\0'; + + if (prefix) + { + strcpy (retval, prefix); + strcat (retval, sep); + } + if (suffix) + strcat (retval, suffix); + return retval; } + else + { + /* We have an obstack. */ + return obconcat (obs, prefix, sep, suffix); + } } static struct type * @@ -9342,7 +9388,10 @@ dwarf2_find_containing_comp_unit (unsigned long offset, struct dwarf2_per_cu_data *this_cu; int low, high; - gdb_assert (dwarf2_per_objfile->all_comp_units != NULL); + if (dwarf2_per_objfile->all_comp_units == NULL) + error ("Dwarf Error: offset 0x%lx points outside this " + "compilation unit [in module %s]", + offset, bfd_get_filename (objfile->obfd)); low = 0; high = dwarf2_per_objfile->n_comp_units - 1; @@ -9402,8 +9451,8 @@ dwarf2_find_comp_unit_psymtab (unsigned int offset, struct objfile *objfile) } /* Release one cached compilation unit, CU. We unlink it from the tree - of compilation units, but we don't remove it from the read_in_chain - (so it should not be on that chain to begin with). */ + of compilation units, but we don't remove it from the read_in_chain; + the caller is responsible for that. */ static void free_one_comp_unit (void *data) @@ -9421,52 +9470,6 @@ free_one_comp_unit (void *data) xfree (cu); } -/* Helper function for cleaning up the compilation unit cache. Walk - this objfile's read_in_chain. If AGING, increase the age counter - on each compilation unit, and free any that are too old. Otherwise, - if TARGET_CU, free only that compilation unit, removing it from the - chain. Otherwise free all compilation units. */ - -static void -free_comp_units_worker (struct dwarf2_cu *target_cu, int aging) -{ - struct dwarf2_per_cu_data *per_cu, **last_chain; - - if (aging) - { - dwarf2_clear_marks (dwarf2_per_objfile->read_in_chain); - per_cu = dwarf2_per_objfile->read_in_chain; - while (per_cu != NULL) - { - per_cu->cu->last_used ++; - if (per_cu->cu->last_used <= dwarf2_max_cache_age) - dwarf2_mark (per_cu->cu); - per_cu = per_cu->cu->read_in_chain; - } - } - - per_cu = dwarf2_per_objfile->read_in_chain; - last_chain = &dwarf2_per_objfile->read_in_chain; - while (per_cu != NULL) - { - struct dwarf2_per_cu_data *next_cu; - - next_cu = per_cu->cu->read_in_chain; - - if ((aging && !per_cu->cu->mark) - || (target_cu && per_cu->cu == target_cu) - || (!aging && target_cu == NULL)) - { - free_one_comp_unit (per_cu->cu); - *last_chain = next_cu; - } - else - last_chain = &per_cu->cu->read_in_chain; - - per_cu = next_cu; - } -} - /* This cleanup function is passed the address of a dwarf2_cu on the stack when we're finished with it. We can't free the pointer itself, but be sure to unlink it from the cache. Also release any associated storage @@ -9491,34 +9494,110 @@ free_stack_comp_unit (void *data) /* If we had a per-cu pointer, then we may have other compilation units loaded, so age them now. */ - age_cached_comp_units (NULL); + age_cached_comp_units (); } } +/* Free all cached compilation units. */ + static void free_cached_comp_units (void *data) { - free_comp_units_worker (NULL, 0); + struct dwarf2_per_cu_data *per_cu, **last_chain; + + per_cu = dwarf2_per_objfile->read_in_chain; + last_chain = &dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) + { + struct dwarf2_per_cu_data *next_cu; + + next_cu = per_cu->cu->read_in_chain; + + free_one_comp_unit (per_cu->cu); + *last_chain = next_cu; + + per_cu = next_cu; + } } +/* Increase the age counter on each cached compilation unit, and free + any that are too old. */ + static void -age_cached_comp_units (void *data) +age_cached_comp_units (void) { - free_comp_units_worker (NULL, 1); + struct dwarf2_per_cu_data *per_cu, **last_chain; + + dwarf2_clear_marks (dwarf2_per_objfile->read_in_chain); + per_cu = dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) + { + per_cu->cu->last_used ++; + if (per_cu->cu->last_used <= dwarf2_max_cache_age) + dwarf2_mark (per_cu->cu); + per_cu = per_cu->cu->read_in_chain; + } + + per_cu = dwarf2_per_objfile->read_in_chain; + last_chain = &dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) + { + struct dwarf2_per_cu_data *next_cu; + + next_cu = per_cu->cu->read_in_chain; + + if (!per_cu->cu->mark) + { + free_one_comp_unit (per_cu->cu); + *last_chain = next_cu; + } + else + last_chain = &per_cu->cu->read_in_chain; + + per_cu = next_cu; + } } +/* Remove a single compilation unit from the cache. */ + static void free_one_cached_comp_unit (void *target_cu) { - free_comp_units_worker (target_cu, 0); + struct dwarf2_per_cu_data *per_cu, **last_chain; + + per_cu = dwarf2_per_objfile->read_in_chain; + last_chain = &dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) + { + struct dwarf2_per_cu_data *next_cu; + + next_cu = per_cu->cu->read_in_chain; + + if (per_cu->cu == target_cu) + { + free_one_comp_unit (per_cu->cu); + *last_chain = next_cu; + break; + } + else + last_chain = &per_cu->cu->read_in_chain; + + per_cu = next_cu; + } } +/* A pair of DIE offset and GDB type pointer. We store these + in a hash table separate from the DIEs, and preserve them + when the DIEs are flushed out of cache. */ + struct dwarf2_offset_and_type { unsigned int offset; struct type *type; }; +/* Hash function for a dwarf2_offset_and_type. */ + static hashval_t offset_and_type_hash (const void *item) { @@ -9526,6 +9605,8 @@ offset_and_type_hash (const void *item) return ofs->offset; } +/* Equality function for a dwarf2_offset_and_type. */ + static int offset_and_type_eq (const void *item_lhs, const void *item_rhs) { @@ -9534,13 +9615,12 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) return ofs_lhs->offset == ofs_rhs->offset; } -/* Functions used to regenerate die->type, given a tree of DIEs and an - already completed symtab. Types without names can't necessarily be - reconstituted, so we save them. */ +/* Set the type associated with DIE to TYPE. Save it in CU's hash + table if necessary. */ + static void set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) { - htab_t type_hash; struct dwarf2_offset_and_type **slot, ofs; die->type = type; @@ -9548,28 +9628,29 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) if (cu->per_cu == NULL) return; - type_hash = PST_PRIVATE (cu->per_cu->psymtab)->type_hash; - if (type_hash == NULL) - { - type_hash = htab_create_alloc_ex (cu->header.length / 24, - offset_and_type_hash, - offset_and_type_eq, - NULL, - &cu->objfile->objfile_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); - PST_PRIVATE (cu->per_cu->psymtab)->type_hash = type_hash; - } + if (cu->per_cu->type_hash == NULL) + cu->per_cu->type_hash + = htab_create_alloc_ex (cu->header.length / 24, + offset_and_type_hash, + offset_and_type_eq, + NULL, + &cu->objfile->objfile_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + ofs.offset = die->offset; ofs.type = type; slot = (struct dwarf2_offset_and_type **) - htab_find_slot_with_hash (type_hash, &ofs, ofs.offset, INSERT); + htab_find_slot_with_hash (cu->per_cu->type_hash, &ofs, ofs.offset, INSERT); *slot = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (**slot)); **slot = ofs; } +/* Find the type for DIE in TYPE_HASH, or return NULL if DIE does not + have a saved type. */ + static struct type * -get_die_type (struct die_info *die, htab_t type_hash, struct dwarf2_cu *cu) +get_die_type (struct die_info *die, htab_t type_hash) { struct dwarf2_offset_and_type *slot, ofs; @@ -9581,24 +9662,28 @@ get_die_type (struct die_info *die, htab_t type_hash, struct dwarf2_cu *cu) return NULL; } +/* Restore the types of the DIE tree starting at START_DIE from the hash + table saved in CU. */ + static void reset_die_and_siblings_types (struct die_info *start_die, struct dwarf2_cu *cu) { struct die_info *die; - htab_t type_hash; - type_hash = PST_PRIVATE (cu->per_cu->psymtab)->type_hash; - if (type_hash == NULL) + if (cu->per_cu->type_hash == NULL) return; for (die = start_die; die != NULL; die = die->sibling) { - die->type = get_die_type (die, type_hash, cu); + die->type = get_die_type (die, cu->per_cu->type_hash); if (die->child != NULL) reset_die_and_siblings_types (die->child, cu); } } +/* Set the mark field in CU and in every other compilation unit in the + cache that we must keep because we are keeping CU. */ + /* Add a dependence relationship from CU to REF_PER_CU. */ static void |