]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf: create: DTD addition and deletion; ctf_rollback
authorNick Alcock <nick.alcock@oracle.com>
Thu, 24 Apr 2025 15:11:53 +0000 (16:11 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 17:07:42 +0000 (18:07 +0100)
DTD deletion changes mostly relate to the changes to the ctf_dtdef_t, but
also we no longer nede to have special handling for forwards (we can just
use ctf_type_kind_forwarded like everyone else).

Rollback no longer needs to delete things by hand (it hasn't needed to for
years): it can just call ctf_dtd_delete.

ctf_add_generic changes substantially, mostly to allow for the ctf_dtdef_t
changes.  Rather than returning a type ID it now returns the DTD it just
allocated: it can also be asked to add some prefixes, and return the first
prefix added (which may not be the first prefix in the type, because if it
is asked to add a non-root-visible type it will additionally allocate a
CTF_K_CONFLICTING prefix to encode that).

Finally, duplicate name detection is suppressed for type and decl tags.

libctf/ctf-create.c

index 86cc8e590a70aaa511c526748c9d455a7ef00129..1a5665b15bc992aef1bf46d459ff4b420662ed42 100644 (file)
@@ -303,28 +303,20 @@ ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
 void
 ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd)
 {
-  int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
-  int name_kind = kind;
-  const char *name;
+  const char *name = ctf_type_name_raw (fp, dtd->dtd_type);
+  int name_kind = ctf_type_kind_forwarded (fp, dtd->dtd_type);
 
-  ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type);
+  /* Repeated calls should do nothing.  */
+  if (name_kind < 0 && ctf_errno (fp) == ECTF_BADID)
+    return;
 
-  switch (kind)
-    {
-    case CTF_K_FORWARD:
-      name_kind = dtd->dtd_data.ctt_type;
-      break;
-    }
-  free (dtd->dtd_vlen);
-  dtd->dtd_vlen_alloc = 0;
+  ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type);
 
-  if (dtd->dtd_data.ctt_name
-      && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
-    {
-      if (LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
-       ctf_dynhash_remove (ctf_name_table (fp, name_kind), name);
-    }
+  if (name != NULL && name[0] != '\0'
+      && LCTF_INFO_ISROOT (fp, dtd->dtd_buf->ctt_info))
+    ctf_dynhash_remove (ctf_name_table (fp, name_kind), name);
 
+  free (dtd->dtd_buf);
   ctf_list_delete (&fp->ctf_dtdefs, dtd);
   free (dtd);
 }
@@ -404,24 +396,10 @@ ctf_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id)
 
   for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
     {
-      int kind;
-      const char *name;
-
       ntd = ctf_list_next (dtd);
 
       if (ctf_type_to_index (fp, dtd->dtd_type) <= id.dtd_id)
        continue;
-
-      kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
-      if (kind == CTF_K_FORWARD)
-       kind = dtd->dtd_data.ctt_type;
-
-      if (dtd->dtd_data.ctt_name
-         && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
-         && LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
-       ctf_dynhash_remove (ctf_name_table (fp, kind), name);
-
-      ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type);
       ctf_dtd_delete (fp, dtd);
     }
 
@@ -524,12 +502,19 @@ ctf_assign_id (ctf_dict_t *fp)
   return ctf_index_to_type (fp, idx);
 }
 
-/* Note: vlen is the amount of space *allocated* for the vlen.  It may well not
-   be the amount of space used (yet): the space used is declared in per-kind
-   fashion in the dtd_data's info word.  */
-static ctf_id_t
+/* Note: vbytes is the amount of space needed by the vlen, plus as many as are
+   needed by the PREFIXES, plus any further prefixes (e.g. for hidden types).
+   It is required to be the amount of space used, as recorded in the per-kind
+   info word.  vbytes_extra is some extra space that can be allocated to reduce
+   realloc calls.
+
+   TYPEP is a pointer to either the actual type structure with the name in it,
+   or to the first prefix requested by PREFIXES, if nonzero.  */
+
+static ctf_dtdef_t *
 ctf_add_generic (ctf_dict_t *fp, uint32_t flag, const char *name, int kind,
-                size_t vbytes, ctf_dtdef_t **rp)
+                int prefixes, size_t vbytes, size_t vbytes_extra,
+                ctf_type_t **typep)
 {
   ctf_dtdef_t *dtd;
   ctf_id_t type;
@@ -539,71 +524,116 @@ ctf_add_generic (ctf_dict_t *fp, uint32_t flag, const char *name, int kind,
     pfp = fp->ctf_parent;
 
   if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
-    return (ctf_set_typed_errno (fp, EINVAL));
+    {
+      ctf_set_errno (fp, EINVAL);
+      return NULL;
+    }
 
   if (fp->ctf_typemax + 1 >= pfp->ctf_provtypemax)
-    return (ctf_set_typed_errno (fp, ECTF_FULL));
+    {
+      ctf_set_errno (fp, ECTF_FULL);
+      return NULL;
+    }
 
   /* Prohibit addition of types in the middle of serialization.  */
 
   if (fp->ctf_flags & LCTF_NO_TYPE)
-    return (ctf_set_errno (fp, ECTF_NOTSERIALIZED));
+    {
+      ctf_set_errno (fp, ECTF_NOTSERIALIZED);
+      return NULL;
+    }
 
   if (fp->ctf_flags & LCTF_NO_STR)
-    return (ctf_set_errno (fp, ECTF_NOPARENT));
+    {
+      ctf_set_errno (fp, ECTF_NOPARENT);
+      return NULL;
+    }
 
   if (fp->ctf_flags & LCTF_CHILD && fp->ctf_parent == NULL)
-    return (ctf_set_errno (fp, ECTF_NOPARENT));
+    {
+      ctf_set_errno (fp, ECTF_NOPARENT);
+      return NULL;
+    }
 
   /* Prohibit addition of a root-visible type that is already present
-     in the non-dynamic portion. */
+     in the non-dynamic portion.  Two exceptions: type and decl tags,
+     whose identifier tables are unusual (duplicates are expected).  */
 
-  if (flag == CTF_ADD_ROOT && name != NULL && name[0] != '\0')
+  if (flag == CTF_ADD_ROOT && name != NULL && name[0] != '\0'
+      && kind != CTF_K_TYPE_TAG && kind != CTF_K_DECL_TAG)
     {
       ctf_id_t existing;
 
       if (((existing = ctf_dynhash_lookup_type (ctf_name_table (fp, kind),
                                                name)) > 0)
          && ctf_static_type (fp, existing))
-       return (ctf_set_typed_errno (fp, ECTF_RDONLY));
+       {
+         ctf_set_errno (fp, ECTF_RDONLY);
+         return NULL;
+       }
     }
 
   /* Make sure ptrtab always grows to be big enough for all types.  */
   if (ctf_grow_ptrtab (fp) < 0)
-    return CTF_ERR;                            /* errno is set for us. */
+    return NULL;                               /* errno is set for us. */
 
   if ((dtd = calloc (1, sizeof (ctf_dtdef_t))) == NULL)
-    return (ctf_set_typed_errno (fp, EAGAIN));
-
-  dtd->dtd_vlen_alloc = vbytes;
-  if (vbytes > 0)
     {
-      if ((dtd->dtd_vlen = calloc (1, vbytes)) == NULL)
-       goto oom;
+      ctf_set_typed_errno (fp, EAGAIN);
+      return NULL;
     }
-  else
-    dtd->dtd_vlen = NULL;
+
+  dtd->dtd_buf_size = vbytes + vbytes_extra + sizeof (ctf_type_t);
+  dtd->dtd_vlen_size = vbytes;
+
+  /* The non-root flag is implemented via prefixes.  */
+  if (flag == CTF_ADD_NONROOT)
+    dtd->dtd_buf_size += sizeof (ctf_type_t);
+
+  if (prefixes)
+    dtd->dtd_buf_size += (sizeof (ctf_type_t) * prefixes);
+
+  if ((dtd->dtd_buf = calloc (1, dtd->dtd_buf_size)) == NULL)
+    goto oom;
+  dtd->dtd_vlen = ((unsigned char *) dtd->dtd_buf) + dtd->dtd_buf_size
+    - vbytes - vbytes_extra;
+  dtd->dtd_data = (ctf_type_t *) (dtd->dtd_vlen - sizeof (ctf_type_t));
 
   type = ctf_assign_id (fp);
 
-  dtd->dtd_data.ctt_name = ctf_str_add (fp, name);
+  /* Populate a conflicting type kind if need be.  This has vlen-in-bytes filled
+     in if small enough to fit, to help prefix-unaware clients skip the prefix
+     easily, but the vlen is otherwise redundant (and not used by libctf).  */
+  if (flag == CTF_ADD_NONROOT)
+    dtd->dtd_buf->ctt_info = CTF_TYPE_INFO (CTF_K_CONFLICTING, 0,
+                                           dtd->dtd_vlen_size < 65536
+                                           ? dtd->dtd_vlen_size : 0);
+
+  dtd->dtd_data->ctt_name = ctf_str_add (fp, name);
   dtd->dtd_type = type;
 
-  if (dtd->dtd_data.ctt_name == 0 && name != NULL && name[0] != '\0')
+  if (dtd->dtd_data->ctt_name == 0 && name != NULL && name[0] != '\0')
     goto oom;
 
   if (ctf_dtd_insert (fp, dtd, flag, kind) < 0)
     goto err;                                  /* errno is set for us.  */
 
-  *rp = dtd;
-  return type;
+  /* Return a pointer to the first user-requested prefix, if any.  i.e., don't
+     return a pointer to the non-root CONFLICTING header.  */
+
+  if (typep)
+    *typep = dtd->dtd_buf + (flag == CTF_ADD_NONROOT);
+
+  fp->ctf_serialize.cs_initialized = 0;
+
+  return dtd;
 
  oom:
   ctf_set_errno (fp, EAGAIN);
  err:
-  free (dtd->dtd_vlen);
+  free (dtd->dtd_buf);
   free (dtd);
-  return CTF_ERR;
+  return NULL;
 }
 
 /* When encoding integer sizes, we want to convert a byte count in the range