libctf, include: support an alternative encoding for nonrepresentable types
authorNick Alcock <nick.alcock@oracle.com>
Thu, 6 May 2021 08:30:58 +0000 (09:30 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Thu, 6 May 2021 08:30:59 +0000 (09:30 +0100)
Before now, types that could not be encoded in CTF were represented as
references to type ID 0, which does not itself appear in the
dictionary. This choice is annoying in several ways, principally that it
forces generators and consumers of CTF to grow special cases for types
that are referenced in valid dicts but don't appear.

Allow an alternative representation (which will become the only
representation in format v4) whereby nonrepresentable types are encoded
as actual types with kind CTF_K_UNKNOWN (an already-existing kind
theoretically but not in practice used for padding, with value 0).
This is backward-compatible, because CTF_K_UNKNOWN was not used anywhere
before now: it was used in old-format function symtypetabs, but these
were never emitted by any compiler and the code to handle them in libctf
likely never worked and was removed last year, in favour of new-format
symtypetabs that contain only type IDs, not type kinds.

In order to link this type, we need an API addition to let us add types
of unknown kind to the dict: we let them optionally have names so that
GCC can emit many different unknown types and those types with identical
names will be deduplicated together.  There are also small tweaks to the
deduplicator to actually dedup such types, to let opening of dicts with
unknown types with names work, to return the ECTF_NONREPRESENTABLE error
on resolution of such types (like ID 0), and to print their names as
something useful but not a valid C identifier, mostly for the sake of
the dumper.

Tests added in the next commit.

include/ChangeLog
2021-05-06  Nick Alcock  <nick.alcock@oracle.com>

* ctf.h (CTF_K_UNKNOWN): Document that it can be used for
nonrepresentable types, not just padding.
* ctf-api.h (ctf_add_unknown): New.

libctf/ChangeLog
2021-05-06  Nick Alcock  <nick.alcock@oracle.com>

* ctf-open.c (init_types): Unknown types may have names.
* ctf-types.c (ctf_type_resolve): CTF_K_UNKNOWN is as
non-representable as type ID 0.
(ctf_type_aname): Print unknown types.
* ctf-dedup.c (ctf_dedup_hash_type): Do not early-exit for
CTF_K_UNKNOWN types: they have real hash values now.
(ctf_dedup_rwalk_one_output_mapping): Treat CTF_K_UNKNOWN types
like other types with no referents: call the callback and do not
skip them.
(ctf_dedup_emit_type): Emit via...
* ctf-create.c (ctf_add_unknown): ... this new function.
* libctf.ver (LIBCTF_1.2): Add it.

include/ChangeLog
include/ctf-api.h
include/ctf.h
libctf/ChangeLog
libctf/NEWS
libctf/ctf-create.c
libctf/ctf-dedup.c
libctf/ctf-open.c
libctf/ctf-types.c
libctf/libctf.ver

index 0f277f95a61b4f0bbd7fa9911d20e32380dc8bea..aed37fd563a9e644402250f487b79ecdae2e4e28 100644 (file)
@@ -1,3 +1,9 @@
+2021-05-06  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ctf.h (CTF_K_UNKNOWN): Document that it can be used for
+       nonrepresentable types, not just padding.
+       * ctf-api.h (ctf_add_unknown): New.
+
 2021-04-22  ClĂ©ment Chigot  <clement.chigot@atos.net>
 
        * coff/internal.h (union internal_auxent):
index 25dbe9ec53358f8db14218083fdd3cb3a2f93a89..fa8f2cd5b684b7238b65c9a1cf2b9ed289347cfd 100644 (file)
@@ -491,6 +491,7 @@ extern ctf_id_t ctf_add_struct_sized (ctf_dict_t *, uint32_t, const char *,
                                      size_t);
 extern ctf_id_t ctf_add_union_sized (ctf_dict_t *, uint32_t, const char *,
                                     size_t);
+extern ctf_id_t ctf_add_unknown (ctf_dict_t *, uint32_t, const char *);
 extern ctf_id_t ctf_add_volatile (ctf_dict_t *, uint32_t, ctf_id_t);
 
 extern int ctf_add_enumerator (ctf_dict_t *, ctf_id_t, const char *, int);
index 90631fccbd60110da9acd472e6e3e222e6c61fab..fa31c46983d3baaa9b3128eccffdd1f34c0892fc 100644 (file)
@@ -405,7 +405,8 @@ union
    CTF_INFO_VLEN() will extract the number of elements in the list, and
    the type of each element is shown in the comments below. */
 
-#define CTF_K_UNKNOWN  0       /* Unknown type (used for padding).  */
+#define CTF_K_UNKNOWN  0       /* Unknown type (used for padding and
+                                  unrepresentable types).  */
 #define CTF_K_INTEGER  1       /* Variant data is CTF_INT_DATA (see below).  */
 #define CTF_K_FLOAT    2       /* Variant data is CTF_FP_DATA (see below).  */
 #define CTF_K_POINTER  3       /* ctt_type is referenced type.  */
index e66224a4fd1d8d4da7513149f1e006a6276afa69..51ecc85f75a7d953c742e0f610efbfcd3af89549 100644 (file)
@@ -1,3 +1,18 @@
+2021-05-06  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ctf-open.c (init_types): Unknown types may have names.
+       * ctf-types.c (ctf_type_resolve): CTF_K_UNKNOWN is as
+       non-representable as type ID 0.
+       (ctf_type_aname): Print unknown types.
+       * ctf-dedup.c (ctf_dedup_hash_type): Do not early-exit for
+       CTF_K_UNKNOWN types: they have real hash values now.
+       (ctf_dedup_rwalk_one_output_mapping): Treat CTF_K_UNKNOWN types
+       like other types with no referents: call the callback and do not
+       skip them.
+       (ctf_dedup_emit_type): Emit via...
+       * ctf-create.c (ctf_add_unknown): ... this new function.
+       * libctf.ver (LIBCTF_1.2): Add it.
+
 2021-03-25  Nick Alcock  <nick.alcock@oracle.com>
 
        * configure.ac: Check for dlsym, not dlopen.
index c0aef3b83ad0d861a862880548aa6232ca8091db..956cca8473e4f93d2719be76c86fb5db7dd8bcee 100644 (file)
@@ -10,6 +10,9 @@ Changes in 2.37:
    symbol number is known, like in object files and dynamic dicts created by
    ctf_create.
 
+** libctf supports compilers that encode unrepresentable types via a special
+   kind (CTF_K_UNKNOWN) as well as via type ID 0.
+
 * Bugfixes
 
 ** Avoid duplicating or losing types of data object symbols when
index e87b91e928e8549235eae38171714da6bf4825ee..2d232d40037bed09e3a030cdfc5295bab07c7d0b 100644 (file)
@@ -965,6 +965,39 @@ ctf_add_forward (ctf_dict_t *fp, uint32_t flag, const char *name,
   return type;
 }
 
+ctf_id_t
+ctf_add_unknown (ctf_dict_t *fp, uint32_t flag, const char *name)
+{
+  ctf_dtdef_t *dtd;
+  ctf_id_t type = 0;
+
+  /* If a type is already defined with this name, error (if not CTF_K_UNKNOWN)
+     or just return it.  */
+
+  if (name != NULL && name[0] != '\0' && flag == CTF_ADD_ROOT
+      && (type = ctf_lookup_by_rawname (fp, CTF_K_UNKNOWN, name)))
+    {
+      if (ctf_type_kind (fp, type) == CTF_K_UNKNOWN)
+       return type;
+      else
+       {
+         ctf_err_warn (fp, 1, ECTF_CONFLICT,
+                       _("ctf_add_unknown: cannot add unknown type "
+                         "named %s: type of this name already defined"),
+                       name ? name : _("(unnamed type)"));
+         return (ctf_set_errno (fp, ECTF_CONFLICT));
+       }
+    }
+
+  if ((type = ctf_add_generic (fp, flag, name, CTF_K_UNKNOWN, 0, &dtd)) == CTF_ERR)
+    return CTF_ERR;            /* errno is set for us.  */
+
+  dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNKNOWN, flag, 0);
+  dtd->dtd_data.ctt_type = 0;
+
+  return type;
+}
+
 ctf_id_t
 ctf_add_typedef (ctf_dict_t *fp, uint32_t flag, const char *name,
                 ctf_id_t ref)
index 572a68d57ad54f589210115fd910af20bffa88a3..649a76a91b62a55d5ac86214fd5651f3664bfea1 100644 (file)
@@ -1064,10 +1064,6 @@ ctf_dedup_hash_type (ctf_dict_t *fp, ctf_dict_t *input,
   if (tp->ctt_name == 0 || !name || name[0] == '\0')
     name = NULL;
 
-  /* Treat the unknown kind just like the unimplemented type.  */
-  if (kind == CTF_K_UNKNOWN)
-    return "00000000000000000000";
-
   /* Decorate the name appropriately for the namespace it appears in: forwards
      appear in the namespace of their referent.  */
 
@@ -2075,8 +2071,6 @@ ctf_dedup_rwalk_one_output_mapping (ctf_dict_t *output,
   switch (ctf_type_kind_unsliced (fp, type))
     {
     case CTF_K_UNKNOWN:
-      /* Just skip things of unknown kind.  */
-      return 0;
     case CTF_K_FORWARD:
     case CTF_K_INTEGER:
     case CTF_K_FLOAT:
@@ -2702,9 +2696,11 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs,
   switch (kind)
     {
     case CTF_K_UNKNOWN:
-      /* These are types that CTF cannot encode, marked as such by the compile.
-        We intentionally do not re-emit these.  */
-      new_type = 0;
+      /* These are types that CTF cannot encode, marked as such by the
+        compiler.  */
+      errtype = _("unknown type");
+      if ((new_type = ctf_add_unknown (target, isroot, name)) == CTF_ERR)
+       goto err_target;
       break;
     case CTF_K_FORWARD:
       /* This will do nothing if the type to which this forwards already exists,
index 8d11134f01731f1acd90286b94eb178aae00e401..1c69dc83102d95e8bb612efdc547b34a160084a2 100644 (file)
@@ -756,7 +756,8 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
     return ENOMEM;
 
   if ((fp->ctf_names.ctn_readonly
-       = ctf_hash_create (pop[CTF_K_INTEGER] +
+       = ctf_hash_create (pop[CTF_K_UNKNOWN] +
+                         pop[CTF_K_INTEGER] +
                          pop[CTF_K_FLOAT] +
                          pop[CTF_K_FUNCTION] +
                          pop[CTF_K_TYPEDEF] +
@@ -800,6 +801,7 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
 
       switch (kind)
        {
+       case CTF_K_UNKNOWN:
        case CTF_K_INTEGER:
        case CTF_K_FLOAT:
          /* Names are reused by bit-fields, which are differentiated by their
index 9afe06ba112db4af14901b470b893354ccdf34fd..243de9348d3ec01c68faa50f8b797b84611c7663 100644 (file)
@@ -579,6 +579,8 @@ ctf_type_resolve (ctf_dict_t *fp, ctf_id_t type)
          prev = type;
          type = tp->ctt_type;
          break;
+       case CTF_K_UNKNOWN:
+         return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
        default:
          return type;
        }
@@ -808,6 +810,13 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
            case CTF_K_RESTRICT:
              ctf_decl_sprintf (&cd, "restrict");
              break;
+           case CTF_K_UNKNOWN:
+             if (name[0] == '\0')
+               ctf_decl_sprintf (&cd, _("(nonrepresentable type)"));
+             else
+               ctf_decl_sprintf (&cd, _("(nonrepresentable type %s)"),
+                                 name);
+             break;
            }
 
          k = cdp->cd_kind;
index 8c362f3c39e07725524cc0110e88538eb503ffcc..0b182f37228de0b340327fd04550452b41472a4b 100644 (file)
@@ -201,4 +201,5 @@ LIBCTF_1.2 {
     global:
        ctf_lookup_by_symbol_name;
        ctf_arc_lookup_symbol_name;
+       ctf_add_unknown;
 } LIBCTF_1.1;