libctf: serialize: handle CTF-versus-BTF output format checks

The internal function ctf_serialize_output_format centralizes all the checks
for BTF-versus-CTF, checking to see if the type section, active
suppressions, and BTF-emission mode permit BTF emission, setting
ctf_serialize.cs_is_btf if we are actually BTF, and raising ECTF_NOTBTF if
we are requiring BTF emission but the type section is such that we can't
emit it.

(There is a forcing parameter in place, as with most of these serialization
functions, to allow for the caller to force CTF emission if it knows the
output will be compressed or will be part of multi-member archives or
something else external to the type section that BTF does not support.)
This commit is contained in:
Nick Alcock
2025-04-25 17:54:48 +01:00
parent 585f569a2d
commit d5012389a4

View File

@@ -1290,8 +1290,57 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr,
/* Overall serialization. */
/* Determine the output format. Returns 0 on successful determination or -1 and
an error if an attempt is being made to write out a CTF dict but the library
state prohibits it, or a per-dict prohibition is preventing the writeout of a
type kind that this dict contains. */
int
ctf_serialize_output_format (ctf_dict_t *fp, int force_ctf)
{
int ctf_needed = 0;
if (fp->ctf_flags & LCTF_NO_STR)
return (ctf_set_errno (fp, ECTF_NOPARENT));
/* Complain if we're asked to emit BTF only, but we have types that call for
CTFv4 extensions, or we are forced to emit CTF because the caller requested
compression. */
if (force_ctf)
ctf_needed = 1;
if (ctf_needed && _libctf_btf_mode == LIBCTF_BTM_BTF)
goto err_not_btf;
/* Relatively expensive, so done after cheap checks. */
if (!ctf_type_sect_is_btf (fp, force_ctf))
ctf_needed = 1;
if (ctf_needed && _libctf_btf_mode == LIBCTF_BTM_BTF)
goto err_not_btf;
if (_libctf_btf_mode == LIBCTF_BTM_ALWAYS
|| (_libctf_btf_mode == LIBCTF_BTM_POSSIBLE && ctf_needed))
fp->ctf_serialize.cs_is_btf = 0;
else
fp->ctf_serialize.cs_is_btf = 1;
fp->ctf_serialize.cs_initialized = 1;
return 0;
err_not_btf:
ctf_set_errno (fp, ECTF_NOTBTF);
/* TODO: a little more info? */
if (force_ctf)
ctf_err_warn (fp, 0, 0, _("Cannot write out dict as BTF: compression requested"));
else
ctf_err_warn (fp, 0, 0, _("Cannot write out dict as BTF: would lose information"));
return -1;
}
/* Do all aspects of serialization up to strtab writeout, including final type
ID assignment. The resulting dict will have the LCTF_PRESERIALIZED flag on
and must not be modified in any way before serialization. (This is only