This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH][gdb] Write index for dwz -m file
- From: Tom de Vries <tdevries at suse dot de>
- To: gdb-patches at sourceware dot org, Simon Marchi <simon dot marchi at polymtl dot ca>
- Date: Tue, 7 May 2019 16:42:09 +0200
- Subject: [PATCH][gdb] Write index for dwz -m file
Hi,
With target board cc-with-dwz-m, we run into the following failures:
...
FAIL: gdb.base/index-cache.exp: test_cache_enabled_hit: check index-cache stats
FAIL: gdb.dwarf2/gdb-index.exp: index used
FAIL: gdb.dwarf2/gdb-index.exp: index used after symbol reloading
...
The problem in both test-cases is that given an executable foo.exe with
.gnu_debugaltlink file foo.dwz, gdb writes the index for both files into a
single file.
Fix this by writing the index for foo.dwz to a seperate file. [ Note that
this does not fix contrib/gdb-add-index.sh. ]
Tested on x86_64-linux with native and cc-with-dwz-m.
The only remaining regressions of cc-with-dwz-m compared to native are:
- PR24508 (gdb.base/maint.exp)
- PR24503 (gdb.base/max-depth.exp and gdb.cp/var-tag.exp)
OK for trunk?
Thanks,
- Tom
[gdb] Write index for dwz -m file
gdb/ChangeLog:
2019-05-07 Simon Marchi <simon.marchi@efficios.com>
PR gdb/24445
* dwarf-index-cache.c (index_cache::store): Save index of
.gnu_debugaltlink file to seperate cache file.
* dwarf-index-write.c (write_gdbindex): Add and handle new parameter
dwz_out_file.
(write_psymtabs_to_index): Add and handle new parameter dwz_basename.
(save_gdb_index_command): Update write_psymtabs_to_index call.
* dwarf-index-write.h (write_psymtabs_to_index): Update declaration.
* dwarf2read.c (struct dwz_file): Move ...
* dwarf2read.h (struct dwz_file): ... here.
gdb/testsuite/ChangeLog:
2019-05-07 Tom de Vries <tdevries@suse.de>
PR gdb/24445
* gdb.dwarf2/gdb-index.exp: Update dwz file with generated index.
---
gdb/dwarf-index-cache.c | 29 +++++++++++--
gdb/dwarf-index-write.c | 90 ++++++++++++++++++++++++++++++++++++++---
gdb/dwarf-index-write.h | 2 +-
gdb/dwarf2read.c | 28 +------------
gdb/dwarf2read.h | 34 ++++++++++++++++
5 files changed, 145 insertions(+), 38 deletions(-)
---
gdb/dwarf-index-cache.c | 27 +++++++++--
gdb/dwarf-index-write.c | 87 +++++++++++++++++++++++++++++++---
gdb/dwarf-index-write.h | 2 +-
gdb/dwarf2read.c | 28 +----------
gdb/dwarf2read.h | 34 +++++++++++++
gdb/testsuite/gdb.dwarf2/gdb-index.exp | 15 ++++++
6 files changed, 156 insertions(+), 37 deletions(-)
diff --git a/gdb/dwarf-index-cache.c b/gdb/dwarf-index-cache.c
index 9513891a45..8d583bd81b 100644
--- a/gdb/dwarf-index-cache.c
+++ b/gdb/dwarf-index-cache.c
@@ -102,14 +102,34 @@ index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile)
return;
}
+ std::string build_id_str = build_id_to_string (build_id);
+
+ const bfd_build_id *dwz_build_id = NULL;
+ gdb::optional<std::string> dwz_build_id_str;
+ const dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
+ const char *dwz_build_id_ptr = NULL;
+ if (dwz != nullptr)
+ {
+ dwz_build_id = build_id_bfd_get (dwz->dwz_bfd.get ());
+
+ if (dwz_build_id == nullptr)
+ {
+ if (debug_index_cache)
+ printf_unfiltered ("index cache: dwz objfile %s has no build id\n",
+ dwz->filename ());
+ return;
+ }
+
+ dwz_build_id_str = build_id_to_string (dwz_build_id);
+ dwz_build_id_ptr = dwz_build_id_str->c_str ();
+ }
+
if (m_dir.empty ())
{
warning (_("The index cache directory name is empty, skipping store."));
return;
}
- std::string build_id_str = build_id_to_string (build_id);
-
try
{
/* Try to create the containing directory. */
@@ -127,7 +147,8 @@ index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile)
/* Write the index itself to the directory, using the build id as the
filename. */
write_psymtabs_to_index (dwarf2_per_objfile, m_dir.c_str (),
- build_id_str.c_str (), dw_index_kind::GDB_INDEX);
+ build_id_str.c_str (), dwz_build_id_ptr,
+ dw_index_kind::GDB_INDEX);
}
catch (const gdb_exception_error &except)
{
diff --git a/gdb/dwarf-index-write.c b/gdb/dwarf-index-write.c
index 8734f99212..7fd9a49270 100644
--- a/gdb/dwarf-index-write.c
+++ b/gdb/dwarf-index-write.c
@@ -1293,11 +1293,13 @@ psyms_seen_size (struct dwarf2_per_objfile *dwarf2_per_objfile)
Return how many bytes were expected to be written into OUT_FILE. */
static size_t
-write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file)
+write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file,
+ FILE *dwz_out_file)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
mapped_symtab symtab;
- data_buf cu_list;
+ data_buf main_cu_list;
+ data_buf dwz_cu_list;
/* While we're scanning CU's create a table that maps a psymtab pointer
(which is what addrmap records) to its index (which is what is recorded
@@ -1331,6 +1333,7 @@ write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file)
const auto insertpair = cu_index_htab.emplace (psymtab, i);
gdb_assert (insertpair.second);
+ data_buf &cu_list = per_cu->is_dwz ? dwz_cu_list : main_cu_list;
cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
to_underlying (per_cu->sect_off));
cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length);
@@ -1370,7 +1373,7 @@ write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file)
/* The offset of the CU list from the start of the file. */
contents.append_data (MAYBE_SWAP (total_len));
- total_len += cu_list.size ();
+ total_len += main_cu_list.size ();
/* The offset of the types CU list from the start of the file. */
contents.append_data (MAYBE_SWAP (total_len));
@@ -1391,12 +1394,39 @@ write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file)
gdb_assert (contents.size () == size_of_contents);
contents.file_write (out_file);
- cu_list.file_write (out_file);
+ main_cu_list.file_write (out_file);
types_cu_list.file_write (out_file);
addr_vec.file_write (out_file);
symtab_vec.file_write (out_file);
constant_pool.file_write (out_file);
+
+ if (dwz_out_file != NULL)
+ {
+ data_buf dwz_contents;
+ const offset_type dwz_size_of_contents = 6 * sizeof (offset_type);
+ offset_type dwz_total_len = size_of_contents;
+
+ /* The version number. */
+ dwz_contents.append_data (MAYBE_SWAP (8));
+
+ /* The offset of the CU list from the start of the file. */
+ dwz_contents.append_data (MAYBE_SWAP (dwz_total_len));
+ dwz_total_len += dwz_cu_list.size ();
+
+ dwz_contents.append_data (MAYBE_SWAP (dwz_total_len));
+ dwz_contents.append_data (MAYBE_SWAP (dwz_total_len));
+ dwz_contents.append_data (MAYBE_SWAP (dwz_total_len));
+ dwz_contents.append_data (MAYBE_SWAP (dwz_total_len));
+
+ gdb_assert (dwz_contents.size () == dwz_size_of_contents);
+
+ dwz_contents.file_write (dwz_out_file);
+ dwz_cu_list.file_write (dwz_out_file);
+ }
+ else
+ gdb_assert (dwz_cu_list.empty ());
+
return total_len;
}
@@ -1548,6 +1578,7 @@ assert_file_size (FILE *file, const char *filename, size_t expected_size)
void
write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
const char *dir, const char *basename,
+ const char *dwz_basename,
dw_index_kind index_kind)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
@@ -1587,6 +1618,32 @@ write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
unlink_file.emplace (filename_temp.data ());
+ /* Order is important here as well, for the same reason as above. */
+ gdb::optional<std::string> dwz_filename;
+ gdb::optional<gdb::char_vector> dwz_filename_temp;
+ gdb::optional<gdb::unlinker> dwz_unlink_file;
+ gdb::optional<scoped_fd> dwz_out_file_fd;
+ gdb::optional<gdb_file_up> dwz_out_file;
+
+ if (dwz_basename != NULL)
+ {
+ dwz_filename = (std::string (dir) + SLASH_STRING + dwz_basename
+ + (index_kind == dw_index_kind::DEBUG_NAMES
+ ? INDEX5_SUFFIX : INDEX4_SUFFIX));
+ dwz_filename_temp = make_temp_filename (*dwz_filename);
+ dwz_out_file_fd.emplace (gdb_mkostemp_cloexec (dwz_filename_temp->data (),
+ O_BINARY));
+ if (dwz_out_file_fd->get () == -1)
+ perror_with_name (("mkstemp"));
+
+ dwz_out_file = dwz_out_file_fd->to_file ("wb");
+
+ if (*dwz_out_file == nullptr)
+ error (_("Can't open `%s' for writing"), dwz_filename_temp->data ());
+
+ dwz_unlink_file.emplace (dwz_filename_temp->data ());
+ }
+
if (index_kind == dw_index_kind::DEBUG_NAMES)
{
std::string filename_str (std::string (dir) + SLASH_STRING
@@ -1623,7 +1680,8 @@ write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
else
{
const size_t total_len
- = write_gdbindex (dwarf2_per_objfile, out_file.get ());
+ = write_gdbindex (dwarf2_per_objfile, out_file.get (),
+ dwz_basename != NULL ? dwz_out_file->get () : NULL);
assert_file_size (out_file.get (), filename_temp.data (), total_len);
}
@@ -1633,7 +1691,18 @@ write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
/* Close and move the file in place. */
out_file.reset ();
if (rename (filename_temp.data (), filename.c_str ()) != 0)
+ perror_with_name (("rename"));
+
+ if (dwz_basename != NULL)
+ {
+ /* We want to keep the file. */
+ dwz_unlink_file->keep ();
+
+ /* Close and move the file in place. */
+ dwz_out_file->reset ();
+ if (rename (dwz_filename_temp->data (), dwz_filename->c_str ()) != 0)
perror_with_name (("rename"));
+ }
}
/* Implementation of the `save gdb-index' command.
@@ -1678,8 +1747,14 @@ save_gdb_index_command (const char *arg, int from_tty)
try
{
const char *basename = lbasename (objfile_name (objfile));
+ const dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
+ const char *dwz_basename = NULL;
+
+ if (dwz != NULL)
+ dwz_basename = lbasename (dwz->filename ());
+
write_psymtabs_to_index (dwarf2_per_objfile, arg, basename,
- index_kind);
+ dwz_basename, index_kind);
}
catch (const gdb_exception_error &except)
{
diff --git a/gdb/dwarf-index-write.h b/gdb/dwarf-index-write.h
index b1d1180c8e..ada6932267 100644
--- a/gdb/dwarf-index-write.h
+++ b/gdb/dwarf-index-write.h
@@ -29,6 +29,6 @@
extern void write_psymtabs_to_index
(struct dwarf2_per_objfile *dwarf2_per_objfile, const char *dir,
- const char *basename, dw_index_kind index_kind);
+ const char *basename, const char *dwz_basename, dw_index_kind index_kind);
#endif /* DWARF_INDEX_WRITE_H */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index b5ea9e3cc0..61d47b10d6 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -886,32 +886,6 @@ struct dwp_file
asection **elf_sections = nullptr;
};
-/* This represents a '.dwz' file. */
-
-struct dwz_file
-{
- dwz_file (gdb_bfd_ref_ptr &&bfd)
- : dwz_bfd (std::move (bfd))
- {
- }
-
- /* A dwz file can only contain a few sections. */
- struct dwarf2_section_info abbrev {};
- struct dwarf2_section_info info {};
- struct dwarf2_section_info str {};
- struct dwarf2_section_info line {};
- struct dwarf2_section_info macro {};
- struct dwarf2_section_info gdb_index {};
- struct dwarf2_section_info debug_names {};
-
- /* The dwz's BFD. */
- gdb_bfd_ref_ptr dwz_bfd;
-
- /* If we loaded the index from an external file, this contains the
- resources associated to the open file, memory mapping, etc. */
- std::unique_ptr<index_cache_resource> index_cache_res;
-};
-
/* 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. This
@@ -2672,7 +2646,7 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
there is no .gnu_debugaltlink section in the file. Error if there
is such a section but the file cannot be found. */
-static struct dwz_file *
+struct dwz_file *
dwarf2_get_dwz_file (struct dwarf2_per_objfile *dwarf2_per_objfile)
{
const char *filename;
diff --git a/gdb/dwarf2read.h b/gdb/dwarf2read.h
index 34c66167b5..14befd7e79 100644
--- a/gdb/dwarf2read.h
+++ b/gdb/dwarf2read.h
@@ -403,4 +403,38 @@ struct signatured_type
typedef struct signatured_type *sig_type_ptr;
DEF_VEC_P (sig_type_ptr);
+/* This represents a '.dwz' file. */
+
+struct dwz_file
+{
+ dwz_file (gdb_bfd_ref_ptr &&bfd)
+ : dwz_bfd (std::move (bfd))
+ {
+ }
+
+ const char *filename () const
+ {
+ return bfd_get_filename (this->dwz_bfd);
+ }
+
+ /* A dwz file can only contain a few sections. */
+ struct dwarf2_section_info abbrev {};
+ struct dwarf2_section_info info {};
+ struct dwarf2_section_info str {};
+ struct dwarf2_section_info line {};
+ struct dwarf2_section_info macro {};
+ struct dwarf2_section_info gdb_index {};
+ struct dwarf2_section_info debug_names {};
+
+ /* The dwz's BFD. */
+ gdb_bfd_ref_ptr dwz_bfd;
+
+ /* If we loaded the index from an external file, this contains the
+ resources associated to the open file, memory mapping, etc. */
+ std::unique_ptr<index_cache_resource> index_cache_res;
+};
+
+extern struct dwz_file *dwarf2_get_dwz_file
+ (struct dwarf2_per_objfile *dwarf2_per_objfile);
+
#endif /* DWARF2READ_H */
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-index.exp b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
index 410e59684f..6fca3c6129 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-index.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
@@ -34,8 +34,11 @@ if { [prepare_for_testing "failed to prepare" "${testfile}" \
proc add_gdb_index { program } {
set index_file ${program}.gdb-index
+ set dwz ${program}.dwz
+ set dwz_index_file ${dwz}.gdb-index
verbose -log "index_file: ${index_file}"
remote_file host delete ${index_file}
+ remote_file host delete ${dwz_index_file}
gdb_test_no_output "save gdb-index [file dirname ${index_file}]" \
"save gdb-index for file [file tail ${program}]"
@@ -55,6 +58,18 @@ proc add_gdb_index { program } {
if {[run_on_host "objcopy" [gdb_find_objcopy] "--remove-section .gdb_index --add-section .gdb_index=$index_file --set-section-flags .gdb_index=readonly ${program} ${program_with_index}"]} {
return ""
}
+
+ if { [remote_file host exists ${dwz_index_file}] } {
+ # We're modifying $dwz in place, otherwise we'd have to update
+ # .gnu_debugaltlink in $program.
+ set args [join [list "--remove-section .gdb_index" \
+ " --add-section .gdb_index=$dwz_index_file" \
+ " --set-section-flags .gdb_index=readonly $dwz"]]
+ if {[run_on_host "objcopy" [gdb_find_objcopy] "$args"]} {
+ return ""
+ }
+ }
+
return ${program_with_index}
}