Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: Simon Marchi <simark@simark.ca>, Tom Tromey <tom@tromey.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH] [gdb/symtab] Add assert in free_cached_comp_units constructor
Date: Mon, 8 Jun 2026 16:20:48 +0200	[thread overview]
Message-ID: <7be245c1-7f93-4485-acd6-aaa33b8cb927@suse.de> (raw)
In-Reply-To: <e30160a8-7534-47c8-bac5-ea052e2ca791@simark.ca>

On 6/1/26 5:18 PM, Simon Marchi wrote:
> On 6/1/26 4:02 AM, Tom de Vries wrote:
>> On 5/30/26 2:52 PM, Tom de Vries wrote:
>>> On 5/28/26 6:43 PM, Tom Tromey wrote:
>>>>>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:
>>>>
>>>> Tom> Detect this situation using an assert in the free_cached_comp_units
>>>> Tom> constructor.
>>>>
>>>> Seems fine to me.
>>>
>>> Thanks for the review.
>>>
>>> I committed this, but afterwards ran into trouble on x86_64-linux with test-cases gdb.ada/uninitialized-variable-record.exp and gdb.ada/ uninitialized_vars.exp on x86_64-linux, so I've reverted this.
>>>
>>
>> I've investigated this, and found that this is due to calls to load_cu in places other than dw2_do_instantiate_symtab.
>>
>> For test-case gdb.ada/uninitialized_vars.exp, it's dwarf2_fetch_die_loc_cu_off.
>>
>> I do wonder if ~free_cached_comp_units is a bit overeager, and should refrain from deleting cached comp units that were present at construction time.
>>
>> Anyway, the assert detected the use-after-free I created, but just doesn't hold in general.
> 
> Let's try to understand why things are the way they are currently.
> 
> Why do we want to delete the just created dwarf2_cus in
> dw2_instantiate_symtab?  I presume it's because the chances of them
> being useful again are slim.  We created the GDB types and symbols, we
> don't need to keep the DIE structure  loaded in memory, so it's better
> to free up the memory.
> 
> The cases where the dwarf2_cus are needed again later appear to be when
> evaluating a some DWARF operator that refers to other DIEs directly,
> such as DW_OP_call*, DW_OP_implicit_pointer, DW_OP_GNU_variable_value,
> etc.
> 
>   - dwarf2_fetch_die_loc_sect_off
>   - dwarf2_fetch_die_loc_cu_off
>   - dwarf2_fetch_constant_bytes
>   - dwarf2_fetch_die_type_sect_off
> 
> In those cases we re-load the right dwarf2_cu in memory to be able to
> look up the DIE and get what we want from it.  In those cases, we don't
> free up the just-loaded dwarf2_cu right away, because it presumably has
> good chances of being needed again in the near future, for other
> operators.  We instead use the "age_comp_units" mechanism, which frees
> the dwarf2_cus once they have been sitting there unused for a while.
> 
> I am unable to reproduce the gdb.ada failures, but the case that you
> looked at appears to be one where a dwarf2_cu was loaded by one of those
> "dwarf2_fetch_*" functions, while evaluating a DWARF expression, and
> then dw2_instantiate_symtab was called to expand a compunit into full
> symbols.  So free_cached_comp_units deletes the dwarf2_cu previously
> cached by the "dwarf2_fetch_*" functions.  I don't think this is wrong
> (as in a correctness bug), so I don't think the assert was right, it
> might just be ineffcient cache usage.  I don't know if it's problematic
> enough to be worth fixing, but if you can think of a simple solution for
> dw2_instantiate_symtab not to delete the pre-existing dwarf2_cus, we
> could consider it.
> 
> It would perhaps be good to investigate whether this "age comp units"
> machinery is still working as initially intended.  It's possible that
> will all the refactors we've done over the years, it's not working as
> intended.  And because it's just a cache, it would not break any tests,
> but it could cause peformance problems.  While searching the code, I
> looked where `cu->last_used` is reset, to prevent the CU from being
> freed by age_comp_units.  It is reset in maybe_queue_comp_unit, which is
> itself called in:
> 
>   - follow_die_sig_1
>   - process_imported_unit_die
>   - follow_die_offset
> 
> Note that those are all used in cross-CU reference cases, when a CU
> needs something from another CU.
> 
> `age_comp_units()` is called in:
> 
>   - dw2_do_instantiate_symtab, when done expanding the symtab(s)
>   - dwarf2_fetch_die_loc_sect_off, when done fetching the location info
> 
> Some fishy things I spotted:
> 
>   - The age_comp_units() call in dw2_do_instantiate_symtab suggests that
>     the comp unit aging system was also meant to be used when expanding
>     symtabs.  The fact that all the places that reset `cu->last_used` are
>     some that handle cross-CU references also suggests this.  The idea
>     might have been that if a CU refers to another CU (via DW_AT_import
>     for instance), then there is a good chance that subsequent CUs will
>     also refer to that second CUs.  So when you're done expanding the
>     first CU, better keep that second CU in cache for when you'll be
>     expanding more CUs.  However, if we free up all cached CUs in
>     dw2_instantiate_symtab via free_cached_comp_units, doesn't it defeat
>     the purpose?  Why call age_comp_units()  in dw2_do_instantiate_symtab
>     if we're going to free them all up in the caller anyway?
> 
>   - Calling dwarf2_fetch_die_loc_sect_off ages the comp units, but
>     shouldn't it also reset the `cu->last_used` field of the CU from
>     which we found the info?  Otherwise, repeated calls to
>     dwarf2_fetch_die_loc_sect_off targetting the same CU will cause that
>     CU to be freed, even if we just used it and will keep needing it
>     (causing it to be re-loaded from scratch the next time).
> 

Hi Simon,

thanks for the comments.

I'm not sure when I'll have the time to follow up on all this, so I've 
filed a review PR ( https://sourceware.org/bugzilla/show_bug.cgi?id=34243 ).

Thanks,
- Tom

> Simon


      reply	other threads:[~2026-06-08 14:21 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-27  9:57 Tom de Vries
2026-05-28 16:43 ` Tom Tromey
2026-05-30 12:52   ` Tom de Vries
2026-06-01  8:02     ` Tom de Vries
2026-06-01 15:18       ` Simon Marchi
2026-06-08 14:20         ` Tom de Vries [this message]

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=7be245c1-7f93-4485-acd6-aaa33b8cb927@suse.de \
    --to=tdevries@suse.de \
    --cc=gdb-patches@sourceware.org \
    --cc=simark@simark.ca \
    --cc=tom@tromey.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