Skip to content

Commit 1fd5fd5

Browse files
committed
Fix file-name handling regression with DWARF index
When run with the gdb-index or debug-names target boards, dup-psym.exp fails. This came up for me because my new DWARF scanner reuses this part of the existing index code, and so it registers as a regression. This is PR symtab/25834. Looking into this, I found that the DWARF index code here is fairly different from the psymtab code. I don't think there's a deep reason for this, and in fact, it seemed to me that the index code could simply mimic what the psymtab code already does. That is what this patch implements. The DW_AT_name and DW_AT_comp_dir are now stored in the quick file names table. This may require allocating a quick file names table even when DW_AT_stmt_list does not exist. Then, the functions that work with this data are changed to use find_source_or_rewrite, just as the psymbol code does. Finally, line_header::file_full_name is removed, as it is no longer needed. Currently, the index maintains a hash table of "quick file names". The hash table uses a deletion function to free the "real name" components when necessary. There's also a second such function to implement the forget_cached_source_info method. This bug fix patch will create a quick file name object even when there is no DW_AT_stmt_list, meaning that the object won't be entered in the hash table. So, this patch changes the memory management approach so that the entries are cleared when the per-BFD object is destroyed. (A dwarf2_per_cu_data destructor is not introduced, because we have been avoiding adding a vtable to that class.) Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=25834
1 parent 15659f0 commit 1fd5fd5

File tree

4 files changed

+84
-84
lines changed

4 files changed

+84
-84
lines changed

gdb/dwarf2/line-header.c

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -96,25 +96,6 @@ line_header::file_file_name (int file) const
9696
}
9797
}
9898

99-
gdb::unique_xmalloc_ptr<char>
100-
line_header::file_full_name (int file, const char *comp_dir) const
101-
{
102-
/* Is the file number a valid index into the line header's file name
103-
table? Remember that file numbers start with one, not zero. */
104-
if (is_valid_file_index (file))
105-
{
106-
gdb::unique_xmalloc_ptr<char> relative = file_file_name (file);
107-
108-
if (IS_ABSOLUTE_PATH (relative.get ()) || comp_dir == NULL)
109-
return relative;
110-
return gdb::unique_xmalloc_ptr<char> (concat (comp_dir, SLASH_STRING,
111-
relative.get (),
112-
(char *) NULL));
113-
}
114-
else
115-
return file_file_name (file);
116-
}
117-
11899
static void
119100
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
120101
{

gdb/dwarf2/line-header.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,6 @@ struct line_header
162162
header. These point into dwarf2_per_objfile->line_buffer. */
163163
const gdb_byte *statement_program_start {}, *statement_program_end {};
164164

165-
/* Return the full name of file number I in this object's file name
166-
table. Use COMP_DIR as the name of the current directory of the
167-
compilation. The result is allocated using xmalloc; the caller
168-
is responsible for freeing it. */
169-
gdb::unique_xmalloc_ptr<char> file_full_name (int file,
170-
const char *comp_dir) const;
171-
172165
/* Return file name relative to the compilation directory of file
173166
number I in this object's file name table. The result is
174167
allocated using xmalloc; the caller is responsible for freeing

gdb/dwarf2/read.c

Lines changed: 81 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,12 @@ struct file_and_directory
15421542
static file_and_directory find_file_and_directory (struct die_info *die,
15431543
struct dwarf2_cu *cu);
15441544

1545+
static const char *compute_include_file_name
1546+
(const struct line_header *lh,
1547+
const file_entry &fe,
1548+
const file_and_directory &cu_info,
1549+
gdb::unique_xmalloc_ptr<char> *name_holder);
1550+
15451551
static htab_up allocate_signatured_type_table ();
15461552

15471553
static htab_up allocate_dwo_unit_table ();
@@ -1654,7 +1660,10 @@ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names,
16541660
dwarf2_per_bfd::~dwarf2_per_bfd ()
16551661
{
16561662
for (auto &per_cu : all_comp_units)
1657-
per_cu->imported_symtabs_free ();
1663+
{
1664+
per_cu->imported_symtabs_free ();
1665+
per_cu->free_cached_file_names ();
1666+
}
16581667

16591668
/* Everything else should be on this->obstack. */
16601669
}
@@ -1966,6 +1975,10 @@ struct quick_file_names
19661975
/* The number of entries in file_names, real_names. */
19671976
unsigned int num_file_names;
19681977

1978+
/* The CU directory, as given by DW_AT_comp_dir. May be
1979+
nullptr. */
1980+
const char *comp_dir;
1981+
19691982
/* The file names from the line table, after being run through
19701983
file_full_name. */
19711984
const char **file_names;
@@ -2162,33 +2175,14 @@ eq_file_name_entry (const void *a, const void *b)
21622175
return eq_stmt_list_entry (&ea->hash, &eb->hash);
21632176
}
21642177

2165-
/* Delete function for a quick_file_names. */
2166-
2167-
static void
2168-
delete_file_name_entry (void *e)
2169-
{
2170-
struct quick_file_names *file_data = (struct quick_file_names *) e;
2171-
int i;
2172-
2173-
for (i = 0; i < file_data->num_file_names; ++i)
2174-
{
2175-
xfree ((void*) file_data->file_names[i]);
2176-
if (file_data->real_names)
2177-
xfree ((void*) file_data->real_names[i]);
2178-
}
2179-
2180-
/* The space for the struct itself lives on the obstack, so we don't
2181-
free it here. */
2182-
}
2183-
21842178
/* Create a quick_file_names hash table. */
21852179

21862180
static htab_up
21872181
create_quick_file_names_table (unsigned int nr_initial_entries)
21882182
{
21892183
return htab_up (htab_create_alloc (nr_initial_entries,
21902184
hash_file_name_entry, eq_file_name_entry,
2191-
delete_file_name_entry, xcalloc, xfree));
2185+
nullptr, xcalloc, xfree));
21922186
}
21932187

21942188
/* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE. This
@@ -2930,30 +2924,50 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
29302924

29312925
lh = dwarf_decode_line_header (line_offset, cu);
29322926
}
2933-
if (lh == NULL)
2934-
return;
2935-
2936-
qfn = XOBNEW (&per_objfile->per_bfd->obstack, struct quick_file_names);
2937-
qfn->hash.dwo_unit = cu->dwo_unit;
2938-
qfn->hash.line_sect_off = line_offset;
2939-
gdb_assert (slot != NULL);
2940-
*slot = qfn;
29412927

29422928
file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
29432929

29442930
int offset = 0;
29452931
if (strcmp (fnd.name, "<unknown>") != 0)
29462932
++offset;
2933+
else if (lh == nullptr)
2934+
return;
2935+
2936+
qfn = XOBNEW (&per_objfile->per_bfd->obstack, struct quick_file_names);
2937+
qfn->hash.dwo_unit = cu->dwo_unit;
2938+
qfn->hash.line_sect_off = line_offset;
2939+
/* There may not be a DW_AT_stmt_list. */
2940+
if (slot != nullptr)
2941+
*slot = qfn;
2942+
2943+
std::vector<const char *> include_names;
2944+
if (lh != nullptr)
2945+
{
2946+
for (const auto &entry : lh->file_names ())
2947+
{
2948+
gdb::unique_xmalloc_ptr<char> name_holder;
2949+
const char *include_name =
2950+
compute_include_file_name (lh.get (), entry, fnd, &name_holder);
2951+
if (include_name != nullptr)
2952+
{
2953+
include_name = per_objfile->objfile->intern (include_name);
2954+
include_names.push_back (include_name);
2955+
}
2956+
}
2957+
}
29472958

2948-
qfn->num_file_names = offset + lh->file_names_size ();
2959+
qfn->num_file_names = offset + include_names.size ();
2960+
qfn->comp_dir = fnd.comp_dir;
29492961
qfn->file_names =
29502962
XOBNEWVEC (&per_objfile->per_bfd->obstack, const char *,
29512963
qfn->num_file_names);
29522964
if (offset != 0)
29532965
qfn->file_names[0] = xstrdup (fnd.name);
2954-
for (int i = 0; i < lh->file_names_size (); ++i)
2955-
qfn->file_names[i + offset] = lh->file_full_name (i + 1,
2956-
fnd.comp_dir).release ();
2966+
2967+
if (!include_names.empty ())
2968+
memcpy (&qfn->file_names[offset], include_names.data (),
2969+
include_names.size () * sizeof (const char *));
2970+
29572971
qfn->real_names = NULL;
29582972

29592973
lh_cu->v.quick->file_names = qfn;
@@ -2993,7 +3007,17 @@ dw2_get_real_path (dwarf2_per_objfile *per_objfile,
29933007
qfn->num_file_names, const char *);
29943008

29953009
if (qfn->real_names[index] == NULL)
2996-
qfn->real_names[index] = gdb_realpath (qfn->file_names[index]).release ();
3010+
{
3011+
const char *dirname = nullptr;
3012+
3013+
if (!IS_ABSOLUTE_PATH (qfn->file_names[index]))
3014+
dirname = qfn->comp_dir;
3015+
3016+
gdb::unique_xmalloc_ptr<char> fullname;
3017+
fullname = find_source_or_rewrite (qfn->file_names[index], dirname);
3018+
3019+
qfn->real_names[index] = fullname.release ();
3020+
}
29973021

29983022
return qfn->real_names[index];
29993023
}
@@ -3012,25 +3036,23 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
30123036
return compunit_primary_filetab (cust);
30133037
}
30143038

3015-
/* Traversal function for dw2_forget_cached_source_info. */
3039+
/* See read.h. */
30163040

3017-
static int
3018-
dw2_free_cached_file_names (void **slot, void *info)
3041+
void
3042+
dwarf2_per_cu_data::free_cached_file_names ()
30193043
{
3020-
struct quick_file_names *file_data = (struct quick_file_names *) *slot;
3044+
if (per_bfd == nullptr || !per_bfd->using_index || v.quick == nullptr)
3045+
return;
30213046

3022-
if (file_data->real_names)
3047+
struct quick_file_names *file_data = v.quick->file_names;
3048+
if (file_data != nullptr && file_data->real_names != nullptr)
30233049
{
3024-
int i;
3025-
3026-
for (i = 0; i < file_data->num_file_names; ++i)
3050+
for (int i = 0; i < file_data->num_file_names; ++i)
30273051
{
3028-
xfree ((void*) file_data->real_names[i]);
3029-
file_data->real_names[i] = NULL;
3052+
xfree ((void *) file_data->real_names[i]);
3053+
file_data->real_names[i] = nullptr;
30303054
}
30313055
}
3032-
3033-
return 1;
30343056
}
30353057

30363058
void
@@ -3039,8 +3061,8 @@ dwarf2_base_index_functions::forget_cached_source_info
30393061
{
30403062
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
30413063

3042-
htab_traverse_noresize (per_objfile->per_bfd->quick_file_names_table.get (),
3043-
dw2_free_cached_file_names, NULL);
3064+
for (auto &per_cu : per_objfile->per_bfd->all_comp_units)
3065+
per_cu->free_cached_file_names ();
30443066
}
30453067

30463068
/* Struct used to manage iterating over all CUs looking for a symbol. */
@@ -4444,18 +4466,19 @@ dwarf2_base_index_functions::map_symbol_filenames
44444466
for (int j = 0; j < file_data->num_file_names; ++j)
44454467
{
44464468
const char *filename = file_data->file_names[j];
4447-
filenames_cache.seen (filename);
4448-
}
4449-
}
4469+
const char *key = filename;
4470+
const char *fullname = nullptr;
44504471

4451-
filenames_cache.traverse ([&] (const char *filename)
4452-
{
4453-
gdb::unique_xmalloc_ptr<char> this_real_name;
4472+
if (need_fullname)
4473+
{
4474+
fullname = dw2_get_real_path (per_objfile, file_data, j);
4475+
key = fullname;
4476+
}
44544477

4455-
if (need_fullname)
4456-
this_real_name = gdb_realpath (filename);
4457-
fun (filename, this_real_name.get ());
4458-
});
4478+
if (!filenames_cache.seen (key))
4479+
fun (filename, fullname);
4480+
}
4481+
}
44594482
}
44604483

44614484
bool

gdb/dwarf2/read.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ struct dwarf2_per_cu_data
275275
{
276276
return section == nullptr;
277277
}
278+
279+
/* Free any cached file names. */
280+
void free_cached_file_names ();
278281
};
279282

280283
/* Entry in the signatured_types hash table. */

0 commit comments

Comments
 (0)