150 lines
5.3 KiB
Diff
150 lines
5.3 KiB
Diff
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
|
From: Tom Tromey <tom@tromey.com>
|
|
Date: Mon, 23 Oct 2023 16:44:53 -0600
|
|
Subject: gdb-rhel2295897-pre-read-DWZ-file-in-DWARF-reader.patch
|
|
|
|
;; backport of upstream commit 91874afabcd
|
|
;; This (somehow) solves a double-free when reading minimal symbols
|
|
|
|
Pre-read DWZ file in DWARF reader
|
|
|
|
While working on background reading of DWARF, I came across the
|
|
DWZ-reading code. This code can query the user (via the debuginfod
|
|
support) -- something that cannot be done off the main thread.
|
|
|
|
Looking into it, I realized that this code can be run much earlier,
|
|
avoiding this problem. Digging a bit deeper, I also found a
|
|
discrepancy here between how the DWARF reader works in "readnow" mode
|
|
as compared to the normal modes.
|
|
|
|
This patch cleans this up by trying to read the DWZ file earlier, and
|
|
also by having the DWARF reader convert any exception here into a
|
|
warning. This unifies the various cases, but also makes it so that
|
|
errors do not prevent gdb from continuing on to the extent possible.
|
|
|
|
Regression tested on x86-64 Fedora 38.
|
|
|
|
diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
|
|
--- a/gdb/dwarf2/dwz.c
|
|
+++ b/gdb/dwarf2/dwz.c
|
|
@@ -29,6 +29,7 @@
|
|
#include "gdbcore.h"
|
|
#include "gdbsupport/pathstuff.h"
|
|
#include "gdbsupport/scoped_fd.h"
|
|
+#include "run-on-main-thread.h"
|
|
|
|
const char *
|
|
dwz_file::read_string (struct objfile *objfile, LONGEST str_offset)
|
|
@@ -196,8 +197,20 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
|
|
size_t buildid_len;
|
|
bfd_byte *buildid;
|
|
|
|
- if (per_bfd->dwz_file != NULL)
|
|
- return per_bfd->dwz_file.get ();
|
|
+ if (per_bfd->dwz_file.has_value ())
|
|
+ {
|
|
+ dwz_file *result = per_bfd->dwz_file->get ();
|
|
+ if (require && result == nullptr)
|
|
+ error (_("could not read '.gnu_debugaltlink' section"));
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ /* This may query the user via the debuginfod support, so it may
|
|
+ only be run in the main thread. */
|
|
+ gdb_assert (is_main_thread ());
|
|
+
|
|
+ /* Set this early, so that on error it remains NULL. */
|
|
+ per_bfd->dwz_file.emplace (nullptr);
|
|
|
|
bfd_set_error (bfd_error_no_error);
|
|
gdb::unique_xmalloc_ptr<char> data
|
|
@@ -283,5 +296,5 @@ dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
|
|
|
|
gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ());
|
|
per_bfd->dwz_file = std::move (result);
|
|
- return per_bfd->dwz_file.get ();
|
|
+ return per_bfd->dwz_file->get ();
|
|
}
|
|
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
|
--- a/gdb/dwarf2/read.c
|
|
+++ b/gdb/dwarf2/read.c
|
|
@@ -3387,6 +3387,17 @@ dwarf2_initialize_objfile (struct objfile *objfile)
|
|
|
|
dwarf_read_debug_printf ("called");
|
|
|
|
+ /* Try to fetch any potential dwz file early, while still on the
|
|
+ main thread. */
|
|
+ try
|
|
+ {
|
|
+ dwarf2_get_dwz_file (per_bfd);
|
|
+ }
|
|
+ catch (const gdb_exception_error &err)
|
|
+ {
|
|
+ warning (_("%s"), err.what ());
|
|
+ }
|
|
+
|
|
/* If we're about to read full symbols, don't bother with the
|
|
indices. In this case we also don't care if some other debug
|
|
format is making psymtabs, because they are all about to be
|
|
@@ -5294,16 +5305,7 @@ create_all_units (dwarf2_per_objfile *per_objfile)
|
|
&per_objfile->per_bfd->abbrev, 0,
|
|
types_htab, rcuh_kind::TYPE);
|
|
|
|
- dwz_file *dwz;
|
|
- try
|
|
- {
|
|
- dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
|
|
- }
|
|
- catch (const gdb_exception_error &)
|
|
- {
|
|
- per_objfile->per_bfd->all_units.clear ();
|
|
- throw;
|
|
- }
|
|
+ dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
|
|
if (dwz != NULL)
|
|
{
|
|
/* Pre-read the sections we'll need to construct an index. */
|
|
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
|
|
--- a/gdb/dwarf2/read.h
|
|
+++ b/gdb/dwarf2/read.h
|
|
@@ -520,7 +520,7 @@ struct dwarf2_per_bfd
|
|
|
|
/* The shared '.dwz' file, if one exists. This is used when the
|
|
original data was compressed using 'dwz -m'. */
|
|
- std::unique_ptr<struct dwz_file> dwz_file;
|
|
+ gdb::optional<std::unique_ptr<struct dwz_file>> dwz_file;
|
|
|
|
/* Whether copy relocations are supported by this object format. */
|
|
bool can_copy;
|
|
diff --git a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
|
|
--- a/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
|
|
+++ b/gdb/testsuite/gdb.dwarf2/dwzbuildid.exp
|
|
@@ -142,13 +142,6 @@ proc do_test {} {
|
|
|
|
gdb_load ${::binfile}-${::testname}
|
|
|
|
- if { $::testname == "mismatch" && [readnow] } {
|
|
- # Main is found in the minimal symbols. When using readnow, a
|
|
- # failure to read the dwarf also causes the minimal symbols to be
|
|
- # unavailable.
|
|
- # Setup a kfail for "FAIL: gdb_breakpoint: set breakpoint at main".
|
|
- setup_kfail "symtab/26797" *-*-*
|
|
- }
|
|
if {![runto_main]} {
|
|
return
|
|
}
|
|
diff --git a/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp b/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
|
|
--- a/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
|
|
+++ b/gdb/testsuite/gdb.dwarf2/no-gnu-debuglink.exp
|
|
@@ -37,8 +37,8 @@ if { [build_executable $testfile.exp $testfile [list $srcfile $asm_file]] } {
|
|
|
|
clean_restart
|
|
|
|
-set msg "\r\ncould not find '\.gnu_debugaltlink' file for \[^\r\n\]*"
|
|
+set msg "\r\nwarning: could not find '\.gnu_debugaltlink' file for \[^\r\n\]*"
|
|
gdb_test "file $binfile" "$msg" "file command"
|
|
|
|
set question "Load new symbol table from .*\? .y or n. "
|
|
-gdb_test "file $binfile" "$msg" "file command, again" $question "y"
|
|
+gdb_test "file $binfile" "" "file command, again" $question "y"
|