libctf: dedup: preserve non-root flag across normal links

The previous commits dropped preservation of the non-root flag in ctf_link
and arranged to use it somewhat differently to track conflicting types in
cu-mapped CUs when doing cu-mapped links.  This was necessary to prevent
entirely spuriously hidden types from appearing on the output of such links.

Bring it (and the test for it) back.  The problem with the previous design
was that it implicitly assumed that the non-root flag it saw on the input
was always meant to be preserved (when in the final phase of cu-mapped links
it merely means that conflicting types were found in intermediate links),
and also that it could figure out what the non-root flag on the input was by
sucking in the non-root flag of the input type corresponding to an output in
the output mapping (which maps type hashes to a corresponding type on some
input).

This method of getting properties of the input type *does* work *if* that
property was one of those hashed by the ctf_dedup_hash_type process.  In
that case, every type with a given hash will have the same value for all
hashed-in properties, so it doesn't matter which one is consulted (the
output mapping points at an arbitrary one of those input types).  But the
non-root flag is explicitly *not* hashed in: as a comment in
ctf_dedup_rhash_type notes, being non-root is not a property of a type, and
two types (one non-root, one not) can perfectly well be the same type even
though one is visible and one isn't.  So just copying the non-root flag from
the output mapping's idea of the input type will copy in a value that is not
stabilized by the hash, so is more-or-less random!

So we cannot do that.  We have to do something else, which means we have to
decide what to do if two identical types with different nonroot flag values
pop up.  The most sensible thing to do is probably to say that if all
instances of a type are non-root-visible, the linked output should also be
non-root-visible: any root-visible types in that set, and the output type is
root-visible again.

We implement this with a new cd_nonroot_consistency dynhash, which maps type
hashes to the value 0 ("all instances root-visible"), 1 ("all instances
non-root-visible") or 2 ("inconsistent").  After hashing is over, we save a
bit of memory by deleting everything from this hashtab that doesn't have a
value of 1 ("non-root-visible"), then use this to decide whether to emit any
given type as non-root-visible or not.

However... that's not quite enough.  In cu-mapped links, we want to
disregard this whole thing because we just hide everything -- but in phase
2, when we take the smushed-together CUs resulting from phase 1 and
deduplicate them against each other, we want to do what the previous commits
implemented and ignore the non-root flag entirely, instead falling back to
preventing clashes by hiding anything that would be considered conflicting.
We extend the existing cu_mapped parameter to various bits of ctf_dedup so
that it is now tristate: 0 means a normal link, 1 means the smush-it-
together phase of cu-mapped links, and 2 means the final phase of cu-mapped
links.  We do the hide-conflicting stuff only in phase 2, meaning that
normal links by GNU ld can always respect the value of the nonroot flag put
on types in the input.

(One extra thing added as part of this: you can now efficiently delete the
last value returned by ctf_dynhash_next() by calling
ctf_dynhash_next_remove.)

We bring back the ctf-nonroot-linking test with one tweak: linking now works
on mingw as long as you're using the ucrt libc, so re-enable it for better
test coverage on that platform.

libctf/
	PR libctf/33047
	* ctf-hash.c (ctf_dynhash_next_remove): New.
	* ctf-impl.h (struct ctf_dedup) [cd_nonroot_consistency]: New.
	* ctf-link.c (ctf_link_deduplicating):  Differentiate between
	cu-mapped and non-cu-mapped links, even in the final phase.
	* ctf-dedup.c (ctf_dedup_hash_type): Callback prototype addition.
	Get the non-root flag and pass it down.
	(ctf_dedup_rhash_type): Callback prototype addition. Document
	restrictions on use of the nonroot flag.
	(ctf_dedup_populate_mappings): Populate cd_nonroot_consistency.
	(ctf_dedup_hash_type_fini): New function: delete now-unnecessary
	values from cd_nonroot_consistency.
	(ctf_dedup_init): Initialize it.
	(ctf_dedup_fini): Destroy it.
	(ctf_dedup): cu_mapping is now cu_mapping_phase.  Call
	ctf_dedup_hash_type_fini.
	(ctf_dedup_emit_type): Use cu_mapping_phase and
	cd_nonroot_consistency to propagate the non-root flag into outputs
	for normal links, and to do name-based conflict checking only for
	phase 2 of cu-mapped links.
	(ctf_dedup_emit): cu_mapping is now cu_mapping_phase.  Adjust
	assertion accordingly.
	* testsuite/libctf-writable/ctf-nonroot-linking.c: Bring back.
	* testsuite/libctf-writable/ctf-nonroot-linking.lk: Likewise.
6 files changed