From: Bernd Edlinger <bernd.edlinger@hotmail.de>
To: Andrew Burgess <aburgess@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH] gdb: handle DW_AT_entry_pc pointing at an empty sub-range
Date: Wed, 27 Nov 2024 21:12:22 +0100 [thread overview]
Message-ID: <DU2PR08MB10263EA307E097C5B8CB2C1FDE4282@DU2PR08MB10263.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <87bjy1lwcn.fsf@redhat.com>
On 11/26/24 18:48, Andrew Burgess wrote:
> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>
>> On 11/25/24 15:30, Andrew Burgess wrote:
>>> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>>>
>>>> Okay, I just wanted to point out that in my opinion the debug info which
>>>> points at the end of a sub-range is not incorrect, just maybe on a border
>>>> line, where the dwarf spec is unclear. So you should not say:
>>>> "after all, the DWARF spec is clear that such a range covers no code."
>>>>
>>>> But there are obviously not only cases where the entry_pc points at
>>>> an empty sub-range, but also in very rare cases the entry_pc points at
>>>> the end of a non-empty sub-range.
>>>> So could you please change the check in dwarf2_addr_in_block_ranges
>>>> from addr >= start && addr < end to addr >= start && addr <= end.
>>>
>>> Could you expand on why you believe that the DWARF spec is unclear in
>>> this regard. I came to my conclusion based on this text within the
>>> DWARF-5 specification, section 2.17.3 Non-Contiguous Address Ranges:
>>>
>>> Bounded range. This kind of entry defines an address range that is
>>> included in the range list. The starting address is the lowest address
>>> of the address range. The ending address is the address of the first
>>> location past the highest address of the address range
>>>
>>> This seems pretty clear (to me) that the end address is not part of the
>>> region covered by a range.
>>>
>>
>> Yes, but on the other hand, when we look at line table entries, each has a
>> PC and a VIEW number, and even the DW_AT_entry_pc has a DW_AT_GNU_entry_view,
>> just the range list does not have a view number, and that is inconsistent
>> with the concept of location views.
>>
>> Consider as a simple example an inline function:
>>
>> int f(int x)
>> {
>> x++;
>> return x;
>> }
>>
>> it will most likely just be compiled into one "inc eax" or similar,
>> and of course you may want to set a break point on the return statement,
>> to inspect 'x' after the increment, but that will be on 'pc == end' !
>>
>> But if the location view number would not be missing from the rnglist
>> it would be obvious whether the corresponding view number is still within
>> subroutine and not outside. So in my opinion it is a defect in the
>> specification that it does not reflect this use case.
>
> You make an interesting argument that the specification is deficient.
> But I'm not sure how this helps with this discussion. I would like to
> avoid derailing this conversation with discussion of missing DWARF
> features.
>
>>
>>> Additionally, if we start to accept 'addr == end' then this is going to
>>> cause problems elsewhere. GDB will place a b/p at the 'end' address,
>>> but when GDB then performs block lookup, GDB will not return the block
>>> we expect, and so GDB will not report the inferior as having stopped in
>>> the scope that the user expects.
>>>
>>
>> No, because this is exactly what the core of my patch does, admittedly
>> I also modified the block lookup code a bit, to handle that case.
>> So I strongly disagree here: we have to accept 'addr == end' and other
>> corner cases, otherwise my patch won't work in the end, regardless of in
>> how many small bug-fixes it can be split up, because it depends exactly
>> on not ignoring any information while parsing the debug info.
>
> But accepting 'addr == end' only works if you also change the block
> lookup mechanism, which isn't part of this patch. This patch is based
> on the state of block lookup as it exists today.
>
> I've included a patch below which applies on top of this patch (i.e. the
> one this thread is about), it changes the check to accept 'addr == end'
> as you suggest. It also updates the test so that an inline function
> (bar) has DW_AT_entry_pc point at the 'end' address of a non-empty
> sub-range.
>
> Here's a GDB session with that patch applied:
>
> (gdb) b bar
> Breakpoint 1 at 0x401137
> (gdb) r
> Starting program: /tmp/gdb/testsuite/outputs/gdb.dwarf2/dw2-entry-pc-in-empty-range/dw2-entry-pc-in-empty-range-4
>
> Breakpoint 1, 0x0000000000401137 in foo ()
> (gdb) maintenance info blocks
> Blocks at 0x401137:
> from objfile: [(objfile *) 0x3b11720] /tmp/gdb/testsuite/outputs/gdb.dwarf2/dw2-entry-pc-in-empty-range/dw2-entry-pc-in-empty-range-4
>
> [(block *) 0x357e680] 0x401106..0x401185
> entry pc: 0x401106
> is global block
> symbol count: 1
> is contiguous
> [(block *) 0x357e630] 0x401106..0x401185
> entry pc: 0x401106
> is static block
> is contiguous
> [(block *) 0x357e5e0] 0x401106..0x401185
> entry pc: 0x401106
> function: foo
> is contiguous
> (gdb)
>
> As you can see, GDB stops at an address which doesn't then resolve to
> the bar block.
>
Ah, okay, thanks for the test case I looked into it and tried it out with
a gdb built with my patch.
A breakpoint an an empty subrange works as expected, but indeed a breakpoint
at the end of a non-empty subrange does behave as you described.
But with real code examples a break point at the end of a non-empty subrange
does work, and that is because my "heuristic" which does the magic, uses
weak line-table entries near the end of a subrange to determine what to do
here. So because the test case does not have a line table at all, the
test case is not realistic in that aspect, and does not tell you what happens
here in a real world example.
So a patch that allows for start <= addr && addr <= end should be applied,
probably with a line table that looks more like a real line table especially
at the end of a subrange, then the test should probably work out of the box.
But it is okay to do that after the rest of the series is applied.
> If/when the block lookup code is changed as you propose then this
> restriction (addr < end) can be relaxed. But it doesn't make sense to
> merge the relaxed restriction, without the block lookup changes.
>
> And no, I don't see that as a reason to merge all of the changes at
> once. I think splitting the original large change into many small steps
> is the correct approach. And sometimes that will mean that we check
> something in, and then revise it in a later commit. That's not a
> problem with this approach, it's an advantage of this approach. It
> makes it clearer how we got to the final destination. And each step is
> smaller, and easier to review. This is the preferred approach for GDB
> patches.
>
> I feel that, as the author of the original large change, you're looking
> ahead and you're frustrated that this code isn't inline with how you
> feel the code should finally look. But just because I hope we can check
> this code in first, doesn't mean that I will prevent this code being
> changed later on. As GDB evolves (e.g. if the block lookup code
> changes) then I'm happy for this code to evolve with it.
>
> To (I hope) offer you some confidence, I have, on my machine, created a
> branch with this patch (without the 'addr == end' change), followed by
> the next two patches I plan to post (once this is merged), and then, on
> top of that, I have rebased your original series. This includes all of
> your original tests completely unmodified.
>
> I have tested this merge with gcc versions 14.2.0, 13.3.0, 12.2.0,
> 11.5.0, 10.5.0, 9.5.0, 9.3.1, 8.4.0, 8.1.0, and in all cases, all of
> your original tests pass. I'd rather not post this merged branch just
> yet, as I'm worried that this might derail review of this patch even
> more, I really don't want to start discussing the next patches before
> they are even posted, but if it's the only way to move this patch
> forward then I could share the branch. I do plan to make this unified
> branch available when I post the next two patches I'd like to upstream,
> as I think it will actually help at that point.
>
> My hope is that you will be willing to accept this change on the
> understanding that this code might need to be modified in the future.
>
> For my part I also accept that this code might need to change in the
> future.
>
Well okay, please go ahead.
Thanks
Bernd.
> Thanks,
> Andrew
>
> ---
>
> ### Patch to show 'addr == end' doesn't work (yet) ###
>
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index c178b13d96d..60daf032036 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -11351,7 +11351,7 @@ dwarf2_addr_in_block_ranges (CORE_ADDR addr, struct block *block)
> /* Check if ADDR is within any of the block's sub-ranges. */
> for (const blockrange &br : block->ranges ())
> {
> - if (addr >= br.start () && addr < br.end ())
> + if (addr >= br.start () && addr <= br.end ())
> return true;
> }
>
> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-entry-pc-in-empty-range.exp b/gdb/testsuite/gdb.dwarf2/dw2-entry-pc-in-empty-range.exp
> index 79b1783b2ec..9e4fb781a8d 100644
> --- a/gdb/testsuite/gdb.dwarf2/dw2-entry-pc-in-empty-range.exp
> +++ b/gdb/testsuite/gdb.dwarf2/dw2-entry-pc-in-empty-range.exp
> @@ -179,8 +179,8 @@ proc run_test { entry_label dwarf_version } {
> " $::foo_5\\.\\.$::foo_6"]
> }
>
> -foreach_with_prefix entry_label { foo_3 foo_4 } {
> - foreach_with_prefix dwarf_version { 4 5 } {
> +foreach_with_prefix entry_label { foo_2 } {
> + foreach_with_prefix dwarf_version { 4 } {
> run_test $entry_label $dwarf_version
> }
> }
>
next prev parent reply other threads:[~2024-11-27 20:12 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-20 15:01 Andrew Burgess
2024-11-20 21:00 ` Kevin Buettner
2024-11-21 13:21 ` Bernd Edlinger
2024-11-22 16:53 ` Andrew Burgess
2024-11-22 22:57 ` Bernd Edlinger
2024-11-25 14:30 ` Andrew Burgess
2024-11-26 12:35 ` Bernd Edlinger
2024-11-26 17:48 ` Andrew Burgess
2024-11-27 20:12 ` Bernd Edlinger [this message]
2024-11-28 10:10 ` Andrew Burgess
2024-11-28 17:44 ` [PATCHv2] " Andrew Burgess
2024-11-29 14:19 ` Bernd Edlinger
2024-12-02 10:53 ` 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=DU2PR08MB10263EA307E097C5B8CB2C1FDE4282@DU2PR08MB10263.eurprd08.prod.outlook.com \
--to=bernd.edlinger@hotmail.de \
--cc=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
/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