From: Andrew Burgess <aburgess@redhat.com>
To: Simon Marchi <simon.marchi@efficios.com>, gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@efficios.com>
Subject: Re: [PATCH 4/6] gdb/dwarf: when in dwarf2_cu, read addr_size from dwarf2_cu::header
Date: Wed, 19 Nov 2025 14:30:06 +0000 [thread overview]
Message-ID: <87jyzmt7rl.fsf@redhat.com> (raw)
In-Reply-To: <20251107211041.520697-5-simon.marchi@efficios.com>
Simon Marchi <simon.marchi@efficios.com> writes:
> This patch fixes a crash caused by GDB trying to read from a section not
> read in. The bug happens in those specific circumstances:
>
> - reading a type unit from .dwo
> - that type unit has a stub in the main file
> - there is a GDB index (.gdb_index) present
>
> This crash is the cause of the following test failure:
>
> $ Running /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.dwarf2/fission-reread.exp ...
> ERROR: GDB process no longer exists
It's probably worth mentioning that this failure only occurs when using
the cc-with-gdb-index board.
>
> Or, manually:
>
> $ ./gdb -nx -q --data-directory=data-directory /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-reread/fission-reread -ex "p 1"
> Reading symbols from /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/fission-reread/fission-reread...
>
> Fatal signal: Segmentation fault
>
> For this last one, you need to interrupt the test (e.g. add a return)
> before the test deletes the .dwo file.
>
> The backtrace at the moment of the crash is:
>
> #0 0x0000555566968f7f in bfd_getl32 (p=0x0) at /home/simark/src/binutils-gdb/bfd/libbfd.c:846
> #1 0x00005555642e561d in read_initial_length (abfd=0x7d1ff1eb0e40, buf=0x0, bytes_read=0x7bfff0962fa0, handle_nonstd=true) at /home/simark/src/binutils-gdb/gdb/dwarf2/leb.c:92
> #2 0x00005555647ca9ea in read_unit_head (header=0x7d0ff1e068b0, info_ptr=0x0, section=0x7c3ff1dea7d0, section_kind=ruh_kind::COMPILE) at /home/simark/src/binutils-gdb/gdb/dwarf2/unit-head.c:44
> #3 0x000055556452e37e in dwarf2_per_cu::get_header (this=0x7d0ff1e06880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:18531
> #4 0x000055556452e574 in dwarf2_per_cu::addr_size (this=0x7d0ff1e06880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:18544
> #5 0x000055556406af91 in dwarf2_cu::addr_type (this=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/cu.c:124
> #6 0x0000555564534e48 in set_die_type (die=0x7e0ff1f23dd0, type=0x7e0ff1f027f0, cu=0x7d7ff1e20880, skip_data_location=false) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:19020
> #7 0x00005555644dcc7b in read_structure_type (die=0x7e0ff1f23dd0, cu=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:11239
> #8 0x000055556451c834 in read_type_die_1 (die=0x7e0ff1f23dd0, cu=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16878
> #9 0x000055556451c5e0 in read_type_die (die=0x7e0ff1f23dd0, cu=0x7d7ff1e20880) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16861
> #10 0x0000555564526f3a in get_signatured_type (die=0x7e0ff1f0ffb0, signature=10386129560629316377, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:17998
> #11 0x000055556451c23b in lookup_die_type (die=0x7e0ff1f0ffb0, attr=0x7e0ff1f10008, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16808
> #12 0x000055556451b2e9 in die_type (die=0x7e0ff1f0ffb0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16684
> #13 0x000055556451457f in new_symbol (die=0x7e0ff1f0ffb0, type=0x0, cu=0x7d7ff1e0f480, space=0x0) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:16089
> #14 0x00005555644c52a4 in read_variable (die=0x7e0ff1f0ffb0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:9119
> #15 0x0000555564494072 in process_die (die=0x7e0ff1f0ffb0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:5197
> #16 0x000055556449c88e in read_file_scope (die=0x7e0ff1f0fdd0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:6125
> #17 0x0000555564493671 in process_die (die=0x7e0ff1f0fdd0, cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:5098
> #18 0x00005555644912f5 in process_full_comp_unit (cu=0x7d7ff1e0f480) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:4851
> #19 0x0000555564485e18 in process_queue (per_objfile=0x7d6ff1e71100) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:4161
> #20 0x000055556446391d in dw2_do_instantiate_symtab (per_cu=0x7ceff1de42d0, per_objfile=0x7d6ff1e71100, skip_partial=true) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:1650
> #21 0x0000555564463b3c in dw2_instantiate_symtab (per_cu=0x7ceff1de42d0, per_objfile=0x7d6ff1e71100, skip_partial=true) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:1671
> #22 0x00005555644687fd in dwarf2_base_index_functions::expand_all_symtabs (this=0x7c1ff1e04990, objfile=0x7d5ff1e46080) at /home/simark/src/binutils-gdb/gdb/dwarf2/read.c:1990
> #23 0x0000555564381050 in cooked_index_functions::expand_all_symtabs (this=0x7c1ff1e04990, objfile=0x7d5ff1e46080) at /home/simark/src/binutils-gdb/gdb/dwarf2/cooked-index.h:237
> #24 0x0000555565df5b0d in objfile::expand_all_symtabs (this=0x7d5ff1e46080) at /home/simark/src/binutils-gdb/gdb/symfile-debug.c:372
> #25 0x0000555565eafc4a in maintenance_expand_symtabs (args=0x0, from_tty=1) at /home/simark/src/binutils-gdb/gdb/symmisc.c:914
>
> The main file contains a stub (skeleton) for a compilation unit and a
> stub for a type unit. The .dwo file contains a compilation unit and a
> type unit matching those stubs. When doing the initial scan of the main
> file, the DWARF reader parses the CU/TU list from the GDB index
> (.gdb_index), and thus creates a signatured_type object based on that.
> The section field of this signatured_type points to the .debug_types
> section in the main file, the one containing the stub. And because GDB
> trusts the GDB index, it never needs to look at that .debug_types
> section in the main file. That section remains not read in.
>
> When expanding the compilation unit, GDB encounters a type unit
> reference (by signature) corresponding to the type in the type unit. We
> get in lookup_dwo_signatured_type, trying to see if there is a type unit
> matching that signature in the current .dwo file. We proceed to read
> and expand that type unit, until we eventually get to a
> dwarf2_cu::addr_type() call, which doess:
>
> int addr_size = this->per_cu->addr_size ();
>
> dwarf2_per_cu::addr_size() tries to read the header from the section
> pointed to by dwarf2_per_cu::section which, if you recall, is the
> .debug_types section in the main file that was never read in. That
> causes the segfault.
>
> All this was working fine before these patches of mine, that tried to do
> some cleanups:
>
> a47e2297fc28 ("gdb/dwarf: pass section offset to dwarf2_per_cu_data constructor")
> c44ab627b021 ("gdb/dwarf: pass section to dwarf2_per_cu_data constructor")
> 39ee8c928551 ("gdb/dwarf: pass unit length to dwarf2_per_cu_data constructor")
>
> Before these patches, the fill_in_sig_entry_from_dwo_entry function
> (called from lookup_dwo_signatured_type, among others) would overwrite
> some dwarf2_per_cu fields (including the section) to point to the .dwo,
> rather than represent what's in the main file. Therefore, the header
> would have been read from the unit in the .dwo file, and things would
> have been fine.
>
> When doing these changes, I mistakenly assumed that the section written
> by fill_in_sig_entry_from_dwo_entry was the same as the section already
> there, which is why I removed the statements overwriting the section
> field (and the two others). To my defense, here's the comment on
> dwarf2_per_cu::section:
>
> /* The section this CU/TU lives in.
> If the DIE refers to a DWO file, this is always the original die,
> not the DWO file. */
> struct dwarf2_section_info *section = nullptr;
>
> I would prefer to not reintroduce the behavior of overwriting the
> section info in dwarf2_per_cu, because:
>
> 1. I find it confusing, I like the invariant of dwarf2_per_cu::section
> points to the stub, and dwarf2_cu::section points to where we
> actually read the debug info from.
> 2. The dwarf2_per_bfd::all_units vector is nowadays sorted by (section,
> section offset). If we change the section and section offset of a
> dwarf2_per_cu, then we can no longer do binary searches in it, we
> would have to re-sort the vector (not a big deal, but still adds to
> the confusion).
>
> One possible fix would be to make sure that the section is read in when
> reading the header, probably in dwarf2_per_cu::get_header. An approach
> like that was proposed by Andrew initially, here:
>
> https://inbox.sourceware.org/gdb-patches/60ba2b019930fd6164f8e6ab6cb2e396c32c6ac2.1759486109.git.aburgess@redhat.com/
>
> It would work, but there is a more straightforward fix for this
> particular problem, I believe. In dwarf2_cu, we have access to the
> header read from the unit we're actually reading the DWARF from. In the
> DWO case, that is the header read from the .dwo file. We can get the
> address size from there instead of going through the dwarf2_per_cu
> object. This is what this patch does.
This looks good to me.
I would encourage you to consider extending the existing test to cover
this case without needing to test with the cc-with-gdb-index board. I
think the reality is most people don't test every patch with every
board. But I do understand that, if taken to extreme, that would mean
running every test in every mode, which clearly doesn't scale. But when
we run into a regression my instinct is to ensure that the default test
mode covers this case. And there's plenty of precedent for this in the
testsuite, e.g. gdb.server/*.exp. You're welcome to take the test
changes from the patch linked above if that is useful.
Also in the patch linked above is the addition of an assert:
gdb_assert (this->section ()->readin);
in 'dwarf2_per_cu::get_header ()'. I haven't checked the later patches
from this series yet, so maybe you already do something similar, but if
not, maybe it would be good to add something like that in this patch,
given that this is dealing with the assert caused by the section not
being read in?
Anyway, these aren't hard requirements, just my thoughts. I think the
fix looks good.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Thanks,
Andrew
next prev parent reply other threads:[~2025-11-19 14:31 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-07 21:10 [PATCH 0/6] Type unit + split DWARF fixes (PR 33307) Simon Marchi
2025-11-07 21:10 ` [PATCH 1/6] gdb/testsuite/dwarf: use single abbrev table in .dwo files Simon Marchi
2025-11-10 20:14 ` Simon Marchi
2025-11-18 13:32 ` Andrew Burgess
2025-11-18 16:50 ` Simon Marchi
2025-11-18 16:55 ` Andrew Burgess
2025-11-18 17:20 ` Simon Marchi
2025-11-19 16:05 ` Tom Tromey
2025-11-19 20:21 ` Simon Marchi
2025-11-07 21:10 ` [PATCH 2/6] gdb/testsuite/dwarf: convert _section proc to use parse_options Simon Marchi
2025-11-19 10:59 ` Andrew Burgess
2025-11-19 15:53 ` Tom Tromey
2025-11-19 20:40 ` Simon Marchi
2025-11-19 21:03 ` Tom Tromey
2025-11-07 21:10 ` [PATCH 3/6] gdb/testsuite/dwarf: emit type unit sections as COMDAT Simon Marchi
2025-11-19 11:43 ` Andrew Burgess
2025-11-07 21:10 ` [PATCH 4/6] gdb/dwarf: when in dwarf2_cu, read addr_size from dwarf2_cu::header Simon Marchi
2025-11-19 14:30 ` Andrew Burgess [this message]
2025-11-19 20:46 ` Simon Marchi
2025-11-19 16:11 ` Tom Tromey
2025-11-19 20:51 ` Simon Marchi
2025-11-07 21:10 ` [PATCH 5/6] gdb/dwarf: store addr/offset/ref_addr sizes in dwarf2_per_cu Simon Marchi
2025-11-19 14:42 ` Andrew Burgess
2025-11-19 16:14 ` Tom Tromey
2025-11-21 19:54 ` Simon Marchi
2025-11-21 21:25 ` Tom Tromey
2025-11-07 21:10 ` [PATCH 6/6] gdb/dwarf: use dwarf2_per_cu::ref_addr_size in one spot Simon Marchi
2025-11-19 14:44 ` Andrew Burgess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87jyzmt7rl.fsf@redhat.com \
--to=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=simon.marchi@efficios.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox