[PATCH 4/4] libctf: fix cv-qualified unnamed struct/union field lookup
Stephen Brennan
stephen.s.brennan@oracle.com
Wed Feb 26 17:21:39 GMT 2025
On 2/25/25 13:10, Nick Alcock wrote:
> GCC permits not only unnamed structs and unions, but cv-qualified ones.
> Our earlier fix in 6c3a38777b38a2ad87e2b2bcec4567578d1c83ec supported
> unnamed structs and unions, but only unqualified ones.
>
> Resolving away cvr-quals of nameless fields (and, irrelevantly, typedefs)
> is easy and fixes this problem.
>
> Tests adjusted accordingly.
For what it's worth (and if binutils uses these trailers):
Tested-by: Stephen Brennan <stephen.s.brennan@oracle.com>
>
> libctf/
> PR libctf/32746
> * ctf-types.c (ctf_member_next): Resolve away cv-quals.
> (ctf_member_info): Likewise.
> * testsuite/libctf-lookup/struct-iteration-ctf.c: Add a cv-qualified
> type or two: make sure to keep a non-qualified one.
> * testsuite/libctf-lookup/struct-iteration.c: Verify consistency
> of ctf_member_next and ctf_member_info.
> * testsuite/libctf-lookup/struct-iteration.lk: Adjust.
> ---
> libctf/ctf-types.c | 33 +++++++++++++++----
> .../libctf-lookup/struct-iteration-ctf.c | 7 ++--
> .../libctf-lookup/struct-iteration.c | 18 ++++++++++
> .../libctf-lookup/struct-iteration.lk | 10 +++---
> 4 files changed, 55 insertions(+), 13 deletions(-)
>
> diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
> index 067a5d8c3a0..044a1852c1a 100644
> --- a/libctf/ctf-types.c
> +++ b/libctf/ctf-types.c
> @@ -187,10 +187,21 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
> *membtype = memb.ctlm_type;
> offset = (unsigned long) CTF_LMEM_OFFSET (&memb);
>
> - if (membname[0] == 0
> - && (ctf_type_kind (fp, memb.ctlm_type) == CTF_K_STRUCT
> - || ctf_type_kind (fp, memb.ctlm_type) == CTF_K_UNION))
> - i->ctn_type = memb.ctlm_type;
> + if (membname[0] == 0)
> + {
> + ctf_id_t resolved;
> +
> + if ((resolved = ctf_type_resolve (fp, memb.ctlm_type)) == CTF_ERR)
> + {
> + if (ctf_errno (fp) != ECTF_NONREPRESENTABLE)
> + return -1; /* errno is set for us. */
> + resolved = memb.ctlm_type;
> + }
> +
> + if (ctf_type_kind (fp, resolved) == CTF_K_STRUCT
> + || ctf_type_kind (fp, resolved) == CTF_K_UNION)
> + i->ctn_type = resolved;
> + }
> i->ctn_n++;
>
> /* The callers might want automatic recursive sub-struct traversal. */
> @@ -1406,16 +1417,24 @@ ctf_member_info (ctf_dict_t *fp, ctf_id_t type, const char *name,
> {
> ctf_lmember_t memb;
> const char *membname;
> + ctf_id_t resolved;
>
> if (ctf_struct_member (fp, &memb, tp, vlen, vbytes, i) < 0)
> return (ctf_set_errno (ofp, ctf_errno (fp)));
>
> membname = ctf_strptr (fp, memb.ctlm_name);
>
> + if ((resolved = ctf_type_resolve (fp, memb.ctlm_type)) == CTF_ERR)
> + {
> + if (ctf_errno (fp) != ECTF_NONREPRESENTABLE)
> + return (ctf_set_errno (ofp, ctf_errno (fp)));
> + resolved = memb.ctlm_type;
> + }
> +
> if (membname[0] == 0
> - && (ctf_type_kind (fp, memb.ctlm_type) == CTF_K_STRUCT
> - || ctf_type_kind (fp, memb.ctlm_type) == CTF_K_UNION)
> - && (ctf_member_info (fp, memb.ctlm_type, name, mip) == 0))
> + && (ctf_type_kind (fp, resolved) == CTF_K_STRUCT
> + || ctf_type_kind (fp, resolved) == CTF_K_UNION)
> + && (ctf_member_info (fp, resolved, name, mip) == 0))
> {
> mip->ctm_offset += (unsigned long) CTF_LMEM_OFFSET (&memb);
> return 0;
> diff --git a/libctf/testsuite/libctf-lookup/struct-iteration-ctf.c b/libctf/testsuite/libctf-lookup/struct-iteration-ctf.c
> index 7df67adaad4..0a50d2c35af 100644
> --- a/libctf/testsuite/libctf-lookup/struct-iteration-ctf.c
> +++ b/libctf/testsuite/libctf-lookup/struct-iteration-ctf.c
> @@ -6,12 +6,12 @@ struct foo_t
> size_t bar;
> const char *baz;
> struct foo_t *self;
> - union
> + const volatile union
> {
> double should_not_appear;
> char *nor_should_this;
> } named;
> - struct
> + volatile const struct
> {
> long unnamed_sub_member;
> union
> @@ -19,6 +19,9 @@ struct foo_t
> double one_more_level;
> long yes_really_one_more;
> };
> + struct {
> + int and_finally;
> + };
> };
> struct {}; /* Empty ones */
> union {};
> diff --git a/libctf/testsuite/libctf-lookup/struct-iteration.c b/libctf/testsuite/libctf-lookup/struct-iteration.c
> index b2408648e7e..fd89ca77f67 100644
> --- a/libctf/testsuite/libctf-lookup/struct-iteration.c
> +++ b/libctf/testsuite/libctf-lookup/struct-iteration.c
> @@ -51,11 +51,29 @@ main (int argc, char *argv[])
> while ((offset = ctf_member_next (fp, type, &i, &name, &membtype,
> CTF_MN_RECURSE)) >= 0)
> {
> + ctf_membinfo_t memb;
> char *type_name = ctf_type_aname (fp, membtype);
>
> printf ("next test: %s, offset %zx, has type %lx/%s\n",
> name, offset, membtype, type_name);
> free (type_name);
> +
> + /* Check that we can get the same member via ctf_member_info too. */
> + if (name[0] != '\0')
> + {
> + if (ctf_member_info (fp, type, name, &memb) != 0)
> + {
> + fprintf (stderr, "Cannot get member info for %s: %s\n",
> + name, ctf_errmsg (ctf_errno (fp)));
> + exit (1);
> + }
> + if (memb.ctm_offset != offset || memb.ctm_type != membtype)
> + {
> + fprintf (stderr, "ctf_member_info versus iteration comparison "
> + "failure: types %lx/%lx, offsets %zx/%lx\n",
> + membtype, memb.ctm_type, offset, memb.ctm_offset);
> + }
> + }
> }
> if (ctf_errno (fp) != ECTF_NEXT_END)
> goto nerr;
> diff --git a/libctf/testsuite/libctf-lookup/struct-iteration.lk b/libctf/testsuite/libctf-lookup/struct-iteration.lk
> index fd644547f20..aecffd44c85 100644
> --- a/libctf/testsuite/libctf-lookup/struct-iteration.lk
> +++ b/libctf/testsuite/libctf-lookup/struct-iteration.lk
> @@ -4,8 +4,8 @@ iter test: foo, offset [0-9a-f]*, has type [0-9a-f]*/int
> iter test: bar, offset [0-9a-f]*, has type [0-9a-f]*/size_t
> iter test: baz, offset [0-9a-f]*, has type [0-9a-f]*/const char \*
> iter test: self, offset [0-9a-f]*, has type [0-9a-f]*/struct foo_t \*
> -iter test: named, offset [0-9a-f]*, has type [0-9a-f]*/union
> -iter test: , offset [0-9a-f]*, has type [0-9a-f]*/struct
> +iter test: named, offset [0-9a-f]*, has type [0-9a-f]*/volatile const union
> +iter test: , offset [0-9a-f]*, has type [0-9a-f]*/volatile const struct
> iter test: , offset [0-9a-f]*, has type [0-9a-f]*/struct
> iter test: , offset [0-9a-f]*, has type [0-9a-f]*/union
> iter test: after_the_end, offset [0-9a-f]*, has type [0-9a-f]*/int
> @@ -13,12 +13,14 @@ next test: foo, offset [0-9a-f]*, has type [0-9a-f]*/int
> next test: bar, offset [0-9a-f]*, has type [0-9a-f]*/size_t
> next test: baz, offset [0-9a-f]*, has type [0-9a-f]*/const char \*
> next test: self, offset [0-9a-f]*, has type [0-9a-f]*/struct foo_t \*
> -next test: named, offset [0-9a-f]*, has type [0-9a-f]*/union
> -next test: , offset [0-9a-f]*, has type [0-9a-f]*/struct
> +next test: named, offset [0-9a-f]*, has type [0-9a-f]*/volatile const union
> +next test: , offset [0-9a-f]*, has type [0-9a-f]*/volatile const struct
> next test: unnamed_sub_member, offset [0-9a-f]*, has type [0-9a-f]*/long int
> next test: , offset [0-9a-f]*, has type [0-9a-f]*/union
> next test: one_more_level, offset [0-9a-f]*, has type [0-9a-f]*/double
> next test: yes_really_one_more, offset [0-9a-f]*, has type [0-9a-f]*/long int
> next test: , offset [0-9a-f]*, has type [0-9a-f]*/struct
> +next test: and_finally, offset [0-9a-f]*, has type [0-9a-f]*/int
> +next test: , offset [0-9a-f]*, has type [0-9a-f]*/struct
> next test: , offset [0-9a-f]*, has type [0-9a-f]*/union
> next test: after_the_end, offset [0-9a-f]*, has type [0-9a-f]*/int
More information about the Binutils
mailing list