https://sourceware.org/bugzilla/show_bug.cgi?id=33047

Nick Alcock <nick.alcock at oracle dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|unassigned at sourceware dot org   |nick.alcock at oracle 
dot com
             Status|NEW                         |ASSIGNED

--- Comment #1 from Nick Alcock <nick.alcock at oracle dot com> ---
The underlying problem here is commit 87b2f673102884d7c69144c85a26ed5dbaa4f86a
("libctf: fix linking of non-root-visible types"). The idea there was to
preserve cases where the caller of ctf_add_*() had requested at type-add time
that the type should be hidden, by passing the hidden flag through to the
output. 

Unfortunately this fails because we don't actually consider the hidden flag to
be part of the type: if someone inserts some struct with the hidden flag on,
and then the exact same struct with it off, we don't want to emit two structs!
So when the deduplicator hides types when merging CUs together in this weird
cu-mapped link mode, if it hides a type in one CU (because that CU has multiple
conflicting definitions of it) and then doesn't hide it in some others, we will
consider all those types identical; because they're identical, we will
propagate the properties of that type from a *randomly-chosen* instance of that
type onto the output.  Which means we get a randomly-chosen non-root flag, and
half the time the type is hidden.

We really have two distinct cases here.

 - The user has chosen to hide types via ctf_add_*()'s CTF_ADD_NONROOT flag.
This is usually for non-C but C-compatible type systems, which are rarely
linked, but if the user *does* elect to link them, it would be very confusing
to find all those nonroot flags stripped off. This is what the problematic
commit was trying to fix (and failing).

 - The user hasn't done anything with nonroot flags -- probably this is
compiler output via -gctf -- and a cu-mapped link is running. This uses the
nonroot flag so that when it smushes together compilation units'-worth of CTF,
the link does not fail because of name duplication, even if some types are
conflicting. We don't really care what the state of the nonroot flag is at this
stage: after smushing together translation units, cu-mapped linking does
another pass of deduplication and dedups all the smushed-together CUs against
each other. At this stage, if it ignores the nonroot flag, it can figure out
which of these conflicting types can be promoted into the shared dict and which
must be left conflicting.

So we can solve this by distinguishing the two cases.  Hide absolutely
everything when smushing compilation units together: every single type. Then
ignore the nonroot flag when deduplicating the smushed-together compilation
units against each other, but do not hide everything: instead, only hide types
if they would otherwise collide (colliding names, colliding enumerands).

When doing normal links with GNU ld, don't do any of this: none of these
collisions can ever happen, because in a normal link any conflicting type is
moved into a per-CU child which corresponds to a single real C translation
unit, and these cannot contain conflicting names because that would be an
identifier clash in C as well. So in GNU ld-based links we can preserve the
nonroot flag as the user expects: we only have to ignore it in cu-mapped links
(and the input to such links always comes from the compiler, and never uses the
non-root flag, so that's fine too.)

Fix under test.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to