diff options
author | Nick Alcock <nick.alcock@oracle.com> | 2025-02-24 18:11:25 +0000 |
---|---|---|
committer | Nick Alcock <nick.alcock@oracle.com> | 2025-02-28 14:16:42 +0000 |
commit | fa4fe2753730f412c00a8a2bab36550c063dfe95 (patch) | |
tree | cb5dd0b34e23d0cb57668b61fcdd208898c3cb11 /libctf | |
parent | 83e8a5d39be92d052986fe9d687a049db8f9f8c5 (diff) | |
download | binutils-fa4fe2753730f412c00a8a2bab36550c063dfe95.zip binutils-fa4fe2753730f412c00a8a2bab36550c063dfe95.tar.gz binutils-fa4fe2753730f412c00a8a2bab36550c063dfe95.tar.bz2 |
libctf: fix cv-qualified unnamed struct/union field lookup
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.
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.
Tested-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Diffstat (limited to 'libctf')
-rw-r--r-- | libctf/ctf-types.c | 33 | ||||
-rw-r--r-- | libctf/testsuite/libctf-lookup/struct-iteration-ctf.c | 7 | ||||
-rw-r--r-- | libctf/testsuite/libctf-lookup/struct-iteration.c | 18 | ||||
-rw-r--r-- | libctf/testsuite/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 067a5d8..044a185 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 7df67ad..0a50d2c 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 b240864..fd89ca7 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 fd64454..aecffd4 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 |