From: Nick Alcock Date: Fri, 25 Apr 2025 10:23:46 +0000 (+0100) Subject: libctf: create, types: conflicting types X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5dd8997b3464e7518e4a9db690fc4d195d8075f;p=thirdparty%2Fbinutils-gdb.git 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...) --- diff --git a/include/ctf-api.h b/include/ctf-api.h index e986cadee09..dd159c3836c 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -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.) */ diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 6a22aca1d67..ba8c266dd8d 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -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. */ diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index dac1ec50468..275e5c00e15 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -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. */ diff --git a/libctf/libctf.ver b/libctf/libctf.ver index 66ddb530a1b..c8525b5f1d5 100644 --- a/libctf/libctf.ver +++ b/libctf/libctf.ver @@ -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;