From patchwork Sat May 11 02:36:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 32642 Received: (qmail 40249 invoked by alias); 11 May 2019 02:36:56 -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 40241 invoked by uid 89); 11 May 2019 02:36:56 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-14.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.1 spammy=HDKIM-Filter:v2.11.0, sk:gdb-add, gdbaddindexsh, sk:gdbadd X-HELO: smtp.polymtl.ca Received: from smtp.polymtl.ca (HELO smtp.polymtl.ca) (132.207.4.11) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 11 May 2019 02:36:52 +0000 Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id x4B2ae78031956 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 May 2019 22:36:45 -0400 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca x4B2ae78031956 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=polymtl.ca; s=default; t=1557542207; bh=g0PJYpkY+0DTo1qcnxZEMT+lHY8LK4tTSRy3+zW0p+0=; h=Subject:To:References:From:Date:In-Reply-To:From; b=r+xWJRGLyZ1I+C/miWE3LYdiJE9HsjVbGncufU2U1TD91Gisl/yrnUGmigJxRq8Ti 0DCxQCpQbszocCkXQzuPaE3jqkSRS691Reu/ZF3X/ceO1IfeDlpUidXfMIJqg3b0m+ Owv2yCygijdF+lyetls5ZHbXUVoATvnrC7krAgwY= Received: from [10.0.0.11] (unknown [192.222.164.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id D62301E0A9; Fri, 10 May 2019 22:36:39 -0400 (EDT) Subject: Re: [PATCH][gdb] Write index for dwz -m file To: Tom de Vries , gdb-patches@sourceware.org References: <20190507144207.GA17626@delia> From: Simon Marchi Message-ID: <90892dae-b6b9-6a89-7cee-bbed859c207b@polymtl.ca> Date: Fri, 10 May 2019 22:36:39 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <20190507144207.GA17626@delia> X-IsSubscribed: yes On 2019-05-07 10:42 a.m., Tom de Vries wrote: > 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 The patch sent by Tom was more of a quick prototype I made and attached in Bugzilla (thanks for updating the test!). I have take the time to clean up the code a bit, what do you think about the patch below? From 3e22d9fd561656e3ce86039f5ba4533018055208 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Sun, 28 Apr 2019 23:19:24 -0400 Subject: [PATCH] Write index for dwz -m file PR 24445 ("dwz multifile index not written to index cache") exposed the fact that we are not doing things right when we generate an index for an object file that has is linked to a dwz file. The same happens whether the index is generated with the index of populating the index cache or using the save gdb-index command. The problem can be observed when running these tests with the cc-with-dwz-m board: 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 When generating the index for such file and inspecting the CU list of the resulting index (with readelf --debug-dump=gdb_index), we can see something like: CU table: [ 0] 0x0 - 0xb9 [ 1] 0x0 - 0x44 This is supposed to be a sorted list of the ranges of all CUs in the file this index represents, so already having some overlap is a red flag. It turns out that we save the ranges of CUs coming from both the main file and the dwz file in the same index. After digging a little bit, it became quite obvious that the index in the main file should only list the CUs present in the main file, and a separate index should be generated for the dwz file, listing the CUs present in that file. First, that's what happens if you run dwz on a file that already has a GDB index embedded. Second, dwarf2read.c has code to read an index from a dwz file. The index in the dwz file is actually required to be present, if the main file has an index). So this patch changes write_psymtabs_to_index to generate an index for the dwz file, if present. That index only contains a CU list, just like what the dwz tool does when processing a file that already contains an index. Some notes about the implementation: - The file management (creating a temp file, make sure it's close/removed on error - in the right order) is a bit heavy in write_psymtabs_to_index, and I needed to add a third file. I factored this pattern in a separate class, index_wip_file. - It became a bit tedious to keep the call to assert_file_size in write_psymtabs_to_index, write_gdbindex would have had to return two sizes. Instead, I moved the calls to assert_file_size where the file is written. The downside is that we lose the filename at this point, but it was only used for the very improbably case of ftell failing, so I think it's not a problem. - The actual writing of the index file is factored out to write_gdbindex_1, so it can be re-used for both index files. - While the "save gdb-index" command will now write two .gdb-index files, this patch does not update the gdb-add-index.sh script, this will come in a later patch. gdb/ChangeLog: YYYY-MM-DD Simon Marchi PR gdb/24445 * dwarf-index-write.h (write_psymtabs_to_index): Add dwz_basename parameter. * dwarf-index-write.c (write_gdbindex): Move file writing to write_gdbindex_1. Change return type void. (assert_file_size): Move up, remove filename parameter. (write_gdbindex_1): New function. (write_debug_names): Change return type to void, call assert_file_size. (struct index_wip_file): New struct. (write_psymtabs_to_index): Add dwz_basename parameter. Move file logic to index_wip_file. Write index for dwz file if needed. (save_gdb_index_command): Pass basename of dwz file, if present. * dwarf-index-cache.c (index_cache::store): Obtain and pass build-id of dwz file, if present. * dwarf2read.c (struct dwz_file): Move to dwarf2read.h. (dwarf2_get_dwz_file): Likewise. * dwarf2read.h (struct dwz_file): Move from dwarf2read.c. (dwarf2_get_dwz_file): Likewise. gdb/testsuite/ChangeLog: YYYY-MM-DD Tom de Vries PR gdb/24445 * gdb.dwarf2/gdb-index.exp (add_gdb_index): Update dwz file with generated index. --- gdb/dwarf-index-cache.c | 31 ++- gdb/dwarf-index-write.c | 272 +++++++++++++++---------- gdb/dwarf-index-write.h | 13 +- gdb/dwarf2read.c | 32 +-- gdb/dwarf2read.h | 38 ++++ gdb/testsuite/gdb.dwarf2/gdb-index.exp | 15 ++ 6 files changed, 251 insertions(+), 150 deletions(-) diff --git a/gdb/dwarf-index-cache.c b/gdb/dwarf-index-cache.c index 9513891a45fc..c3dc8f91dff0 100644 --- a/gdb/dwarf-index-cache.c +++ b/gdb/dwarf-index-cache.c @@ -93,6 +93,7 @@ index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile) if (!enabled ()) return; + /* Get build id of objfile. */ const bfd_build_id *build_id = build_id_bfd_get (obj->obfd); if (build_id == nullptr) { @@ -102,14 +103,35 @@ index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile) return; } + std::string build_id_str = build_id_to_string (build_id); + + /* Get build id of dwz file, if present. */ + 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) + { + const bfd_build_id *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. */ @@ -122,12 +144,13 @@ index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile) if (debug_index_cache) printf_unfiltered ("index cache: writing index cache for objfile %s\n", - objfile_name (obj)); + objfile_name (obj)); /* 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 8734f99212da..9d6ed4471929 100644 --- a/gdb/dwarf-index-write.c +++ b/gdb/dwarf-index-write.c @@ -1289,15 +1289,81 @@ psyms_seen_size (struct dwarf2_per_objfile *dwarf2_per_objfile) return psyms_count / 4; } -/* Write new .gdb_index section for OBJFILE into OUT_FILE. - Return how many bytes were expected to be written into OUT_FILE. */ +/* Assert that FILE's size is EXPECTED_SIZE. Assumes file's seek + position is at the end of the file. */ -static size_t -write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file) +static void +assert_file_size (FILE *file, size_t expected_size) +{ + const auto file_size = ftell (file); + if (file_size == -1) + perror_with_name (("ftell")); + gdb_assert (file_size == expected_size); +} + +/* Write a gdb index file to OUT_FILE from all the sections passed as + arguments. */ + +static void +write_gdbindex_1 (FILE *out_file, + const data_buf &cu_list, + const data_buf &types_cu_list, + const data_buf &addr_vec, + const data_buf &symtab_vec, + const data_buf &constant_pool) +{ + data_buf contents; + const offset_type size_of_header = 6 * sizeof (offset_type); + offset_type total_len = size_of_header; + + /* The version number. */ + contents.append_data (MAYBE_SWAP (8)); + + /* The offset of the CU list from the start of the file. */ + contents.append_data (MAYBE_SWAP (total_len)); + total_len += cu_list.size (); + + /* The offset of the types CU list from the start of the file. */ + contents.append_data (MAYBE_SWAP (total_len)); + total_len += types_cu_list.size (); + + /* The offset of the address table from the start of the file. */ + contents.append_data (MAYBE_SWAP (total_len)); + total_len += addr_vec.size (); + + /* The offset of the symbol table from the start of the file. */ + contents.append_data (MAYBE_SWAP (total_len)); + total_len += symtab_vec.size (); + + /* The offset of the constant pool from the start of the file. */ + contents.append_data (MAYBE_SWAP (total_len)); + total_len += constant_pool.size (); + + gdb_assert (contents.size () == size_of_header); + + contents.file_write (out_file); + 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); + + assert_file_size (out_file, total_len); +} + +/* Write contents of a .gdb_index section for OBJFILE into OUT_FILE. + If OBJFILE has an associated dwz file, write contents of a .gdb_index + section for that dwz file into DWZ_OUT_FILE. If OBJFILE does not have an + associated dwz file, DWZ_OUT_FILE must be NULL. */ + +static void +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 objfile_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 +1397,10 @@ 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); + /* The all_comp_units list contains CUs read from the objfile as well as + from the eventual dwz file. We need to place the entry in the + corresponding index. */ + data_buf &cu_list = per_cu->is_dwz ? dwz_cu_list : objfile_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); @@ -1361,43 +1431,13 @@ write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file) data_buf symtab_vec, constant_pool; write_hash_table (&symtab, symtab_vec, constant_pool); - data_buf contents; - const offset_type size_of_contents = 6 * sizeof (offset_type); - offset_type total_len = size_of_contents; - - /* The version number. */ - contents.append_data (MAYBE_SWAP (8)); - - /* The offset of the CU list from the start of the file. */ - contents.append_data (MAYBE_SWAP (total_len)); - total_len += cu_list.size (); - - /* The offset of the types CU list from the start of the file. */ - contents.append_data (MAYBE_SWAP (total_len)); - total_len += types_cu_list.size (); + write_gdbindex_1(out_file, objfile_cu_list, types_cu_list, addr_vec, + symtab_vec, constant_pool); - /* The offset of the address table from the start of the file. */ - contents.append_data (MAYBE_SWAP (total_len)); - total_len += addr_vec.size (); - - /* The offset of the symbol table from the start of the file. */ - contents.append_data (MAYBE_SWAP (total_len)); - total_len += symtab_vec.size (); - - /* The offset of the constant pool from the start of the file. */ - contents.append_data (MAYBE_SWAP (total_len)); - total_len += constant_pool.size (); - - gdb_assert (contents.size () == size_of_contents); - - contents.file_write (out_file); - 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); - - return total_len; + if (dwz_out_file != NULL) + write_gdbindex_1 (dwz_out_file, dwz_cu_list, {}, {}, {}, {}); + else + gdb_assert (dwz_cu_list.empty ()); } /* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension. */ @@ -1407,7 +1447,7 @@ static const gdb_byte dwarf5_gdb_augmentation[] = { 'G', 'D', 'B', 0 }; needed addition to .debug_str section to OUT_FILE_STR. Return how many bytes were expected to be written into OUT_FILE. */ -static size_t +static void write_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file, FILE *out_file_str) { @@ -1528,26 +1568,69 @@ write_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile, types_cu_list.file_write (out_file); nametable.file_write (out_file, out_file_str); - return expected_bytes; + assert_file_size (out_file, expected_bytes); } -/* Assert that FILE's size is EXPECTED_SIZE. Assumes file's seek - position is at the end of the file. */ +/* This represents an index file being written. -static void -assert_file_size (FILE *file, const char *filename, size_t expected_size) + The data is initially written to a temporary file. When the finalize method + is called, the file is closed and moved to its final location. + + On failure (if this object is being destroyed with having called finalize), + the temporary file is closed and deleted. */ + +struct index_wip_file { - const auto file_size = ftell (file); - if (file_size == -1) - error (_("Can't get `%s' size"), filename); - gdb_assert (file_size == expected_size); -} + index_wip_file (const char *dir, const char *basename, + const char *suffix) + { + filename = (std::string (dir) + SLASH_STRING + basename + + suffix); + + filename_temp = make_temp_filename (filename); + + scoped_fd out_file_fd (gdb_mkostemp_cloexec (filename_temp.data (), + O_BINARY)); + if (out_file_fd.get () == -1) + perror_with_name (("mkstemp")); + + out_file = out_file_fd.to_file ("wb"); + + if (out_file == nullptr) + error (_("Can't open `%s' for writing"), filename_temp.data ()); + + unlink_file.emplace (filename_temp.data ()); + } + + void finalize () + { + /* We want to keep the file. */ + unlink_file->keep (); + + /* Close and move the str file in place. */ + unlink_file.reset (); + if (rename (filename_temp.data (), filename.c_str ()) != 0) + perror_with_name (("rename")); + } + + std::string filename; + gdb::char_vector filename_temp; + + /* Order matters here; we want FILE to be closed before + FILENAME_TEMP is unlinked, because on MS-Windows one cannot + delete a file that is still open. So, we wrap the unlinker in an + optional and emplace it once we know the file name. */ + gdb::optional unlink_file; + + gdb_file_up out_file; +}; /* See dwarf-index-write.h. */ 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; @@ -1566,74 +1649,33 @@ write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile, if (stat (objfile_name (objfile), &st) < 0) perror_with_name (objfile_name (objfile)); - std::string filename (std::string (dir) + SLASH_STRING + basename - + (index_kind == dw_index_kind::DEBUG_NAMES - ? INDEX5_SUFFIX : INDEX4_SUFFIX)); - gdb::char_vector filename_temp = make_temp_filename (filename); + const char *index_suffix = (index_kind == dw_index_kind::DEBUG_NAMES + ? INDEX5_SUFFIX : INDEX4_SUFFIX); - /* Order matters here; we want FILE to be closed before - FILENAME_TEMP is unlinked, because on MS-Windows one cannot - delete a file that is still open. So, we wrap the unlinker in an - optional and emplace it once we know the file name. */ - gdb::optional unlink_file; - scoped_fd out_file_fd (gdb_mkostemp_cloexec (filename_temp.data (), - O_BINARY)); - if (out_file_fd.get () == -1) - perror_with_name (("mkstemp")); + index_wip_file objfile_index_wip (dir, basename, index_suffix); + gdb::optional dwz_index_wip; - gdb_file_up out_file = out_file_fd.to_file ("wb"); - if (out_file == nullptr) - error (_("Can't open `%s' for writing"), filename_temp.data ()); - - unlink_file.emplace (filename_temp.data ()); + if (dwz_basename != NULL) + dwz_index_wip.emplace (dir, dwz_basename, index_suffix); if (index_kind == dw_index_kind::DEBUG_NAMES) { - std::string filename_str (std::string (dir) + SLASH_STRING - + basename + DEBUG_STR_SUFFIX); - gdb::char_vector filename_str_temp = make_temp_filename (filename_str); - - /* As above, arrange to unlink the file only after the file - descriptor has been closed. */ - gdb::optional unlink_file_str; - scoped_fd out_file_str_fd - (gdb_mkostemp_cloexec (filename_str_temp.data (), O_BINARY)); - if (out_file_str_fd.get () == -1) - perror_with_name (("mkstemp")); - - gdb_file_up out_file_str = out_file_str_fd.to_file ("wb"); - if (out_file_str == nullptr) - error (_("Can't open `%s' for writing"), filename_str_temp.data ()); - - unlink_file_str.emplace (filename_str_temp.data ()); - - const size_t total_len - = write_debug_names (dwarf2_per_objfile, out_file.get (), - out_file_str.get ()); - assert_file_size (out_file.get (), filename_temp.data (), total_len); - - /* We want to keep the file .debug_str file too. */ - unlink_file_str->keep (); - - /* Close and move the str file in place. */ - out_file_str.reset (); - if (rename (filename_str_temp.data (), filename_str.c_str ()) != 0) - perror_with_name (("rename")); + index_wip_file str_wip_file (dir, basename, DEBUG_STR_SUFFIX); + + write_debug_names (dwarf2_per_objfile, objfile_index_wip.out_file.get (), + str_wip_file.out_file.get ()); + + str_wip_file.finalize (); } else - { - const size_t total_len - = write_gdbindex (dwarf2_per_objfile, out_file.get ()); - assert_file_size (out_file.get (), filename_temp.data (), total_len); - } + write_gdbindex (dwarf2_per_objfile, objfile_index_wip.out_file.get (), + (dwz_index_wip.has_value () + ? dwz_index_wip->out_file.get () : NULL)); - /* We want to keep the file. */ - unlink_file->keep (); + objfile_index_wip.finalize (); - /* 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_index_wip.has_value ()) + dwz_index_wip->finalize (); } /* Implementation of the `save gdb-index' command. @@ -1678,8 +1720,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 b1d1180c8e30..a8874c864385 100644 --- a/gdb/dwarf-index-write.h +++ b/gdb/dwarf-index-write.h @@ -23,12 +23,17 @@ #include "symfile.h" #include "dwarf2read.h" -/* Create an index file for OBJFILE in the directory DIR. BASENAME is the - desired filename, minus the extension, which gets added by this function - based on INDEX_KIND. */ +/* Create index files for OBJFILE in the directory DIR. + + An index file is created for OBJFILE itself, and is created for its + associated dwz file, if it has one. + + BASENAME is the desired filename base for OBJFILE's index. An extension + derived from INDEX_KIND is added to this base name. DWZ_BASENAME is the + same, but for the dwz file's index. */ 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 b29c089606db..3e9e8d1c704a 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -875,32 +875,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 @@ -2651,11 +2625,9 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg) } } -/* Open the separate '.dwz' debug file, if needed. Return NULL if - there is no .gnu_debugaltlink section in the file. Error if there - is such a section but the file cannot be found. */ +/* See dwarf2read.h. */ -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 732654348a83..e8658950e362 100644 --- a/gdb/dwarf2read.h +++ b/gdb/dwarf2read.h @@ -405,4 +405,42 @@ DEF_VEC_P (sig_type_ptr); ULONGEST read_unsigned_leb128 (bfd *, const gdb_byte *, unsigned int *); +/* 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; +}; + +/* Open the separate '.dwz' debug file, if needed. Return NULL if + there is no .gnu_debugaltlink section in the file. Error if there + is such a section but the file cannot be found. */ + +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 410e59684f33..6fca3c612992 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} }