summaryrefslogtreecommitdiff
path: root/libctf
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2021-05-06 09:30:58 +0100
committerNick Alcock <nick.alcock@oracle.com>2021-05-06 09:30:59 +0100
commit49da556c658684db1b8bdba956e541bc99628f02 (patch)
treea116f7a2004adbeb9f597dfa0397c2a969460853 /libctf
parent15091ded14ec08bd3f3a686d420c6009e1d2c518 (diff)
libctf, include: support an alternative encoding for nonrepresentable types
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.
Diffstat (limited to 'libctf')
-rw-r--r--libctf/ChangeLog15
-rw-r--r--libctf/NEWS3
-rw-r--r--libctf/ctf-create.c33
-rw-r--r--libctf/ctf-dedup.c14
-rw-r--r--libctf/ctf-open.c4
-rw-r--r--libctf/ctf-types.c9
-rw-r--r--libctf/libctf.ver1
7 files changed, 69 insertions, 10 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index e66224a4fd..51ecc85f75 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -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.
diff --git a/libctf/NEWS b/libctf/NEWS
index c0aef3b83a..956cca8473 100644
--- a/libctf/NEWS
+++ b/libctf/NEWS
@@ -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
diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index e87b91e928..2d232d4003 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -966,6 +966,39 @@ ctf_add_forward (ctf_dict_t *fp, uint32_t flag, const char *name,
}
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)
{
diff --git a/libctf/ctf-dedup.c b/libctf/ctf-dedup.c
index 572a68d57a..649a76a91b 100644
--- a/libctf/ctf-dedup.c
+++ b/libctf/ctf-dedup.c
@@ -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,
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index 8d11134f01..1c69dc8310 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -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
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index 9afe06ba11..243de9348d 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -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;
diff --git a/libctf/libctf.ver b/libctf/libctf.ver
index 8c362f3c39..0b182f3722 100644
--- a/libctf/libctf.ver
+++ b/libctf/libctf.ver
@@ -201,4 +201,5 @@ LIBCTF_1.2 {
global:
ctf_lookup_by_symbol_name;
ctf_arc_lookup_symbol_name;
+ ctf_add_unknown;
} LIBCTF_1.1;