]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf: serialize: finish off the serializer
authorNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 17:12:47 +0000 (18:12 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 17:12:47 +0000 (18:12 +0100)
The only remaining parts of serialization that need fixing up is
ctf_preserialize, which despite its name does nearly all the work of
serialization: the only bit it doesn't do is write the string tables
(since that has to happen across dicts after all the dicts have otherwise
been laid out, in order to deduplicate the strtabs).

As usual in this series, there's adjustment for various field name changes
(maxtypes -> ntypes, the move into ctf_serialize, etc), and extra work to
figure out whether we're emitting BTF or not and to handle the distinction
between CTF and BTF headers, and not try to emit CTF-only stuff like the
symtypetabs into BTF dicts; we can also throw out a bunch of old code that
sets compatibility flags, everything to do with forcing variables into the
dynamic state in case they changed (we're going to handle that more
generally for everything in the types table at a later date, outside
serialization), and everything to do with special handling of variables in
general.

But much of that is only a couple of lines each, and most of the changes are
mechanical: this is probably the simplest serialization commit in this
series.

libctf/ctf-serialize.c

index ef4bcd4313d3c02b79381e6aefec21108a8da93f..9c9e71676d14ca9b2e1ea42767bf70784cbc004a 100644 (file)
@@ -1354,15 +1354,14 @@ int
 ctf_preserialize (ctf_dict_t *fp, int force_ctf)
 {
   ctf_header_t hdr, *hdrp;
-  ctf_dvdef_t *dvd;
   ctf_dtdef_t *dtd;
   int sym_functions = 0;
+  size_t hdr_len;
+  int ctf_adjustment = 0;
 
   unsigned char *t;
-  unsigned long i;
   size_t buf_size, type_size, objt_size, func_size;
   size_t funcidx_size, objtidx_size;
-  size_t nvars;
   unsigned char *buf = NULL;
 
   emit_symtypetab_state_t symstate;
@@ -1400,16 +1399,14 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf)
         read-in buffer.  You can emit such dicts using ctf_link, which can
         change type IDs arbitrarily, resolving all overlaps.  */
 
-      if (fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff > 0 &&
-         fp->ctf_header->cth_parent_typemax < fp->ctf_parent->ctf_typemax)
+      if (fp->ctf_header->btf.bth_str_len > 0 &&
+         fp->ctf_header->cth_parent_ntypes < fp->ctf_parent->ctf_typemax)
        {
          ctf_set_errno (fp, ECTF_NOTSERIALIZED);
          ctf_err_warn (fp, 0, 0, _("cannot write out already-written child dict: parent has had %u types added"),
-                       fp->ctf_parent->ctf_typemax - fp->ctf_header->cth_parent_typemax);
+                       fp->ctf_parent->ctf_typemax - fp->ctf_header->cth_parent_ntypes);
          return -1;                            /* errno is set for us.  */
        }
-
-      fp->ctf_header->cth_parent_typemax = fp->ctf_parent->ctf_typemax;
     }
   else
     {
@@ -1431,23 +1428,22 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf)
     }
 
   /* Fill in an initial CTF header.  The type section begins at a 4-byte aligned
-     boundary past the CTF header itself (at relative offset zero).  The flag
-     indicating a new-style function info section (an array of CTF_K_FUNCTION
-     type IDs in the types section) is flipped on.  */
-
-  memset (&hdr, 0, sizeof (hdr));
-  hdr.cth_magic = CTF_MAGIC;
-  hdr.cth_version = CTF_VERSION;
-
-  /* This is a new-format func info section, and the symtab and strtab come out
-     of the dynsym and dynstr these days.  */
+     boundary past the CTF header itself (at relative offset zero).
 
-  /* UPTODO: remove.  */
-  hdr.cth_flags = (CTF_F_NEWFUNCINFO | CTF_F_DYNSTR);
+     It is quite possible that we will only write out the leading
+     ctf_btf_header_t portion of this structure.  */
 
-  /* Propagate all symbols in the symtypetabs into the dynamic state, so that
-     we can put them back in the right order.  Symbols already in the dynamic
-     state, likely due to repeated serialization, are left unchanged.  */
+  memset (&hdr, 0, sizeof (hdr));
+  hdr.btf.bth_preamble.btf_magic = CTF_BTF_MAGIC;
+  hdr.btf.bth_preamble.btf_version = CTF_BTF_VERSION;
+  hdr.btf.bth_preamble.btf_flags = 0;
+  hdr.btf.bth_hdr_len = sizeof (ctf_btf_header_t);
+  hdr.cth_preamble.ctp_magic_version = (CTFv4_MAGIC << 16) | CTF_VERSION;
+
+  /* Propagate all symbols in the symtypetabs into the dynamic state, so that we
+     can put them back in the right order during sizing.  Symbols already in the
+     dynamic state, likely due to repeated serialization, are left
+     unchanged.  */
   do
     {
       ctf_next_t *it = NULL;
@@ -1470,41 +1466,53 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf)
                                 &objtidx_size, &funcidx_size) < 0)
     return -1;                                 /* errno is set for us.  */
 
-  /* Propagate all vars into the dynamic state, so we can put them back later.
-     Variables already in the dynamic state, likely due to repeated
-     serialization, are left unchanged.  */
-
-  for (i = 0; i < fp->ctf_nvars; i++)
+  if (!fp->ctf_serialize.cs_initialized)
     {
-      const char *name = ctf_strptr (fp, fp->ctf_vars[i].ctv_name);
-
-      if (name != NULL && !ctf_dvd_lookup (fp, name))
-       if (ctf_add_variable_forced (fp, name, fp->ctf_vars[i].ctv_type) < 0)
-         return -1;                            /* errno is set for us.  */
+      if (ctf_serialize_output_format (fp, force_ctf) < 0)
+       return -1;                              /* errno is set for us.  */
     }
 
-  for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs);
-       dvd != NULL; dvd = ctf_list_next (dvd), nvars++);
-
   type_size = ctf_type_sect_size (fp);
 
   /* Compute the size of the CTF buffer we need, sans only the string table,
      then allocate a new buffer and memcpy the finished header to the start of
-     the buffer.  (We will adjust this later with strtab length info.)  */
-
-  hdr.cth_lbloff = hdr.cth_objtoff = 0;
-  hdr.cth_funcoff = hdr.cth_objtoff + objt_size;
-  hdr.cth_objtidxoff = hdr.cth_funcoff + func_size;
-  hdr.cth_funcidxoff = hdr.cth_objtidxoff + objtidx_size;
-  hdr.cth_varoff = hdr.cth_funcidxoff + funcidx_size;
-  hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t));
-  hdr.cth_stroff = hdr.cth_typeoff + type_size;
-  hdr.cth_strlen = 0;
+     the buffer.  (We will adjust this later with strtab length info.)
+
+     Offsets in the BTF and CTF headers are relative to the end of te header in
+     question.  */
+
+  if (fp->ctf_serialize.cs_is_btf)
+    {
+      ctf_dprintf ("Writing out as BTF\n");
+
+      hdr_len = sizeof (ctf_btf_header_t);
+    }
+  else
+    {
+      ctf_dprintf ("Writing out as CTF\n");
+
+      hdr_len = sizeof (ctf_header_t);
+      ctf_adjustment = sizeof (ctf_header_t) - sizeof (ctf_btf_header_t);
+    }
+
+  hdr.cth_objt_off = 0;
+  hdr.cth_objt_len = objt_size;
+  hdr.cth_func_off = hdr.cth_objt_off + objt_size;
+  hdr.cth_func_len = func_size;
+  hdr.cth_objtidx_off = hdr.cth_func_off + func_size;
+  hdr.cth_objtidx_len = objtidx_size;
+  hdr.cth_funcidx_off = hdr.cth_objtidx_off + objtidx_size;
+  hdr.cth_funcidx_len = funcidx_size;
+  hdr.btf.bth_type_off = hdr.cth_funcidx_off + funcidx_size + ctf_adjustment;
+  hdr.btf.bth_type_len = type_size;
+  hdr.btf.bth_str_off = hdr.btf.bth_type_off + type_size;
+  hdr.btf.bth_str_len = 0;
   hdr.cth_parent_strlen = 0;
   if (fp->ctf_parent)
-    hdr.cth_parent_typemax = fp->ctf_parent->ctf_typemax;
+    hdr.cth_parent_ntypes = fp->ctf_parent->ctf_typemax;
 
-  buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
+  /* No strings yet.  */
+  buf_size = sizeof (ctf_btf_header_t) + hdr.btf.bth_str_off;
 
   if ((buf = malloc (buf_size)) == NULL)
     return (ctf_set_errno (fp, EAGAIN));
@@ -1512,53 +1520,38 @@ ctf_preserialize (ctf_dict_t *fp, int force_ctf)
   fp->ctf_serialize.cs_buf = buf;
   fp->ctf_serialize.cs_buf_size = buf_size;
 
-  memcpy (buf, &hdr, sizeof (ctf_header_t));
-  t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff;
+  memcpy (buf, &hdr, hdr_len);
+  t = (unsigned char *) buf + hdr_len + hdr.cth_objt_off;
 
   hdrp = (ctf_header_t *) buf;
-  if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL))
-    ctf_str_add_no_dedup_ref (fp, fp->ctf_parname, &hdrp->cth_parname);
-  if (fp->ctf_cuname != NULL)
-    ctf_str_add_no_dedup_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname);
-
-  if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size,
-                                objtidx_size, funcidx_size) < 0)
-    goto err;
 
-  assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff);
-
-  /* Work over the variable list, translating everything into ctf_varent_t's and
-     prepping the string table.  */
-
-  fp->ctf_serializing_vars = (ctf_varent_t *) t;
-  for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL;
-       dvd = ctf_list_next (dvd), i++)
+  if (!fp->ctf_serialize.cs_is_btf)
     {
-      ctf_varent_t *var = &fp->ctf_serializing_vars[i];
-
-      ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name);
-      var->ctv_type = (uint32_t) dvd->dvd_type;
-
-      if (ctf_type_add_ref (fp, &var->ctv_type) < 0)
+      if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent_name != NULL))
+       ctf_str_add_no_dedup_ref (fp, fp->ctf_parent_name,
+                                 &hdrp->cth_parent_name);
+      if (fp->ctf_cu_name != NULL)
+       ctf_str_add_no_dedup_ref (fp, fp->ctf_cu_name, &hdrp->cth_cu_name);
+
+      if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size,
+                                    objtidx_size, funcidx_size) < 0)
        goto err;
     }
-  assert (i == nvars);
-
-  t += sizeof (ctf_varent_t) * nvars;
-  fp->ctf_serializing_nvars = nvars;
-
-  assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff);
+  assert (t == (unsigned char *) buf + sizeof (ctf_btf_header_t)
+         + hdr.btf.bth_type_off);
 
   /* Copy in existing static types, then emit new dynamic types.  */
 
-  memcpy (t, fp->ctf_buf + fp->ctf_header->cth_typeoff,
-         fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff);
-  t += fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff;
+  memcpy (t, fp->ctf_buf + fp->ctf_header->btf.bth_type_off,
+         fp->ctf_header->btf.bth_type_len);
+  t += fp->ctf_header->btf.bth_type_len;
 
-  if (ctf_emit_type_sect (fp, &t) < 0)
+  if (ctf_emit_type_sect (fp, &t, hdr.btf.bth_str_off
+                         - fp->ctf_header->btf.bth_type_len) < 0)
     goto err;
 
-  assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
+  assert (t == (unsigned char *) buf + sizeof (ctf_btf_header_t)
+         + hdr.btf.bth_str_off);
 
   /* All types laid out: update all refs to types to cite the final IDs.  */