]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf: serialize: handle CTF-versus-BTF output format checks
authorNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 16:54:48 +0000 (17:54 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 17:07:44 +0000 (18:07 +0100)
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.)

libctf/ctf-serialize.c

index 2cbaafc4e17a091e957e7bd87f0ef408c9269e98..ef4bcd4313d3c02b79381e6aefec21108a8da93f 100644 (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