libctf: create, types: conflicting types

The conflicting type kind is a CTF-specific prefix kind consisting purely of
an optional translation unit name.  It takes the place of the old hidden
bit: we have already seen it used to prefix types added with a
CTF_ADD_NONROOT flag.  The deduplicator will also use them to label
conflicting types from different TUs smushed into the same dict by the
CU-mapping mechanism: unlike the hidden bit, with this scheme users can tell
which CUs the conflicting types came from.

New API:

+int ctf_type_conflicting (ctf_dict_t *, ctf_id_t, const char **cuname);
+int ctf_set_conflicting (ctf_dict_t *, ctf_id_t, const char *);

(Frankly I expect ctf_set_conflicting to be used only by deduplicators and
things like that, but if we provide an option to query something we should
also provide an option to produce it...)
This commit is contained in:
Nick Alcock
2025-04-25 11:23:46 +01:00
parent fb8917ac21
commit d5dd8997b3
4 changed files with 96 additions and 1 deletions

View File

@@ -674,6 +674,13 @@ extern int ctf_type_kind (ctf_dict_t *, ctf_id_t);
extern int ctf_type_kind_forwarded (ctf_dict_t *, ctf_id_t);
/* Return nonzero if this type is conflicting, zero if it's not, < 0 on error; if
CUNAME is set, set it to the name of the conflicting compilation unit for the
passed-in type (which may be a null string if the cuname is not known, or if
this is not a conflicting type). */
extern int ctf_type_conflicting (ctf_dict_t *, ctf_id_t, const char **cuname);
/* Return the type a pointer, typedef, cvr-qual, or slice refers to, or return
an ECTF_NOTREF error otherwise. ctf_type_kind pretends that slices are
actually the type they are a slice of: this is usually want you want, but if
@@ -1008,7 +1015,13 @@ extern ctf_id_t ctf_add_section_variable (ctf_dict_t *, uint32_t,
extern int ctf_set_array (ctf_dict_t *, ctf_id_t, const ctf_arinfo_t *);
/* Add a function oor object symbol type with a particular name, without saying
/* Mark a type as conflicting, residing in some other translation unit with a
given name. The type is hidden from all name lookups, just like
CTF_ADD_NONROOT. */
extern int ctf_set_conflicting (ctf_dict_t *, ctf_id_t, const char *);
/* Add a function or object symbol type with a particular name, without saying
anything about the actual symbol index. (The linker will then associate them
with actual symbol indexes using the ctf_link functions below.) */

View File

@@ -928,6 +928,43 @@ ctf_set_array (ctf_dict_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
return 0;
}
/* Set this type as conflicting in compilation unit CUNAME. */
int
ctf_set_conflicting (ctf_dict_t *fp, ctf_id_t type, const char *cuname)
{
ctf_dict_t *ofp = fp;
ctf_dtdef_t *dtd;
ctf_type_t *prefix;
uint32_t idx;
if (ctf_lookup_by_id (&fp, type, NULL) == NULL)
return -1; /* errno is set for us. */
idx = ctf_type_to_index (fp, type);
dtd = ctf_dtd_lookup (fp, type);
/* You can only call ctf_set_conflicting on a type you have added, not a type
that was read in via ctf_open. */
if (idx < fp->ctf_stypes)
return (ctf_set_errno (ofp, ECTF_RDONLY));
if (dtd == NULL)
return (ctf_set_errno (ofp, ECTF_BADID));
if ((prefix = (ctf_type_t *) ctf_find_prefix (fp, dtd->dtd_buf,
CTF_K_CONFLICTING)) == NULL)
{
if ((prefix = ctf_add_prefix (fp, dtd, 0)) == NULL)
return -1; /* errno is set for us. */
}
prefix->ctt_name = ctf_str_add (fp, cuname);
prefix->ctt_info = CTF_TYPE_INFO (CTF_K_CONFLICTING, 0,
dtd->dtd_vlen_size < 65536
? dtd->dtd_vlen_size : 0);
return 0;
}
/* Add a type or decl tag applying to some whole type, or to some
component of a type. Component -1 is a whole type. */

View File

@@ -1631,6 +1631,49 @@ ctf_type_kind_forwarded (ctf_dict_t *fp, ctf_id_t type)
return ret;
}
/* Return nonzero if this type is conflicting, nonzero if it's not, < 0 on
error; if CUNAME is set, set it to the name of the conflicting compilation
unit for the passed-in type (which may be a null string if the cuname is not
known). */
int
ctf_type_conflicting (ctf_dict_t *fp, ctf_id_t type, const char **cuname)
{
ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
/* The unimplemented / void type is never conflicting. */
if (type == 0)
return 0;
if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
return -1; /* errno is set for us. */
if ((tp = ctf_lookup_by_id (&fp, type, NULL)) == NULL)
return -1; /* errno is set for us. */
if (cuname)
*cuname = 0;
if (LCTF_INFO_ISROOT (fp, tp->ctt_info))
return 0;
if (!cuname)
return 1;
while (LCTF_INFO_UNPREFIXED_KIND (fp, tp->ctt_info) != CTF_K_CONFLICTING
&& LCTF_IS_PREFIXED_INFO (tp->ctt_info))
tp++;
/* We already checked that this is a non-root-visible type, so this must be
CTF_K_CONFLICTING. */
if (!ctf_assert (ofp, LCTF_IS_PREFIXED_INFO (tp->ctt_info)))
return -1; /* errno is set for us. */
*cuname = ctf_strptr (fp, tp->ctt_name);
return 1;
}
/* If the type is one that directly references another type (such as POINTER),
then return the ID of the type to which it refers. */

View File

@@ -77,6 +77,7 @@ LIBCTF_2.0 {
ctf_type_align;
ctf_type_kind;
ctf_type_kind_forwarded;
ctf_type_conflicting;
ctf_type_reference;
ctf_type_linkage;
ctf_type_pointer;
@@ -155,6 +156,7 @@ LIBCTF_2.0 {
ctf_add_member_bitfield;
ctf_set_array;
ctf_set_conflicting;
ctf_update;
ctf_discard;