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.