From patchwork Tue May 7 14:42:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 32589 Received: (qmail 113715 invoked by alias); 7 May 2019 14:42:16 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 113703 invoked by uid 89); 7 May 2019 14:42:16 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=sk:dwarf-i, sk:dwarfi, objfile_name, sect_off X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 07 May 2019 14:42:13 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id C020BAE2B; Tue, 7 May 2019 14:42:11 +0000 (UTC) Date: Tue, 7 May 2019 16:42:09 +0200 From: Tom de Vries To: gdb-patches@sourceware.org, Simon Marchi Subject: [PATCH][gdb] Write index for dwz -m file Message-ID: <20190507144207.GA17626@delia> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-IsSubscribed: yes 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 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 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 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 dwz_filename; + gdb::optional dwz_filename_temp; + gdb::optional dwz_unlink_file; + gdb::optional dwz_out_file_fd; + gdb::optional 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_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_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} }