mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-25 14:01:00 +08:00
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>
This commit is contained in:
parent
83e8a5d39b
commit
fa4fe27537
@ -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;
|
||||
|
@ -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 {};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user