libctf, link: fix CU-mapped links with CTF_LINK_EMPTY_CU_MAPPINGS
authorNick Alcock <nick.alcock@oracle.com>
Fri, 7 Apr 2023 19:09:24 +0000 (20:09 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Sat, 8 Apr 2023 15:07:17 +0000 (16:07 +0100)
commit869a750c0ec0abcab84e38a43a1ed73321ef4371
treeb404adbb8d7acbc8b55d860b9301a683ca10b047
parentd7474051e87c5804c2b674c0d3ad78030f0464a7
libctf, link: fix CU-mapped links with CTF_LINK_EMPTY_CU_MAPPINGS

This is a bug in the intersection of two obscure options that cannot
even be invoked from ld with a feature added to stop ld of the
same input file repeatedly from crashing the linker.

The latter fix involved tracking input files (internally to libctf) not
just with their input CU name but with a version of their input CU name
that was augmented with a numeric prefix if their linker input file name
was changed, to prevent distinct CTF dicts with the same cuname from
overwriting each other. (We can't use just the linker input file name
because one linker input can contain many CU dicts, particularly under
ld -r).  If these inputs then produced conflicting types, those types
were emitted into similarly-named output dicts, so we needed similar
machinery to detect clashing output dicts and add a numeric prefix to
them as well.

This works fine, except that if you used the cu-mapping feature to force
double-linking of CTF (so that your CTF can be grouped into output dicts
larger than a single translation unit) and then also used
CTF_LINK_EMPTY_CU_MAPPINGS to force every possible output dict in the
mapping to be created (even if empty), we did the creation of empty dicts
first, and then all the actual content got considered to be a clash. So
you ended up with a pile of useless empty dicts and then all the content
was in full dicts with the same names suffixed with a #0.  This seems
likely to confuse consumers that use this facility.

Fixed by generating all the EMPTY_CU_MAPPINGS empty dicts after linking
is complete, not before it runs.

No impact on ld, which does not do cu-mapped links or pass
CTF_LINK_EMPTY_CU_MAPPINGS to ctf_link().

libctf/
* ctf-link.c (ctf_create_per_cu): Don't create new dicts iff one
        already exists and we are making one for no input in particular.
        (ctf_link): Emit empty CTF dicts corresponding to no input in
        particular only after linkiing is complete.
libctf/ctf-link.c