* dwarf2read.c (dwarf2_per_objfile): New member quick_file_names_table.

(dwarf2_per_cu_quick_data): Move definition down to "quick functions"
	section.  Delete members lines full_names.  Rename read_lines to
	no_file_data.
	(quick_file_names): New struct.
	(hash_file_name_entry, eq_file_name_entry): New functions.
	(delete_file_name_entry, create_quick_file_names_table): New functions.
	(dwarf2_read_index): Initialize quick_file_names_table.
	(dw2_get_file_names): Renamed from dw2_require_line_header.
	Return pointer to quick_file_names entry.  All callers updated.
	(dw2_get_real_path): Renamed from dw2_require_full_path.
	Replace per_cu arg with pointer to quick_file_names entry.
	All callers updated.
	(dw2_free_cached_file_names): New function.
	(dw2_forget_cached_source_info): Call it (via htab_traverse_noresize).
	(dwarf2_initialize_objfile): Initialize quick_file_names_table in
	the OBJF_READNOW case.
	(dwarf2_free_objfile): Rewrite freeing of quick file names tables.
This commit is contained in:
Doug Evans 2010-12-12 19:19:27 +00:00
parent 1583e7ea01
commit 7b9f3c509c
2 changed files with 242 additions and 126 deletions

View File

@ -1,3 +1,24 @@
2010-12-12 Doug Evans <dje@google.com>
* dwarf2read.c (dwarf2_per_objfile): New member quick_file_names_table.
(dwarf2_per_cu_quick_data): Move definition down to "quick functions"
section. Delete members lines full_names. Rename read_lines to
no_file_data.
(quick_file_names): New struct.
(hash_file_name_entry, eq_file_name_entry): New functions.
(delete_file_name_entry, create_quick_file_names_table): New functions.
(dwarf2_read_index): Initialize quick_file_names_table.
(dw2_get_file_names): Renamed from dw2_require_line_header.
Return pointer to quick_file_names entry. All callers updated.
(dw2_get_real_path): Renamed from dw2_require_full_path.
Replace per_cu arg with pointer to quick_file_names entry.
All callers updated.
(dw2_free_cached_file_names): New function.
(dw2_forget_cached_source_info): Call it (via htab_traverse_noresize).
(dwarf2_initialize_objfile): Initialize quick_file_names_table in
the OBJF_READNOW case.
(dwarf2_free_objfile): Rewrite freeing of quick file names tables.
2010-12-12 Mark Kettenis <kettenis@gnu.org> 2010-12-12 Mark Kettenis <kettenis@gnu.org>
* mips64obsd-tdep.c (floatformats_mips64_quad): New define. * mips64obsd-tdep.c (floatformats_mips64_quad): New define.

View File

@ -211,6 +211,12 @@ struct dwarf2_per_objfile
/* The mapped index, or NULL if .gdb_index is missing or not being used. */ /* The mapped index, or NULL if .gdb_index is missing or not being used. */
struct mapped_index *index_table; struct mapped_index *index_table;
/* When using index_table, this keeps track of all quick_file_names entries.
TUs can share line table entries with CUs or other TUs, and there can be
a lot more TUs than unique line tables, so we maintain a separate table
of all line table entries to support the sharing. */
htab_t quick_file_names_table;
/* Set during partial symbol reading, to prevent queueing of full /* Set during partial symbol reading, to prevent queueing of full
symbols. */ symbols. */
int reading_partial_symbols; int reading_partial_symbols;
@ -391,32 +397,6 @@ struct dwarf2_cu
unsigned int has_namespace_info : 1; unsigned int has_namespace_info : 1;
}; };
/* When using the index (and thus not using psymtabs), each CU has an
object of this type. This is used to hold information needed by
the various "quick" methods. */
struct dwarf2_per_cu_quick_data
{
/* The line table. This can be NULL if there was no line table. */
struct line_header *lines;
/* The file names from the line table. */
const char **file_names;
/* The file names from the line table after being run through
gdb_realpath. */
const char **full_names;
/* The corresponding symbol table. This is NULL if symbols for this
CU have not yet been read. */
struct symtab *symtab;
/* A temporary mark bit used when iterating over all CUs in
expand_symtabs_matching. */
unsigned int mark : 1;
/* True if we've tried to read the line table. */
unsigned int read_lines : 1;
};
/* Persistent data held for a compilation unit, even when not /* Persistent data held for a compilation unit, even when not
processing it. We put a pointer to this structure in the processing it. We put a pointer to this structure in the
read_symtab_private field of the psymtab. If we encounter read_symtab_private field of the psymtab. If we encounter
@ -1644,6 +1624,102 @@ dwarf2_get_section_info (struct objfile *objfile, const char *section_name,
} }
/* DWARF quick_symbols_functions support. */
/* TUs can share .debug_line entries, and there can be a lot more TUs than
unique line tables, so we maintain a separate table of all .debug_line
derived entries to support the sharing.
All the quick functions need is the list of file names. We discard the
line_header when we're done and don't need to record it here. */
struct quick_file_names
{
/* The offset in .debug_line of the line table. We hash on this. */
unsigned int offset;
/* The number of entries in file_names, real_names. */
unsigned int num_file_names;
/* The file names from the line table, after being run through
file_full_name. */
const char **file_names;
/* The file names from the line table after being run through
gdb_realpath. These are computed lazily. */
const char **real_names;
};
/* When using the index (and thus not using psymtabs), each CU has an
object of this type. This is used to hold information needed by
the various "quick" methods. */
struct dwarf2_per_cu_quick_data
{
/* The file table. This can be NULL if there was no file table
or it's currently not read in.
NOTE: This points into dwarf2_per_objfile->quick_file_names_table. */
struct quick_file_names *file_names;
/* The corresponding symbol table. This is NULL if symbols for this
CU have not yet been read. */
struct symtab *symtab;
/* A temporary mark bit used when iterating over all CUs in
expand_symtabs_matching. */
unsigned int mark : 1;
/* True if we've tried to read the file table and found there isn't one.
There will be no point in trying to read it again next time. */
unsigned int no_file_data : 1;
};
/* Hash function for a quick_file_names. */
static hashval_t
hash_file_name_entry (const void *e)
{
const struct quick_file_names *file_data = e;
return file_data->offset;
}
/* Equality function for a quick_file_names. */
static int
eq_file_name_entry (const void *a, const void *b)
{
const struct quick_file_names *ea = a;
const struct quick_file_names *eb = b;
return ea->offset == eb->offset;
}
/* Delete function for a quick_file_names. */
static void
delete_file_name_entry (void *e)
{
struct quick_file_names *file_data = e;
int i;
for (i = 0; i < file_data->num_file_names; ++i)
{
xfree ((void*) file_data->file_names[i]);
if (file_data->real_names)
xfree ((void*) file_data->real_names[i]);
}
/* The space for the struct itself lives on objfile_obstack,
so we don't free it here. */
}
/* Create a quick_file_names hash table. */
static htab_t
create_quick_file_names_table (unsigned int nr_initial_entries)
{
return htab_create_alloc (nr_initial_entries,
hash_file_name_entry, eq_file_name_entry,
delete_file_name_entry, xcalloc, xfree);
}
/* Read in the symbols for PER_CU. OBJFILE is the objfile from which /* Read in the symbols for PER_CU. OBJFILE is the objfile from which
this CU came. */ this CU came. */
@ -1993,6 +2069,8 @@ dwarf2_read_index (struct objfile *objfile)
dwarf2_per_objfile->index_table = map; dwarf2_per_objfile->index_table = map;
dwarf2_per_objfile->using_index = 1; dwarf2_per_objfile->using_index = 1;
dwarf2_per_objfile->quick_file_names_table =
create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
return 1; return 1;
} }
@ -2010,12 +2088,12 @@ dw2_setup (struct objfile *objfile)
/* A helper for the "quick" functions which attempts to read the line /* A helper for the "quick" functions which attempts to read the line
table for THIS_CU. */ table for THIS_CU. */
static void static struct quick_file_names *
dw2_require_line_header (struct objfile *objfile, dw2_get_file_names (struct objfile *objfile,
struct dwarf2_per_cu_data *this_cu) struct dwarf2_per_cu_data *this_cu)
{ {
bfd *abfd = objfile->obfd; bfd *abfd = objfile->obfd;
struct line_header *lh = NULL; struct line_header *lh;
struct attribute *attr; struct attribute *attr;
struct cleanup *cleanups; struct cleanup *cleanups;
struct die_info *comp_unit_die; struct die_info *comp_unit_die;
@ -2026,10 +2104,15 @@ dw2_require_line_header (struct objfile *objfile,
unsigned int bytes_read, buffer_size; unsigned int bytes_read, buffer_size;
struct die_reader_specs reader_specs; struct die_reader_specs reader_specs;
char *name, *comp_dir; char *name, *comp_dir;
void **slot;
struct quick_file_names *qfn;
unsigned int line_offset;
if (this_cu->v.quick->read_lines) if (this_cu->v.quick->file_names != NULL)
return; return this_cu->v.quick->file_names;
this_cu->v.quick->read_lines = 1; /* If we know there is no line data, no point in looking again. */
if (this_cu->v.quick->no_file_data)
return NULL;
init_one_comp_unit (&cu, objfile); init_one_comp_unit (&cu, objfile);
cleanups = make_cleanup (free_stack_comp_unit, &cu); cleanups = make_cleanup (free_stack_comp_unit, &cu);
@ -2064,52 +2147,73 @@ dw2_require_line_header (struct objfile *objfile,
info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr, info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr,
&has_children); &has_children);
lh = NULL;
slot = NULL;
line_offset = 0;
attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, &cu); attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, &cu);
if (attr) if (attr)
{ {
unsigned int line_offset = DW_UNSND (attr); struct quick_file_names find_entry;
line_offset = DW_UNSND (attr);
/* We may have already read in this line header (TU line header sharing).
If we have we're done. */
find_entry.offset = line_offset;
slot = htab_find_slot (dwarf2_per_objfile->quick_file_names_table,
&find_entry, INSERT);
if (*slot != NULL)
{
do_cleanups (cleanups);
this_cu->v.quick->file_names = *slot;
return *slot;
}
lh = dwarf_decode_line_header (line_offset, abfd, &cu); lh = dwarf_decode_line_header (line_offset, abfd, &cu);
} }
if (lh == NULL) if (lh == NULL)
{ {
do_cleanups (cleanups); do_cleanups (cleanups);
return; this_cu->v.quick->no_file_data = 1;
return NULL;
} }
qfn = obstack_alloc (&objfile->objfile_obstack, sizeof (*qfn));
qfn->offset = line_offset;
gdb_assert (slot != NULL);
*slot = qfn;
find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir); find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir);
this_cu->v.quick->lines = lh; qfn->num_file_names = lh->num_file_names;
qfn->file_names = obstack_alloc (&objfile->objfile_obstack,
this_cu->v.quick->file_names lh->num_file_names * sizeof (char *));
= obstack_alloc (&objfile->objfile_obstack,
lh->num_file_names * sizeof (char *));
for (i = 0; i < lh->num_file_names; ++i) for (i = 0; i < lh->num_file_names; ++i)
this_cu->v.quick->file_names[i] = file_full_name (i + 1, lh, comp_dir); qfn->file_names[i] = file_full_name (i + 1, lh, comp_dir);
qfn->real_names = NULL;
free_line_header (lh);
do_cleanups (cleanups); do_cleanups (cleanups);
this_cu->v.quick->file_names = qfn;
return qfn;
} }
/* A helper for the "quick" functions which computes and caches the /* A helper for the "quick" functions which computes and caches the
real path for a given file name from the line table. real path for a given file name from the line table. */
dw2_require_line_header must have been called before this is
invoked. */
static const char * static const char *
dw2_require_full_path (struct objfile *objfile, dw2_get_real_path (struct objfile *objfile,
struct dwarf2_per_cu_data *per_cu, struct quick_file_names *qfn, int index)
int index)
{ {
if (!per_cu->v.quick->full_names) if (qfn->real_names == NULL)
per_cu->v.quick->full_names qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack,
= OBSTACK_CALLOC (&objfile->objfile_obstack, qfn->num_file_names, sizeof (char *));
per_cu->v.quick->lines->num_file_names,
sizeof (char *));
if (!per_cu->v.quick->full_names[index]) if (qfn->real_names[index] == NULL)
per_cu->v.quick->full_names[index] qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
= gdb_realpath (per_cu->v.quick->file_names[index]);
return per_cu->v.quick->full_names[index]; return qfn->real_names[index];
} }
static struct symtab * static struct symtab *
@ -2122,28 +2226,34 @@ dw2_find_last_source_symtab (struct objfile *objfile)
return dw2_instantiate_symtab (objfile, dw2_get_cu (index)); return dw2_instantiate_symtab (objfile, dw2_get_cu (index));
} }
/* Traversal function for dw2_forget_cached_source_info. */
static int
dw2_free_cached_file_names (void **slot, void *info)
{
struct quick_file_names *file_data = (struct quick_file_names *) *slot;
if (file_data->real_names)
{
int i;
for (i = 0; i < file_data->num_file_names; ++i)
{
xfree ((void*) file_data->real_names[i]);
file_data->real_names[i] = NULL;
}
}
return 1;
}
static void static void
dw2_forget_cached_source_info (struct objfile *objfile) dw2_forget_cached_source_info (struct objfile *objfile)
{ {
int i;
dw2_setup (objfile); dw2_setup (objfile);
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_comp_units); ++i)
{
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
if (per_cu->v.quick->full_names) htab_traverse_noresize (dwarf2_per_objfile->quick_file_names_table,
{ dw2_free_cached_file_names, NULL);
int j;
for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
{
xfree ((void *) per_cu->v.quick->full_names[j]);
per_cu->v.quick->full_names[j] = NULL;
}
}
}
} }
static int static int
@ -2162,17 +2272,18 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
{ {
int j; int j;
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
if (per_cu->v.quick->symtab) if (per_cu->v.quick->symtab)
continue; continue;
dw2_require_line_header (objfile, per_cu); file_data = dw2_get_file_names (objfile, per_cu);
if (!per_cu->v.quick->lines) if (file_data == NULL)
continue; continue;
for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j) for (j = 0; j < file_data->num_file_names; ++j)
{ {
const char *this_name = per_cu->v.quick->file_names[j]; const char *this_name = file_data->file_names[j];
if (FILENAME_CMP (name, this_name) == 0) if (FILENAME_CMP (name, this_name) == 0)
{ {
@ -2186,11 +2297,11 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (full_path != NULL) if (full_path != NULL)
{ {
const char *this_full_name = dw2_require_full_path (objfile, const char *this_real_name = dw2_get_real_path (objfile,
per_cu, j); file_data, j);
if (this_full_name if (this_real_name != NULL
&& FILENAME_CMP (full_path, this_full_name) == 0) && FILENAME_CMP (full_path, this_real_name) == 0)
{ {
*result = dw2_instantiate_symtab (objfile, per_cu); *result = dw2_instantiate_symtab (objfile, per_cu);
return 1; return 1;
@ -2199,11 +2310,11 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (real_path != NULL) if (real_path != NULL)
{ {
const char *this_full_name = dw2_require_full_path (objfile, const char *this_real_name = dw2_get_real_path (objfile,
per_cu, j); file_data, j);
if (this_full_name != NULL if (this_real_name != NULL
&& FILENAME_CMP (real_path, this_full_name) == 0) && FILENAME_CMP (real_path, this_real_name) == 0)
{ {
*result = dw2_instantiate_symtab (objfile, per_cu); *result = dw2_instantiate_symtab (objfile, per_cu);
return 1; return 1;
@ -2337,17 +2448,18 @@ dw2_expand_symtabs_with_filename (struct objfile *objfile,
{ {
int j; int j;
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
if (per_cu->v.quick->symtab) if (per_cu->v.quick->symtab)
continue; continue;
dw2_require_line_header (objfile, per_cu); file_data = dw2_get_file_names (objfile, per_cu);
if (!per_cu->v.quick->lines) if (file_data == NULL)
continue; continue;
for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j) for (j = 0; j < file_data->num_file_names; ++j)
{ {
const char *this_name = per_cu->v.quick->file_names[j]; const char *this_name = file_data->file_names[j];
if (FILENAME_CMP (this_name, filename) == 0) if (FILENAME_CMP (this_name, filename) == 0)
{ {
dw2_instantiate_symtab (objfile, per_cu); dw2_instantiate_symtab (objfile, per_cu);
@ -2362,6 +2474,7 @@ dw2_find_symbol_file (struct objfile *objfile, const char *name)
{ {
struct dwarf2_per_cu_data *per_cu; struct dwarf2_per_cu_data *per_cu;
offset_type *vec; offset_type *vec;
struct quick_file_names *file_data;
dw2_setup (objfile); dw2_setup (objfile);
@ -2380,11 +2493,11 @@ dw2_find_symbol_file (struct objfile *objfile, const char *name)
/* vec[0] is the length, which must always be >0. */ /* vec[0] is the length, which must always be >0. */
per_cu = dw2_get_cu (MAYBE_SWAP (vec[1])); per_cu = dw2_get_cu (MAYBE_SWAP (vec[1]));
dw2_require_line_header (objfile, per_cu); file_data = dw2_get_file_names (objfile, per_cu);
if (!per_cu->v.quick->lines) if (file_data == NULL)
return NULL; return NULL;
return per_cu->v.quick->file_names[per_cu->v.quick->lines->num_file_names - 1]; return file_data->file_names[file_data->num_file_names - 1];
} }
static void static void
@ -2423,18 +2536,19 @@ dw2_expand_symtabs_matching (struct objfile *objfile,
{ {
int j; int j;
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
per_cu->v.quick->mark = 0; per_cu->v.quick->mark = 0;
if (per_cu->v.quick->symtab) if (per_cu->v.quick->symtab)
continue; continue;
dw2_require_line_header (objfile, per_cu); file_data = dw2_get_file_names (objfile, per_cu);
if (!per_cu->v.quick->lines) if (file_data == NULL)
continue; continue;
for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j) for (j = 0; j < file_data->num_file_names; ++j)
{ {
if (file_matcher (per_cu->v.quick->file_names[j], data)) if (file_matcher (file_data->file_names[j], data))
{ {
per_cu->v.quick->mark = 1; per_cu->v.quick->mark = 1;
break; break;
@ -2541,19 +2655,20 @@ dw2_map_symbol_filenames (struct objfile *objfile,
{ {
int j; int j;
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
if (per_cu->v.quick->symtab) if (per_cu->v.quick->symtab)
continue; continue;
dw2_require_line_header (objfile, per_cu); file_data = dw2_get_file_names (objfile, per_cu);
if (!per_cu->v.quick->lines) if (file_data == NULL)
continue; continue;
for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j) for (j = 0; j < file_data->num_file_names; ++j)
{ {
const char *this_full_name = dw2_require_full_path (objfile, per_cu, const char *this_real_name = dw2_get_real_path (objfile, file_data,
j); j);
(*fun) (per_cu->v.quick->file_names[j], this_full_name, data); (*fun) (file_data->file_names[j], this_real_name, data);
} }
} }
} }
@ -2603,6 +2718,8 @@ dwarf2_initialize_objfile (struct objfile *objfile)
dwarf2_per_objfile->using_index = 1; dwarf2_per_objfile->using_index = 1;
create_all_comp_units (objfile); create_all_comp_units (objfile);
create_debug_types_hash_table (objfile); create_debug_types_hash_table (objfile);
dwarf2_per_objfile->quick_file_names_table =
create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
for (i = 0; i < (dwarf2_per_objfile->n_comp_units for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_comp_units); ++i) + dwarf2_per_objfile->n_type_comp_units); ++i)
@ -14536,30 +14653,8 @@ dwarf2_free_objfile (struct objfile *objfile)
/* Cached DIE trees use xmalloc and the comp_unit_obstack. */ /* Cached DIE trees use xmalloc and the comp_unit_obstack. */
free_cached_comp_units (NULL); free_cached_comp_units (NULL);
if (dwarf2_per_objfile->using_index) if (dwarf2_per_objfile->quick_file_names_table)
{ htab_delete (dwarf2_per_objfile->quick_file_names_table);
int i;
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
struct dwarf2_per_cu_data *per_cu =
dwarf2_per_objfile->all_comp_units[i];
if (!per_cu->v.quick->lines)
continue;
for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
{
if (per_cu->v.quick->file_names)
xfree ((void *) per_cu->v.quick->file_names[j]);
if (per_cu->v.quick->full_names)
xfree ((void *) per_cu->v.quick->full_names[j]);
}
free_line_header (per_cu->v.quick->lines);
}
}
/* Everything else should be on the objfile obstack. */ /* Everything else should be on the objfile obstack. */
} }