libctf: add LIBCTF_WRITE_FOREIGN_ENDIAN debugging option
authorNick Alcock <nick.alcock@oracle.com>
Fri, 18 Mar 2022 13:20:29 +0000 (13:20 +0000)
committerNick Alcock <nick.alcock@oracle.com>
Wed, 23 Mar 2022 13:48:32 +0000 (13:48 +0000)
commitfaf5e6ace8c6f82e11ad40393f531123515ce3e6
treee773b6f688ea22554e98c6c4768a3fe58b44dd44
parent84f5c557a4883d336b238e4bf5264bb920e008d9
libctf: add LIBCTF_WRITE_FOREIGN_ENDIAN debugging option

libctf has always handled endianness differences by detecting
foreign-endian CTF dicts on the input and endian-flipping them: dicts
are always written in native endianness.  This makes endian-awareness
very low overhead, but it means that the foreign-endian code paths
almost never get routinely tested, since "make check" usually reads in
dicts ld has just written out: only a few corrupted-CTF tests are
actually in fixed endianness, and even they only test the foreign-
endian code paths when you run make check on a big-endian machine.
(And the fix is surely not to add more .s-based tests like that, because
they are a nightmare to maintain compared to the C-code-based ones.)

To improve on this, add a new environment variable,
LIBCTF_WRITE_FOREIGN_ENDIAN, which causes libctf to unconditionally
endian-flip at ctf_write time, so the output is always in the wrong
endianness.  This then tests the foreign-endian read paths properly
at open time.

Make this easier by restructuring the writeout code in ctf-serialize.c,
which duplicates the maybe-gzip-and-write-out code three times (once
for ctf_write_mem, with thresholding, and once each for
ctf_compress_write and ctf_write just so those can avoid thresholding
and/or compression).  Instead, have the latter two call the former
with thresholds of 0 or (size_t) -1, respectively.

The endian-flipping code itself gains a bit of complexity, because
one single endian-flipper (flip_types) was assuming the input to be
in foreign-endian form and assuming it could pull things out of the
input once they had been flipped and make sense of them. At the
cost of a few lines of duplicated initializations, teach it to
read before flipping if we're flipping to foreign-endianness instead
of away from it.

libctf/
* ctf-impl.h (ctf_flip_header): No longer static.
(ctf_flip): Likewise.
* ctf-open.c (flip_header): Rename to...
(ctf_flip_header): ... this, now it is not private to one file.
(flip_ctf): Rename...
(ctf_flip): ... this too.  Add FOREIGN_ENDIAN arg.
(flip_types): Likewise.  Use it.
(ctf_bufopen_internal): Adjust calls.
* ctf-serialize.c (ctf_write_mem): Add flip_endian path via
a newly-allocated bounce buffer.
(ctf_compress_write): Move below ctf_write_mem and reimplement
in terms of it.
(ctf_write): Likewise.
(ctf_gzwrite): Note that this obscure writeout function does not
support endian-flipping.
libctf/ctf-impl.h
libctf/ctf-open.c
libctf/ctf-serialize.c